This commit is contained in:
IonutParau 2025-07-28 20:20:34 +02:00
parent b7ddf9c34e
commit cd02f31368
3 changed files with 162 additions and 5 deletions

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;