#pragma once #include "json.hpp" #include #include #include #include #include namespace sliger::rpc { struct Err { std::string msg; }; template class Res { public: Res(T value) { this->value = value; this->holds_value = true; } Res(Err error) { this->error = error; this->holds_value = false; } auto is_ok() -> bool { return this->holds_value; } auto ok() -> T { return this->value; } auto err() -> Err { return this->error; } private: bool holds_value; T value; Err error; }; class BracketFinder { public: BracketFinder() : layers(0) { } auto feed(int8_t c) { if (c == '{') { this->layers += 1; } else if (c == '}') { this->layers -= 1; } } auto bracket_closed() -> bool { return this->layers == 0; } private: int layers; }; struct Unit { }; class BufferedWriter { public: BufferedWriter(int fd) : fd(fd) { } BufferedWriter(const BufferedWriter&) = delete; BufferedWriter operator=(const BufferedWriter&) = delete; BufferedWriter(BufferedWriter&&) = delete; BufferedWriter operator=(BufferedWriter&&) = delete; ~BufferedWriter() { close(fd); } auto flush() -> Res; auto write(uint8_t byte) -> Res; auto write(std::string message) -> Res; private: static const size_t length = 1024; size_t occupied = 0; uint8_t buffer[length]; int fd; }; namespace { static inline auto create_address(uint16_t port) -> sockaddr_in { return { .sin_family = AF_INET, .sin_port = htons(port), .sin_addr = { .s_addr = inet_addr("127.0.0.1") }, .sin_zero = { 0 }, }; } } /// - load code /// - program input /// - run /// - run debug /// - fwamegwaph option /// - code covewage option /// - fetch fwamegwaph /// - json string /// - fetch code covewage /// - json string /// - fetch stack /// - json string template class RpcServer { public: RpcServer(Functor&& functor) : functor(functor) {}; auto listen() -> Res { int socket; { socket = ::socket(AF_INET, SOCK_STREAM, 0); if (socket < 0) { return Err { .msg = std::format("could not get socket ({})", socket) }; }; } { auto address = create_address(13370); auto err = ::bind(socket, (struct sockaddr*)&address, sizeof(address)); if (err < 0) { close(socket); return Err { .msg = std::format("could not bind ({})", err) }; }; } { auto err = ::listen(socket, 0); if (err < 0) { close(socket); return Err { .msg = std::format("could not listen ({})", err) }; } } while (true) { auto client_address = create_address(13370); socklen_t address_size = sizeof(client_address); int client = ::accept( socket, (struct sockaddr*)&client_address, &address_size); if (client < 0) { close(socket); return Err { .msg = std::format("could not accept ({})", client) }; } const size_t buf_len = 1024; int8_t buffer[buf_len] = {}; auto bracket_finder = BracketFinder(); std::string message = {}; while (true) { ssize_t bytes_read = read(client, buffer, buf_len); if (bytes_read <= 0) { break; } for (size_t i = 0; i < (size_t)bytes_read; ++i) { message += buffer[i]; bracket_finder.feed(buffer[i]); if (!bracket_finder.bracket_closed()) { continue; } auto req = sliger::json::parse_json(message); if (!req.ok()) { auto err = req.err(); auto msg = std::format( "error parsing rpc message: '{}' @ {}:{}\n", err.msg, err.pos.line, err.pos.col); close(client); close(socket); return Err { .msg = msg, }; } auto writer = std::make_unique(client); this->functor(std::move(req.val()), std::move(writer)); message.clear(); break; } } } std::unreachable(); }; private: Functor functor; }; };