From cd02f31368413cdace1218b403e620c8c5a40748 Mon Sep 17 00:00:00 2001 From: IonutParau Date: Mon, 28 Jul 2025 20:20:34 +0200 Subject: [PATCH] tunnels --- src/components/loopbackTunnel.c | 54 +++++++++++++++- src/components/tunnel.c | 105 ++++++++++++++++++++++++++++++++ src/neonucleus.h | 8 +-- 3 files changed, 162 insertions(+), 5 deletions(-) diff --git a/src/components/loopbackTunnel.c b/src/components/loopbackTunnel.c index e167b0d..df2f26a 100644 --- a/src/components/loopbackTunnel.c +++ b/src/components/loopbackTunnel.c @@ -1,7 +1,59 @@ #include "../neonucleus.h" +typedef struct nn_loopTunnel_t { + nn_Context ctx; + nn_debugLoopbackNetworkOpts opts; + char wakeup[NN_MAX_WAKEUPMSG]; + nn_size_t wakeupLen; +} nn_loopTunnel_t; + +static void nni_debugTunnel_deinit(nn_loopTunnel_t *t) { + nn_Alloc a = t->ctx.allocator; + nn_deallocStr(&a, t->opts.address); + nn_dealloc(&a, t, sizeof(nn_loopTunnel_t)); +} + +static nn_size_t nni_debugTunnel_getChannel(nn_loopTunnel_t *t, char *buf, nn_errorbuf_t err) { + nn_strcpy(buf, "loopback"); + return 8; +} + +static nn_size_t nni_debugTunnel_getWakeMessage(nn_loopTunnel_t *t, char *buf, nn_errorbuf_t err) { + nn_memcpy(buf, t->wakeup, t->wakeupLen); + return t->wakeupLen; +} + +static nn_size_t nni_debugTunnel_setWakeMessage(nn_loopTunnel_t *t, const char *buf, nn_size_t buflen, nn_bool_t fuzzy, nn_errorbuf_t err) { + if(buflen > NN_MAX_CHANNEL_SIZE) buflen = NN_MAX_CHANNEL_SIZE; + nn_memcpy(t->wakeup, buf, buflen); + t->wakeupLen = buflen; + return buflen; +} + +static void nni_debugTunnel_send(nn_loopTunnel_t *t, nn_value *values, nn_size_t valueCount, nn_errorbuf_t err) { + nn_pushNetworkMessage(t->opts.computer, t->opts.address, "loopback", NN_TUNNEL_PORT, 0, values, valueCount); +} + nn_tunnel *nn_debugLoopbackTunnel(nn_Context *context, nn_debugLoopbackNetworkOpts opts, nn_networkControl control) { - nn_tunnelTable table = {}; + nn_Alloc *alloc = &context->allocator; + + nn_loopTunnel_t *t = nn_alloc(alloc, sizeof(nn_loopTunnel_t)); + t->ctx = *context; + t->opts = opts; + t->opts.address = nn_strdup(alloc, t->opts.address); + t->wakeupLen = 0; + + nn_tunnelTable table = { + .userdata = t, + .deinit = (void *)nni_debugTunnel_deinit, + + .maxValues = opts.maxValues, + .maxPacketSize = opts.maxPacketSize, + .getChannel = (void *)nni_debugTunnel_getChannel, + .getWakeMessage = (void *)nni_debugTunnel_getWakeMessage, + .setWakeMessage = (void *)nni_debugTunnel_setWakeMessage, + .send = (void *)nni_debugTunnel_send, + }; return nn_newTunnel(context, table, control); } diff --git a/src/components/tunnel.c b/src/components/tunnel.c index af41fb7..e746501 100644 --- a/src/components/tunnel.c +++ b/src/components/tunnel.c @@ -42,9 +42,114 @@ void nn_tunnel_destroy(void *_, nn_component *component, nn_tunnel *tunnel) { nn_destroyTunnel(tunnel); } +static void nni_tunnel_maxPacketSize(nn_tunnel *tunnel, void *_, nn_component *component, nn_computer *computer) { + nn_return_integer(computer, tunnel->table.maxPacketSize); +} + +static void nni_tunnel_maxValues(nn_tunnel *tunnel, void *_, nn_component *component, nn_computer *computer) { + nn_return_integer(computer, tunnel->table.maxValues); +} + +static void nni_tunnel_getChannel(nn_tunnel *tunnel, void *_, nn_component *component, nn_computer *computer) { + nn_errorbuf_t err = ""; + char buf[NN_MAX_CHANNEL_SIZE]; + nn_lock(&tunnel->ctx, tunnel->lock); + nn_size_t len = tunnel->table.getChannel(tunnel->table.userdata, buf, err); + nn_unlock(&tunnel->ctx, tunnel->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } + nn_return_string(computer, buf, len); +} + +static void nni_tunnel_getWakeMessage(nn_tunnel *tunnel, void *_, nn_component *component, nn_computer *computer) { + nn_errorbuf_t err = ""; + char buf[NN_MAX_CHANNEL_SIZE]; + nn_lock(&tunnel->ctx, tunnel->lock); + nn_size_t len = tunnel->table.getWakeMessage(tunnel->table.userdata, buf, err); + nn_unlock(&tunnel->ctx, tunnel->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } + nn_return_string(computer, buf, len); +} + +static void nni_tunnel_setWakeMessage(nn_tunnel *tunnel, void *_, nn_component *component, nn_computer *computer) { + nn_size_t buflen; + const char *buf = nn_toString(nn_getArgument(computer, 0), &buflen); + + if(buf == NULL) { + nn_setCError(computer, "invalid wake message"); + return; + } + + if(buflen > NN_MAX_WAKEUPMSG) { + buflen = NN_MAX_WAKEUPMSG; + } + + nn_bool_t fuzzy = nn_toBoolean(nn_getArgument(computer, 1)); // nil is false + + nn_errorbuf_t err = ""; + + nn_lock(&tunnel->ctx, tunnel->lock); + buflen = tunnel->table.setWakeMessage(tunnel->table.userdata, buf, buflen, fuzzy, err); + nn_unlock(&tunnel->ctx, tunnel->lock); + + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } + + nn_return_string(computer, buf, buflen); +} + +static void nni_tunnel_send(nn_tunnel *tunnel, void *_, nn_component *component, nn_computer *computer) { + nn_value vals[tunnel->table.maxValues]; + nn_size_t valLen = nn_getArgumentCount(computer); + + if(valLen > tunnel->table.maxValues) { + nn_setCError(computer, "too many values"); + return; + } + + for(nn_size_t i = 0; i < valLen; i++) { + vals[i] = nn_getArgument(computer, i); + } + + nn_size_t bytesSent = nn_measurePacketSize(vals, valLen); + if(bytesSent > tunnel->table.maxPacketSize) { + nn_setCError(computer, "packet too big"); + return; + } + nn_simulateBufferedIndirect(component, bytesSent, tunnel->ctrl.packetBytesPerTick); + double d = (double)bytesSent / tunnel->table.maxPacketSize; + nn_addHeat(computer, d * tunnel->ctrl.heatPerFullPacket); + nn_removeEnergy(computer, d * tunnel->ctrl.energyPerFullPacket); + + nn_errorbuf_t err = ""; + nn_lock(&tunnel->ctx, tunnel->lock); + tunnel->table.send(tunnel->table.userdata, vals, valLen, err); + nn_unlock(&tunnel->ctx, tunnel->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } + + nn_return_boolean(computer, true); +} + void nn_loadTunnelTable(nn_universe *universe) { nn_componentTable *tunnelTable = nn_newComponentTable(nn_getAllocator(universe), "tunnel", NULL, NULL, (nn_componentDestructor *)nn_tunnel_destroy); nn_storeUserdata(universe, "NN:TUNNEL", tunnelTable); + + nn_defineMethod(tunnelTable, "maxPacketSize", (nn_componentMethod *)nni_tunnel_maxPacketSize, "maxPacketSize(): integer - Returns the maximum size of a packet"); + nn_defineMethod(tunnelTable, "maxValues", (nn_componentMethod *)nni_tunnel_maxValues, "maxValues(): integer - the maximum number of values which can be sent in a packet"); + nn_defineMethod(tunnelTable, "getChannel", (nn_componentMethod *)nni_tunnel_getChannel, "getChannel(): string - Gets the ID of the communications channel of the tunnel. Under normal conditions, there are only 2 cards in the same universe which share this."); + nn_defineMethod(tunnelTable, "getWakeMessage", (nn_componentMethod *)nni_tunnel_getWakeMessage, "getWakeMessage(): string - Returns the current wake message"); + nn_defineMethod(tunnelTable, "setWakeMessage", (nn_componentMethod *)nni_tunnel_setWakeMessage, "setWakeMessage(msg: string[, fuzzy: boolean]): string - Sets the new wake message"); + nn_defineMethod(tunnelTable, "send", (nn_componentMethod *)nni_tunnel_send, "send(...): boolean - Sends a tunnel message. Returns whether it was sent."); } nn_component *nn_addTunnel(nn_computer *computer, nn_address address, int slot, nn_tunnel *tunnel) { diff --git a/src/neonucleus.h b/src/neonucleus.h index fcc86ba..05f6003 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -1017,10 +1017,10 @@ typedef struct nn_tunnelTable { nn_size_t maxValues; nn_size_t maxPacketSize; - nn_bool_t (*send)(void *userdata, nn_value *values, nn_size_t valueCount); - void (*getChannel)(void *userdata, char *buf, nn_size_t *buflen); - void (*getWakeMessage)(void *userdata, char *buf, nn_size_t *buflen); - nn_size_t (*setWakeMessage)(void *userdata, const char *buf, nn_size_t buflen, nn_bool_t fuzzy); + void (*send)(void *userdata, nn_value *values, nn_size_t valueCount, nn_errorbuf_t err); + nn_size_t (*getChannel)(void *userdata, char *buf, nn_errorbuf_t err); + nn_size_t (*getWakeMessage)(void *userdata, char *buf, nn_errorbuf_t err); + nn_size_t (*setWakeMessage)(void *userdata, const char *buf, nn_size_t buflen, nn_bool_t fuzzy, nn_errorbuf_t err); } nn_tunnelTable; typedef struct nn_tunnel nn_tunnel;