mirror of
https://github.com/open-goal/jak-project
synced 2026-08-20 14:24:45 -04:00
common: make a common interface for creating a server socket
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
#include "ReplServer.h"
|
||||
|
||||
#include "common/cross_sockets/XSocket.h"
|
||||
|
||||
#include "third-party/fmt/core.h"
|
||||
#include <common/versions.h>
|
||||
|
||||
// TODO - basically REPL to listen and inject commands into a running REPL
|
||||
// - we will need a C++ side client as well which will let us communicate with the repl via for
|
||||
@@ -8,53 +11,90 @@
|
||||
//
|
||||
// TODO - The server also needs to eventually return the result of the evaluation
|
||||
|
||||
ReplSession::ReplSession(tcp::socket socket, Compiler* repl) : socket_(std::move(socket)) {
|
||||
m_repl = repl;
|
||||
// Known Issues:
|
||||
// - doesn't handle disconnects/reconnects
|
||||
|
||||
void ReplServer::write_on_accept() {
|
||||
ping_response();
|
||||
}
|
||||
|
||||
void ReplSession::start() {
|
||||
fmt::print("[nREPL]: Client Connected!\n\r");
|
||||
do_read();
|
||||
}
|
||||
void ReplServer::read_data() {
|
||||
int desired_size = 1;
|
||||
int got = 0;
|
||||
|
||||
void ReplSession::do_read() {
|
||||
auto self(shared_from_this());
|
||||
socket_.async_read_some(asio::buffer(data_, max_length),
|
||||
[this, self](std::error_code ec, std::size_t length) {
|
||||
if (!ec) {
|
||||
auto input = std::string(data_, length);
|
||||
if (!input.empty()) {
|
||||
m_repl->read_eval_print(input);
|
||||
}
|
||||
// TODO - i think this is kinda a hack, but its to keep the server
|
||||
// cycling
|
||||
do_write(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ReplSession::do_write(std::size_t length) {
|
||||
auto self(shared_from_this());
|
||||
asio::async_write(socket_, asio::buffer(data_, length),
|
||||
[this, self](std::error_code ec, std::size_t /*length*/) {
|
||||
if (!ec) {
|
||||
do_read();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ReplServer::ReplServer(asio::io_context& io_context, Compiler* repl)
|
||||
: acceptor_(io_context, tcp::endpoint(tcp::v4(), repl->m_nrepl_port)), socket_(io_context) {
|
||||
m_repl = repl;
|
||||
m_port = repl->m_nrepl_port;
|
||||
do_accept();
|
||||
}
|
||||
|
||||
void ReplServer::do_accept() {
|
||||
acceptor_.async_accept(socket_, [this](std::error_code ec) {
|
||||
if (!ec) {
|
||||
std::make_shared<ReplSession>(std::move(socket_), this->m_repl)->start();
|
||||
while (got < desired_size) {
|
||||
ASSERT(got + desired_size < buffer_size);
|
||||
int sock = accepted_socket;
|
||||
auto x = read_from_socket(sock, buffer + got, desired_size - got);
|
||||
if (want_exit_callback()) {
|
||||
return;
|
||||
}
|
||||
do_accept();
|
||||
});
|
||||
got += x > 0 ? x : 0;
|
||||
}
|
||||
|
||||
auto* header = (ReplServerHeader*)(buffer);
|
||||
|
||||
lock();
|
||||
|
||||
// get the body of the message
|
||||
desired_size = header->length;
|
||||
got = 0;
|
||||
while (got < desired_size) {
|
||||
ASSERT(got + desired_size < buffer_size);
|
||||
auto x = read_from_socket(accepted_socket, buffer + got, desired_size - got);
|
||||
if (want_exit_callback()) {
|
||||
return;
|
||||
}
|
||||
got += x > 0 ? x : 0;
|
||||
}
|
||||
|
||||
auto* body = (char*)(buffer);
|
||||
|
||||
switch (header->type) {
|
||||
case ReplServerMessageType::PING:
|
||||
ping_response();
|
||||
break;
|
||||
case ReplServerMessageType::EVAL:
|
||||
compile_msg("(repl-help)");
|
||||
break;
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
void ReplServer::send_data(void* buf, u16 len) {
|
||||
lock();
|
||||
if (client_connected) {
|
||||
int bytes_sent = 0;
|
||||
while (bytes_sent < len) {
|
||||
int wrote = write_to_socket(accepted_socket, (char*)(buf) + bytes_sent, len - bytes_sent);
|
||||
bytes_sent += wrote;
|
||||
if (!client_connected || want_exit_callback()) {
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void ReplServer::set_compiler(std::shared_ptr<Compiler> _compiler) {
|
||||
compiler = std::move(_compiler);
|
||||
}
|
||||
|
||||
void ReplServer::ping_response() {
|
||||
u32 versions[2] = {versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR};
|
||||
char* ye = "sanity";
|
||||
lock();
|
||||
write_to_socket(accepted_socket, (char*)&ye, 6);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void ReplServer::compile_msg(const std::string_view& msg) {
|
||||
if (compiler == nullptr) {
|
||||
return;
|
||||
}
|
||||
compiler->lock();
|
||||
compiler->read_eval_print(msg.data());
|
||||
compiler->unlock();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user