mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 09:03:32 +02:00
120 lines
3.4 KiB
C
120 lines
3.4 KiB
C
#include "../neonucleus.h"
|
|
|
|
typedef struct nn_modemLoop {
|
|
nn_Context ctx;
|
|
nn_debugLoopbackNetworkOpts opts;
|
|
nn_size_t *openPorts;
|
|
nn_size_t strength;
|
|
char wakeup[NN_MAX_WAKEUPMSG];
|
|
nn_size_t wakeupLen;
|
|
} nn_modemLoop;
|
|
|
|
void nn_loopModem_deinit(nn_modemLoop *loop) {
|
|
nn_Context ctx = loop->ctx;
|
|
|
|
nn_deallocStr(&ctx.allocator, loop->opts.address);
|
|
nn_dealloc(&ctx.allocator, loop->openPorts, loop->opts.maxOpenPorts * sizeof(nn_size_t));
|
|
nn_dealloc(&ctx.allocator, loop, sizeof(nn_modemLoop));
|
|
}
|
|
|
|
nn_bool_t nn_loopModem_isOpen(nn_modemLoop *loop, nn_size_t port, nn_errorbuf_t err) {
|
|
for(nn_size_t i = 0; i < loop->opts.maxOpenPorts; i++) {
|
|
if(loop->openPorts[i] == port) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
nn_bool_t nn_loopModem_open(nn_modemLoop *loop, nn_size_t port, nn_errorbuf_t err) {
|
|
int slot = -1;
|
|
for(nn_size_t i = 0; i < loop->opts.maxOpenPorts; i++) {
|
|
if(loop->openPorts[i] == NN_PORT_CLOSEALL) {
|
|
slot = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(slot == -1) {
|
|
nn_error_write(err, "too many open ports");
|
|
return false;
|
|
}
|
|
|
|
loop->openPorts[slot] = port;
|
|
|
|
return true;
|
|
}
|
|
|
|
nn_bool_t nn_loopModem_close(nn_modemLoop *loop, nn_size_t port, nn_errorbuf_t err) {
|
|
if(port == NN_PORT_CLOSEALL) {
|
|
for(nn_size_t i = 0; i < loop->opts.maxOpenPorts; i++) loop->openPorts[i] = NN_PORT_CLOSEALL;
|
|
return true;
|
|
}
|
|
|
|
for(nn_size_t i = 0; i < loop->opts.maxOpenPorts; i++) {
|
|
if(loop->openPorts[i] == port) {
|
|
loop->openPorts[i] = NN_PORT_CLOSEALL;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
nn_error_write(err, "port already closed");
|
|
return false;
|
|
}
|
|
|
|
nn_size_t nn_loopModem_getPorts(nn_modemLoop *loop, nn_size_t *ports, nn_errorbuf_t err) {
|
|
nn_size_t len = 0;
|
|
for(nn_size_t i = 0; i < loop->opts.maxOpenPorts; i++) {
|
|
if(loop->openPorts[i] != NN_PORT_CLOSEALL) {
|
|
ports[len] = loop->openPorts[i];
|
|
len++;
|
|
}
|
|
}
|
|
return len;
|
|
}
|
|
|
|
nn_bool_t nn_loopModem_send(nn_modemLoop *loop, nn_address address, nn_size_t port, nn_value *values, nn_size_t valuec, nn_errorbuf_t err) {
|
|
if(address == NULL) {
|
|
// broadcasting, set it to our address
|
|
address = loop->opts.address;
|
|
}
|
|
|
|
// error is discarded as packet loss
|
|
nn_pushNetworkMessage(loop->opts.computer, loop->opts.address, address, port, loop->strength, values, valuec);
|
|
|
|
return true;
|
|
}
|
|
|
|
nn_modem *nn_debugLoopbackModem(nn_Context *context, nn_debugLoopbackNetworkOpts opts, nn_networkControl control) {
|
|
opts.address = nn_strdup(&context->allocator, opts.address);
|
|
nn_modemLoop *m = nn_alloc(&context->allocator, sizeof(nn_modemLoop));
|
|
m->ctx = *context;
|
|
m->opts = opts;
|
|
m->strength = opts.maxStrength;
|
|
m->wakeupLen = 0;
|
|
m->openPorts = nn_alloc(&context->allocator, opts.maxOpenPorts * sizeof(nn_size_t));
|
|
for(nn_size_t i = 0; i < opts.maxOpenPorts; i++) {
|
|
m->openPorts[i] = NN_PORT_CLOSEALL; // used as a NULL port
|
|
}
|
|
nn_modemTable table = {
|
|
.userdata = m,
|
|
.deinit = (void *)nn_loopModem_deinit,
|
|
|
|
.wireless = opts.isWireless,
|
|
.maxValues = opts.maxValues,
|
|
.maxOpenPorts = opts.maxOpenPorts,
|
|
.maxPacketSize = opts.maxPacketSize,
|
|
|
|
.isOpen = (void *)nn_loopModem_isOpen,
|
|
.open = (void *)nn_loopModem_open,
|
|
.close = (void *)nn_loopModem_close,
|
|
.getPorts = (void *)nn_loopModem_getPorts,
|
|
|
|
.send = (void *)nn_loopModem_send,
|
|
|
|
.maxStrength = opts.maxStrength,
|
|
};
|
|
return nn_newModem(context, table, control);
|
|
}
|