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