mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 20:42:56 +01:00
Initial version of a simple remote shell for starting cells over the network.
This commit is contained in:
105
repos/ealanos/run/kuori.run
Normal file
105
repos/ealanos/run/kuori.run
Normal file
@@ -0,0 +1,105 @@
|
||||
create_boot_directory
|
||||
import_from_depot [depot_user]/pkg/[drivers_nic_pkg] \
|
||||
|
||||
append config {
|
||||
<config prio_levels="32" verbose="yes">
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
|
||||
<default-route>
|
||||
<service name="Timer"> <child name="timer"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
|
||||
<affinity-space width="64" height="1"/>
|
||||
<default caps="500"/>
|
||||
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="16M"/>
|
||||
<provides> <service name="Timer"/> </provides>
|
||||
</start>
|
||||
|
||||
<start name="drivers" caps="1500" managing_system="yes">
|
||||
<resource name="RAM" quantum="512M"/>
|
||||
<binary name="init"/>
|
||||
<route>
|
||||
<service name="ROM" label="config"> <parent label="drivers.config"/> </service>
|
||||
<service name="Timer"> <child name="timer"/> </service>
|
||||
<service name="Uplink"> <child name="nic_router"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="nic_router" caps="200">
|
||||
<resource name="RAM" quantum="20M"/>
|
||||
<provides>
|
||||
<service name="Nic"/>
|
||||
<service name="Uplink"/>
|
||||
</provides>
|
||||
<config verbose_domain_state="true">
|
||||
|
||||
<policy label_prefix="kuori" domain="downlink"/>
|
||||
<policy label_prefix="drivers" domain="uplink"/>
|
||||
<domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1">
|
||||
<!--
|
||||
<domain name="uplink" interface="192.168.0.2/24" gateway="192.168.0.2" verbose_packets="yes">
|
||||
-->
|
||||
|
||||
<nat domain="downlink"
|
||||
tcp-ports="16384"
|
||||
udp-ports="16384"
|
||||
icmp-ids="16384"/>
|
||||
|
||||
<tcp-forward port="80" domain="downlink" to="10.0.3.55"/>
|
||||
<tcp-forward port="8080" domain="downlink" to="10.0.3.55"/>
|
||||
|
||||
<udp-forward port="7" domain="downlink" to="10.0.3.55"/>
|
||||
<udp-forward port="7070" domain="downlink" to="10.0.3.55"/>
|
||||
|
||||
</domain>
|
||||
|
||||
<domain name="downlink" interface="10.0.3.1/24" verbose_packets="no">
|
||||
|
||||
<dhcp-server ip_first="10.0.3.55" ip_last="10.0.3.55">
|
||||
<dns-server ip="8.8.8.8"/>
|
||||
<dns-server ip="1.1.1.1"/>
|
||||
</dhcp-server>
|
||||
|
||||
<tcp dst="0.0.0.0/0"><permit-any domain="uplink" /></tcp>
|
||||
<udp dst="0.0.0.0/0"><permit-any domain="uplink" /></udp>
|
||||
<icmp dst="0.0.0.0/0" domain="uplink"/>
|
||||
|
||||
</domain>
|
||||
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="kuori" caps="200">
|
||||
<binary name="kuori"/>
|
||||
<resource name="RAM" quantum="512M"/>
|
||||
<route>
|
||||
<service name="Launcher"><local/></service>
|
||||
<service name="Nic"> <child name="nic_router"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
<config dhcp="yes"/>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
append qemu_args " -nographic "
|
||||
append_qemu_nic_args "host=10.0.2.1,dhcpstart=10.0.2.55,hostfwd=tcp::10080-:80,hostfwd=tcp::18080-:8080,hostfwd=udp::10007-:7,hostfwd=udp::17070-:7070"
|
||||
|
||||
build { core init hoitaja timer lib/ld lib/vfs lib/libm lib/libc lib/stdcxx server/nic_router server/nic_uplink app/kuori app/allocating_cell }
|
||||
|
||||
install_config $config
|
||||
build_boot_image [build_artifacts]
|
||||
run_genode_until forever
|
||||
352
repos/ealanos/src/app/kuori/main.cc
Normal file
352
repos/ealanos/src/app/kuori/main.cc
Normal file
@@ -0,0 +1,352 @@
|
||||
#include <base/heap.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <libc/component.h>
|
||||
#include <base/log.h>
|
||||
#include <lwip/lwip_genode_init.h>
|
||||
#include <lwip/nic_netif.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <ealanos/laucher/connection.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace Lwip {
|
||||
extern "C" {
|
||||
#include <lwip/arch.h>
|
||||
#include <lwip/opt.h>
|
||||
#include <lwip/tcp.h>
|
||||
#include <lwip/dns.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ealan::Kuori {
|
||||
using namespace Genode;
|
||||
class Main;
|
||||
}
|
||||
|
||||
class Ealan::Kuori::Main
|
||||
{
|
||||
private:
|
||||
Env &_env;
|
||||
Heap &_heap;
|
||||
|
||||
Ealan::Launcher_connection &_hoitaja;
|
||||
|
||||
struct Wakeup_scheduler : Lwip::Nic_netif::Wakeup_scheduler
|
||||
{
|
||||
Lwip::Nic_netif *nic{nullptr};
|
||||
|
||||
void schedule_nic_server_wakeup() override
|
||||
{
|
||||
nic->wakeup_nic_server();
|
||||
}
|
||||
|
||||
void set_nic(Lwip::Nic_netif *nic)
|
||||
{
|
||||
this->nic = nic;
|
||||
}
|
||||
|
||||
Wakeup_scheduler() = default;
|
||||
} _wakeup_scheduler;
|
||||
|
||||
enum states
|
||||
{
|
||||
NONE = 0,
|
||||
ACCEPTED,
|
||||
RECEIVED,
|
||||
CLOSING
|
||||
};
|
||||
|
||||
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};
|
||||
|
||||
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 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);
|
||||
|
||||
free(s);
|
||||
Lwip::tcp_close(tpcb);
|
||||
}
|
||||
|
||||
static void send(struct Lwip::tcp_pcb *tpcb, struct state *s)
|
||||
{
|
||||
struct Lwip::pbuf *ptr;
|
||||
Lwip::err_t wr_err = Lwip::ERR_OK;
|
||||
|
||||
while ((wr_err == Lwip::ERR_OK) && (s->p != nullptr))
|
||||
{
|
||||
ptr = s->p;
|
||||
|
||||
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;
|
||||
|
||||
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<signed int>(wr_err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void error(void *arg, Lwip::err_t error)
|
||||
{
|
||||
struct state *s;
|
||||
|
||||
LWIP_UNUSED_ARG(error);
|
||||
|
||||
s = static_cast<struct state *>(arg);
|
||||
|
||||
free(s);
|
||||
}
|
||||
|
||||
static Lwip::err_t poll(void *arg, struct Lwip::tcp_pcb *tpcb)
|
||||
{
|
||||
Lwip::err_t rc;
|
||||
struct state *s;
|
||||
|
||||
s = static_cast<struct state *>(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;
|
||||
}
|
||||
|
||||
static Lwip::err_t sent(void *arg, struct Lwip::tcp_pcb *tpcb, [[maybe_unused]] Lwip::u16_t len)
|
||||
{
|
||||
struct state *s;
|
||||
|
||||
s = static_cast<struct state *>(arg);
|
||||
s->retries = 0;
|
||||
|
||||
if (s->p) {
|
||||
Lwip::tcp_sent(tpcb, sent);
|
||||
send(tpcb, s);
|
||||
} else {
|
||||
if (s->state == CLOSING) {
|
||||
close(tpcb, s);
|
||||
}
|
||||
}
|
||||
return Lwip::ERR_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
s = static_cast<struct state *>(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;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
if ((err != Lwip::ERR_OK) || (newpcb == nullptr)) {
|
||||
return Lwip::ERR_VAL;
|
||||
}
|
||||
|
||||
s = static_cast<struct state *>(Lwip::mem_malloc(sizeof(struct state)));
|
||||
if (s) {
|
||||
s->state = ACCEPTED;
|
||||
s->pcb = newpcb;
|
||||
s->retries = 0;
|
||||
s->p = nullptr;
|
||||
|
||||
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);
|
||||
|
||||
rc = Lwip::ERR_OK;
|
||||
|
||||
Genode::log("Accepted new connection from ", const_cast<const char*>(Lwip::ipaddr_ntoa(&newpcb->remote_ip)));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = Lwip::ERR_MEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void init()
|
||||
{
|
||||
listen_socket = Lwip::tcp_new_ip_type(Lwip::IPADDR_TYPE_ANY);
|
||||
|
||||
if (!listen_socket) {
|
||||
Genode::error("Failed to create server socket.");
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
Tcp_connection::kuori = this;
|
||||
|
||||
Genode::log("Kuori v0.1 - Remote shell for EalánOS");
|
||||
}
|
||||
|
||||
Lwip::Nic_netif _netif;
|
||||
|
||||
public:
|
||||
Main(Env &env, Genode::Heap &heap, Xml_node config, Ealan::Launcher_connection &hoitaja) : _env(env), _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<const char *>(p->payload));
|
||||
Xml_node start_node(static_cast<char *>(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<const char*>(p->payload));
|
||||
Genode::log(cell_cfg);
|
||||
_hoitaja.launch(cell_cfg);
|
||||
|
||||
Lwip::pbuf *response_buffer = Lwip::pbuf_alloc(Lwip::PBUF_TRANSPORT, Genode::strlen(msg), Lwip::PBUF_RAM);
|
||||
|
||||
Lwip::pbuf_take(response_buffer, msg, 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, response.length(), Lwip::PBUF_RAM);
|
||||
Lwip::pbuf_take(response_buffer, response.string(), response.length());
|
||||
|
||||
state->p = response_buffer;
|
||||
Tcp_connection::send(tpcb, state);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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 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);
|
||||
}
|
||||
22
repos/ealanos/src/app/kuori/target.mk
Normal file
22
repos/ealanos/src/app/kuori/target.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
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
|
||||
|
||||
CC_OPT += -Wno-error=conversion -Wno-error=effc++
|
||||
LIBS += base libm libc lwip stdcxx
|
||||
Reference in New Issue
Block a user