diff --git a/repos/ealanos/src/app/kuori/main.cc b/repos/ealanos/src/app/kuori/main.cc index f3b787820a..d871cf0b0e 100644 --- a/repos/ealanos/src/app/kuori/main.cc +++ b/repos/ealanos/src/app/kuori/main.cc @@ -1,352 +1,216 @@ -#include -#include -#include +#include "base/attached_ram_dataspace.h" +#include "base/ram_allocator.h" +#include "region_map/region_map.h" +#include "sys/_pthreadtypes.h" +#include "util/xml_node.h" #include -#include -#include -#include -#include +#include +#include +#include +#include -#include +#include +#include +#include -namespace Lwip { - extern "C" { - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include + +#include + +#include "protocol.h" +namespace Ealan { + namespace Kuori { + class Server; } } -namespace Ealan::Kuori { - using namespace Genode; - class Main; -} - -class Ealan::Kuori::Main +static void print(Genode::Output &output, sockaddr_in const &addr) { - private: - Heap &_heap; + Genode::print(output, (ntohl(addr.sin_addr.s_addr) >> 24) & 0xff); + output.out_string("."); + Genode::print(output, (ntohl(addr.sin_addr.s_addr) >> 16) & 0xff); + output.out_string("."); + Genode::print(output, (ntohl(addr.sin_addr.s_addr) >> 8) & 0xff); + output.out_string("."); + Genode::print(output, (ntohl(addr.sin_addr.s_addr) >> 0) & 0xff); + output.out_string(":"); + Genode::print(output, ntohs(addr.sin_port)); +} +class Ealan::Kuori::Server +{ + private: - Ealan::Launcher_connection &_hoitaja; + Libc::Env &_env; + Genode::Attached_rom_dataspace _config_rom {_env, "config"}; + Genode::Xml_node _config{_config_rom.xml()}; + Ealan::Shell::Connection _shell{_env}; - struct Wakeup_scheduler : Lwip::Nic_netif::Wakeup_scheduler - { - Lwip::Nic_netif *nic{nullptr}; + void _die(const char *reason){ perror(reason); _env.parent().exit(1); } - void schedule_nic_server_wakeup() override - { - nic->wakeup_nic_server(); - } + struct handler { + pthread_t *thread; + Server *server; + int cd; + }; - void set_nic(Lwip::Nic_netif *nic) - { - this->nic = nic; - } + char *_config_ptr; - Wakeup_scheduler() = default; - } _wakeup_scheduler; + public: - enum states - { - NONE = 0, - ACCEPTED, - RECEIVED, - CLOSING - }; + using Command = Ealan::Kuori::Package_header::Command; + using Header = Ealan::Kuori::Package_header; + using State = Ealan::Kuori::Package_header::State; - struct state - { - uint8_t state; - uint8_t retries; - struct Lwip::tcp_pcb *pcb; - struct Lwip::pbuf *p; - }; - - Lwip::tcp_pcb *listen_socket; - uint16_t _port{8080}; + + Server(Libc::Env &env) : _env(env) {} - struct Tcp_connection - { - static Main *kuori; - /** - * @brief Free state and lwip objects - * - * @param s - */ - static void free(struct state *s) - { - if (s != nullptr) { - if (s->p) { - Lwip::pbuf_free(s->p); - } - Lwip::mem_free(s); - } - } + static void *handle(void *args) + { + struct handler *h = reinterpret_cast(args); + h->server->handle_connection(h->cd); + delete h->thread; + delete h; - static void close(struct Lwip::tcp_pcb *tpcb, struct state *s) - { - Lwip::tcp_arg(tpcb, nullptr); - Lwip::tcp_sent(tpcb, nullptr); - Lwip::tcp_recv(tpcb, nullptr); - Lwip::tcp_err(tpcb, nullptr); - Lwip::tcp_poll(tpcb, nullptr, 0); + return nullptr; + } - free(s); - Lwip::tcp_close(tpcb); - } + void handle_connection(int cd) + { + Header header; + + while (true) { + int ret = read(cd, &header, sizeof(header)); - static void send(struct Lwip::tcp_pcb *tpcb, struct state *s) - { - struct Lwip::pbuf *ptr; - Lwip::err_t wr_err = Lwip::ERR_OK; + if (!ret) break; - while ((wr_err == Lwip::ERR_OK) && (s->p != nullptr)) - { - ptr = s->p; + if (ret > 0) { + Request request{header.command, header.length, cd}; + Genode::log("size of command: ", sizeof(Command)); + Genode::log("CMD=", static_cast(request.command), " CD=", cd, " LEN=", header.length); + process_request(request); + } + } - wr_err = Lwip::tcp_write(tpcb, ptr->payload, ptr->len, 3); - if (wr_err == Lwip::ERR_OK) { - uint16_t plen; + } - plen = ptr->len; - s->p = ptr->next; + void process_request(Request &request) + { + switch (request.command) { + case Command::BEGIN: + { + + /* Acknowledge the new transaction */ - if (s->p) { - Lwip::pbuf_ref(s->p); - } - Lwip::pbuf_free(ptr); - Lwip::tcp_recved(tpcb, plen); - } else if (wr_err == Lwip::ERR_MEM) { - s->p = ptr; - } else { - Genode::error("Encountered LwIP error code ", static_cast(wr_err)); - } - } - } + Header *ack = new Header {Command::ACK, State::ACCEPT, static_cast(::strlen(_config_ptr)) }; + write(request.cd, ack, sizeof(Header)); - static void error(void *arg, Lwip::err_t error) - { - struct state *s; + /* Send habitat configuration to client */ + write(request.cd, _config_ptr, ::strlen(_config_ptr)); + break; + } - LWIP_UNUSED_ARG(error); + case Command::COMMIT: + { + char *buf = new char[request.length]; + Genode::log("Commit: Awaiting ", request.length, " bytes"); + std::uint32_t bytes = 0; + int rc = 0; - s = static_cast(arg); + while (bytes < request.length) { + rc = read(request.cd, &buf[bytes], request.length); + if (rc == 0) + break; + Genode::log("Read ", rc, " bytes."); + bytes += rc; + } - free(s); - } - static Lwip::err_t poll(void *arg, struct Lwip::tcp_pcb *tpcb) - { - Lwip::err_t rc; - struct state *s; + memcpy(_config_ptr, buf, request.length); + _config_ptr[bytes] = '\0'; - s = static_cast(arg); - if (s) { - if (s->p) { - send(tpcb, s); - } else { - if (s->state == CLOSING) { - close(tpcb, s); - } - } - rc = Lwip::ERR_OK; - } else { - Lwip::tcp_abort(tpcb); - rc = Lwip::ERR_ABRT; - } - return rc; - } + printf("Read new configuration:\n %s\n", _config_ptr); - static Lwip::err_t sent(void *arg, struct Lwip::tcp_pcb *tpcb, [[maybe_unused]] Lwip::u16_t len) - { - struct state *s; + _shell.commit(); + break; + } + default: + { + return; + } + } + } - s = static_cast(arg); - s->retries = 0; + void run() + { + int rc = 0; - if (s->p) { - Lwip::tcp_sent(tpcb, sent); - send(tpcb, s); - } else { - if (s->state == CLOSING) { - close(tpcb, s); - } - } - return Lwip::ERR_OK; - } + Genode::log("Kuori v1.0 - Remote Shell for EalánOS"); - static Lwip::err_t receive(void *arg, struct Lwip::tcp_pcb *tpcb, struct Lwip::pbuf *p, Lwip::err_t err) - { - struct state *s; - Lwip::err_t rc = Lwip::ERR_OK; + Genode::Ram_dataspace_capability cap = _shell.connect(); + Genode::Region_map::Attr attr{}; + attr.writeable = true; - s = static_cast(arg); - - if (!p) { - s->state = CLOSING; - if (!s->p) { - close(tpcb, s); - } else { - send(tpcb, s); - } - rc = Lwip::ERR_OK; - } else if (err != Lwip::ERR_OK) { - rc = err; - } else if (s->state == ACCEPTED) { - s->state = RECEIVED; - kuori->parse_and_launch(tpcb, p, s); - } - else if (s->state == RECEIVED) - { - if (!s->p) { - s->p = p; - kuori->parse_and_launch(tpcb, p, s); - } - else - { - struct Lwip::pbuf *ptr; - ptr = s->p; - Lwip::pbuf_cat(ptr, p); - } - rc = Lwip::ERR_OK; - } - else - { - Lwip::tcp_recved(tpcb, p->tot_len); - Lwip::pbuf_free(p); - rc = Lwip::ERR_OK; - } + _config_ptr = _env.rm().attach(cap, attr).convert( + [&](Genode::Region_map::Range r) { return reinterpret_cast(r.start); }, [&] (Genode::Region_map::Attach_error) { return nullptr; }); - return rc; - } + if (!_config_ptr) _die("Failed mapping habitat config"); - static Lwip::err_t accept([[maybe_unused]] void *arg, struct Lwip::tcp_pcb *newpcb, Lwip::err_t err) - { - Lwip::err_t rc; - struct state *s; + Genode::log("Mapped habitat configuration"); - LWIP_UNUSED_ARG(arg); + printf("%s\n", _config_ptr); + + int const sd = socket(AF_INET, SOCK_STREAM, 0); + if (sd == -1) { _die("socket"); } - if ((err != Lwip::ERR_OK) || (newpcb == nullptr)) { - return Lwip::ERR_VAL; - } + unsigned const port = _config.attribute_value("port", 8080U); - s = static_cast(Lwip::mem_malloc(sizeof(struct state))); - if (s) { - s->state = ACCEPTED; - s->pcb = newpcb; - s->retries = 0; - s->p = nullptr; + sockaddr_in const addr{0, AF_INET, htons(port), {INADDR_ANY}, {INADDR_ANY}}; + sockaddr const *paddr = reinterpret_cast(&addr); - Lwip::tcp_arg(newpcb, s); - Lwip::tcp_recv(newpcb, receive); - Lwip::tcp_err(newpcb, error); - Lwip::tcp_poll(newpcb, poll, 0); - Lwip::tcp_sent(newpcb, sent); + int const on = 1; + rc = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - rc = Lwip::ERR_OK; + if (rc) _die("setsockopt"); - Genode::log("Accepted new connection from ", const_cast(Lwip::ipaddr_ntoa(&newpcb->remote_ip))); - } - else - { - rc = Lwip::ERR_MEM; - } - return rc; - } + rc = bind(sd, paddr, sizeof(addr)); + if (rc == -1) _die("bind"); - }; - - void init() - { - listen_socket = Lwip::tcp_new_ip_type(Lwip::IPADDR_TYPE_ANY); + rc = listen(sd, SOMAXCONN); + if (rc == -1) _die("listen"); - if (!listen_socket) { - Genode::error("Failed to create server socket."); - } + Genode::log("Kuori service up and running."); - Lwip::err_t err; - err = Lwip::tcp_bind(listen_socket, &Lwip::ip_addr_any, _port); - - if (err == Lwip::ERR_OK) { - listen_socket = Lwip::tcp_listen_with_backlog(listen_socket, 255); - Lwip::tcp_accept(listen_socket, Tcp_connection::accept); - } else { - Genode::error("Failed to bind socket."); - } + while (true) { + sockaddr_in caddr; + socklen_t scaddr = sizeof(caddr); + sockaddr *pcaddr = reinterpret_cast(&caddr); - Tcp_connection::kuori = this; + int const cd = accept(sd, pcaddr, &scaddr); + if (cd == -1) _die("accept"); - Genode::log("Kuori v0.1 - Remote shell for EalánOS"); - } + Genode::log("New connection from ", caddr); + struct handler *handler = new struct handler(); + handler->cd = cd; + handler->server = this; + handler->thread = new pthread_t(); - Lwip::Nic_netif _netif; - - public: - Main(Env &env, Genode::Heap &heap, Xml_node config, Ealan::Launcher_connection &hoitaja) : _heap(heap), _hoitaja(hoitaja), _wakeup_scheduler(), _netif(env, _heap, config, _wakeup_scheduler) { - - _wakeup_scheduler.set_nic(&_netif); - init(); - } - - void parse_and_launch(Lwip::tcp_pcb *tpcb, Lwip::pbuf *p, state *state) - { - try { - Genode::log("Parsing input of length ", p->len); - Genode::log(static_cast(p->payload)); - Xml_node start_node(static_cast(p->payload)); - //Genode::log(start_node); - - Genode::String<90> name = start_node.attribute_value("name", Genode::String<90>()); - char msg[120]; - - std::sprintf(msg, "Lauching %s\n", name.string()); - - Genode::String<640> cell_cfg(static_cast(p->payload)); - Genode::log(cell_cfg); - _hoitaja.launch(cell_cfg); - - Lwip::pbuf *response_buffer = Lwip::pbuf_alloc(Lwip::PBUF_TRANSPORT, static_cast(Genode::strlen(msg)), Lwip::PBUF_RAM); - - Lwip::pbuf_take(response_buffer, msg, static_cast(Genode::strlen(msg))); - - state->p = response_buffer; - Tcp_connection::send(tpcb, state); - } - catch (Genode::Xml_attribute::Invalid_syntax) - { - Genode::error("Invalid config supplied."); - Genode::String<100> response("Invalid cell configuration.\n"); - - Lwip::pbuf *response_buffer = Lwip::pbuf_alloc(Lwip::PBUF_TRANSPORT, static_cast(response.length()), Lwip::PBUF_RAM); - Lwip::pbuf_take(response_buffer, response.string(), static_cast(response.length())); - - state->p = response_buffer; - Tcp_connection::send(tpcb, state); - } - } + Genode::String<32> const name {"kuori#", caddr}; + + Libc::pthread_create_from_session(handler->thread, Server::handle, handler, 8*4096, name.string(), &_env.cpu(), _env.cpu().affinity_space().location_of_index(0)); + } + } }; -Ealan::Kuori::Main *Ealan::Kuori::Main::Tcp_connection::kuori; - void Libc::Component::construct(Libc::Env &env) { - Genode::Attached_rom_dataspace _config{env, "config"}; - Genode::Xml_node config = _config.xml(); + static Ealan::Kuori::Server kuori(env); - static Genode::Heap heap{env.ram(), env.rm()}; - - static Timer::Connection timer{env}; - - Lwip::genode_init(heap, timer); - - Genode::Thread *myself = Genode::Thread::myself(); - Genode::Affinity::Location loc = myself->affinity(); - Genode::Affinity affinity(env.cpu().affinity_space(), loc); - - static Ealan::Launcher_connection hoitaja{env, affinity}; - - static Ealan::Kuori::Main kuori(env, heap, config, hoitaja); -} \ No newline at end of file + Libc::with_libc([&]() { + kuori.run(); + }); +} diff --git a/repos/ealanos/src/app/kuori/protocol.h b/repos/ealanos/src/app/kuori/protocol.h new file mode 100644 index 0000000000..0ff417ab16 --- /dev/null +++ b/repos/ealanos/src/app/kuori/protocol.h @@ -0,0 +1,36 @@ +#ifndef __EALANOS__SRC__APP__KUORI__PROTOCOL_H_ +#define __EALANOS__SRC__APP__KUORI__PROTOCOL_H_ + +#include + +namespace Ealan +{ + namespace Kuori + { + using Handle = std::uint16_t; + + struct Package_header { + enum Command { BEGIN, COMMIT, ACK }; + + enum State { + ACCEPT, + FAILED, + SUCCESS, + WAIT + }; + + Command command; + State state; + std::uint32_t length; + }; + + struct Request { + Package_header::Command command; + std::uint32_t length; + int cd; + }; + } + // namespace Kuori +} + +#endif \ No newline at end of file diff --git a/repos/ealanos/src/app/kuori/target.mk b/repos/ealanos/src/app/kuori/target.mk index c1d013067e..ecf98c95ee 100644 --- a/repos/ealanos/src/app/kuori/target.mk +++ b/repos/ealanos/src/app/kuori/target.mk @@ -1,22 +1,8 @@ SRC_CC = main.cc -SRC_CC += vfs.cc printf.cc rand.cc sys_arch.cc TARGET = kuori -LIBPORTS_DIR = $(REP_DIR)/../libports -VFS_DIR = $(LIBPORTS_DIR)/src/lib/vfs/lwip -vpath %.cc $(VFS_DIR) - - -LWIP_PORT_DIR := $(call select_from_ports,lwip) -LWIPDIR := $(LWIP_PORT_DIR)/src/lib/lwip/src -INC_DIR += $(LWIP_PORT_DIR)/include/lwip \ - $(LWIPDIR)/include \ - $(LWIPDIR)/include/ipv4 \ - $(LWIPDIR)/include/api \ - $(LWIPDIR)/include/netif \ - $(LIBPORTS_DIR)/src/lib/lwip/include \ - $(LIBPORTS_DIR)/src/lib/vfs \ - $(LIBPORTS_DIR)/src/lib/vfs/lwip +INC_DIR += $(call select_from_repositories,src/lib/libc) +INC_DIR += $(call select_from_repositories,src/lib/libc)/spec/x86_64 CC_OPT += -Wno-error=conversion -Wno-error=effc++ LIBS += base libm libc lwip stdcxx \ No newline at end of file