initial work on modems

This commit is contained in:
2026-04-06 14:19:29 +02:00
parent 79ae1e13f8
commit b5b9fe4018
2 changed files with 282 additions and 68 deletions

View File

@@ -1023,6 +1023,7 @@ typedef struct nn_Signal {
typedef struct nn_Computer { typedef struct nn_Computer {
nn_ComputerState state; nn_ComputerState state;
nn_Universe *universe; nn_Universe *universe;
nn_Lock *lock;
void *userdata; void *userdata;
char *address; char *address;
char *tmpaddress; char *tmpaddress;
@@ -1126,8 +1127,15 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
c->universe = universe; c->universe = universe;
c->userdata = userdata; c->userdata = userdata;
c->lock = nn_createLock(ctx);
if(c->lock == NULL) {
nn_free(ctx, c, sizeof(nn_Computer));
return NULL;
}
c->address = nn_strdup(ctx, address); c->address = nn_strdup(ctx, address);
if(c->address == NULL) { if(c->address == NULL) {
nn_destroyLock(ctx, c->lock);
nn_free(ctx, c, sizeof(nn_Computer)); nn_free(ctx, c, sizeof(nn_Computer));
return NULL; return NULL;
} }
@@ -1142,6 +1150,7 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
c->callBudget = c->totalCallBudget; c->callBudget = c->totalCallBudget;
if(nn_hashInit(&c->components, maxComponents, ctx, &nn_componentHasher)) { if(nn_hashInit(&c->components, maxComponents, ctx, &nn_componentHasher)) {
nn_destroyLock(ctx, c->lock);
nn_strfree(ctx, c->address); nn_strfree(ctx, c->address);
nn_free(ctx, c, sizeof(nn_Computer)); nn_free(ctx, c, sizeof(nn_Computer));
return NULL; return NULL;
@@ -1163,6 +1172,14 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
return c; return c;
} }
void nn_lockComputer(nn_Computer *computer) {
nn_lock(&computer->universe->ctx, computer->lock);
}
void nn_unlockComputer(nn_Computer *computer) {
nn_unlock(&computer->universe->ctx, computer->lock);
}
static void nn_dropValue(nn_Value val); static void nn_dropValue(nn_Value val);
static nn_ComponentEntry *nn_getInternalComponent(nn_Computer *computer, const char *address) { static nn_ComponentEntry *nn_getInternalComponent(nn_Computer *computer, const char *address) {
@@ -1195,9 +1212,6 @@ void nn_destroyComputer(nn_Computer *computer) {
nn_dropValue(computer->callstack[i]); nn_dropValue(computer->callstack[i]);
} }
for(nn_ComponentEntry *c = nn_hashIterate(&computer->components, NULL); c != NULL; c = nn_hashIterate(&computer->components, c)) { for(nn_ComponentEntry *c = nn_hashIterate(&computer->components, NULL); c != NULL; c = nn_hashIterate(&computer->components, c)) {
if(c->slot >= 0 || (computer->tmpaddress != NULL && nn_strcmp(computer->tmpaddress, c->address))) {
nn_signalComponent(c->comp, computer, NN_CSIGRESET);
}
nn_dropComponent(c->comp); nn_dropComponent(c->comp);
} }
for(size_t i = 0; i < computer->signalCount; i++) { for(size_t i = 0; i < computer->signalCount; i++) {
@@ -1800,6 +1814,7 @@ nn_Exit nn_mountComponent(nn_Computer *c, nn_Component *comp, int slot) {
}; };
if(!nn_hashPut(&c->components, &ent)) return NN_ELIMIT; if(!nn_hashPut(&c->components, &ent)) return NN_ELIMIT;
nn_retainComponent(comp); nn_retainComponent(comp);
nn_signalComponent(comp, c, NN_CSIGMOUNTED);
if(c->state == NN_RUNNING) { if(c->state == NN_RUNNING) {
return nn_pushComponentAdded(c, comp->address, comp->type); return nn_pushComponentAdded(c, comp->address, comp->type);
} }
@@ -1816,6 +1831,7 @@ nn_Exit nn_unmountComponent(nn_Computer *c, const char *address) {
if(c->state == NN_RUNNING) { if(c->state == NN_RUNNING) {
e = nn_pushComponentRemoved(c, address, comp->type); e = nn_pushComponentRemoved(c, address, comp->type);
} }
nn_signalComponent(comp, c, NN_CSIGUNMOUNTED);
nn_dropComponent(comp); nn_dropComponent(comp);
return e; return e;
} }
@@ -4757,41 +4773,39 @@ nn_Component *nn_createScreen(
const nn_Method methods[NN_SCRNUM_COUNT] = { const nn_Method methods[NN_SCRNUM_COUNT] = {
[NN_SCRNUM_ISON] = { [NN_SCRNUM_ISON] = {
"isOn", "isOn",
"function():boolean -- Screen powered?", "function(): boolean - Returns whether the screen is on",
NN_DIRECT}, NN_DIRECT},
[NN_SCRNUM_TURNON] = { [NN_SCRNUM_TURNON] = {
"turnOn", "turnOn",
"function():boolean,boolean -- Turn on", "function(): boolean, boolean - Turn on",
NN_INDIRECT}, NN_INDIRECT},
[NN_SCRNUM_TURNOFF] = { [NN_SCRNUM_TURNOFF] = {
"turnOff", "turnOff",
"function():boolean,boolean -- Turn off", "function(): boolean, boolean - Turn off",
NN_INDIRECT}, NN_INDIRECT},
[NN_SCRNUM_GETASPECTRATIO] = { [NN_SCRNUM_GETASPECTRATIO] = {
"getAspectRatio", "getAspectRatio",
"function():number,number -- Block ratio", "function(): integer, integer - Block ratio",
NN_DIRECT}, NN_DIRECT},
[NN_SCRNUM_GETKEYBOARDS] = { [NN_SCRNUM_GETKEYBOARDS] = {
"getKeyboards", "getKeyboards",
"function():table -- Attached keyboards", "function(): string[] - Gets the keyboards attached to the screen",
NN_DIRECT}, NN_DIRECT},
[NN_SCRNUM_SETPRECISE] = { [NN_SCRNUM_SETPRECISE] = {
"setPrecise", "setPrecise",
"function(on:boolean):boolean" "function(on: boolean): boolean - Enable/disable high-precision mouse events",
" -- High-precision mouse",
NN_DIRECT}, NN_DIRECT},
[NN_SCRNUM_ISPRECISE] = { [NN_SCRNUM_ISPRECISE] = {
"isPrecise", "isPrecise",
"function():boolean -- Precision enabled?", "function():boolean -- Returns whether high-precision mouse events are enabled",
NN_DIRECT}, NN_DIRECT},
[NN_SCRNUM_SETTOUCHINVERTED] = { [NN_SCRNUM_SETTOUCHINVERTED] = {
"setTouchModeInverted", "setTouchModeInverted",
"function(on:boolean):boolean" "function(on: boolean): boolean - Enables/disables inverse touch mode, which changes how the user interacts with the screen",
" -- Invert touch mode",
NN_DIRECT}, NN_DIRECT},
[NN_SCRNUM_ISTOUCHINVERTED] = { [NN_SCRNUM_ISTOUCHINVERTED] = {
"isTouchModeInverted", "isTouchModeInverted",
"function():boolean -- Touch inverted?", "function(): boolean - Returns whether inverse touch mode is enabled",
NN_DIRECT}, NN_DIRECT},
}; };
@@ -5030,7 +5044,9 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
const char *name = nn_depthName(g.depth.oldDepth); const char *name = nn_depthName(g.depth.oldDepth);
if(name == NULL) name = "Unknown"; if(name == NULL) name = "Unknown";
req->returnCount = 1; req->returnCount = 1;
return nn_pushstring(C, name); e = nn_pushstring(C, name);
if(e) return e;
return nn_pushinteger(C, g.depth.oldDepth);
} }
// maxResolution // maxResolution
if(m == NN_GPUNUM_MAXRES) { if(m == NN_GPUNUM_MAXRES) {
@@ -5368,112 +5384,101 @@ nn_Component *nn_createGPU(
const nn_Method methods[NN_GPUNUM_COUNT] = { const nn_Method methods[NN_GPUNUM_COUNT] = {
[NN_GPUNUM_BIND] = { [NN_GPUNUM_BIND] = {
"bind", "bind",
"function(address:string[,reset:boolean])" "function(address: string, reset?:boolean): boolean - Attempts to bind the GPU to a screen",
":boolean -- Bind to screen",
NN_INDIRECT}, NN_INDIRECT},
[NN_GPUNUM_GETSCREEN] = { [NN_GPUNUM_GETSCREEN] = {
"getScreen", "getScreen",
"function():string -- Bound screen address", "function(): string? - Get the bound screen, if any",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_GETBG] = { [NN_GPUNUM_GETBG] = {
"getBackground", "getBackground",
"function():number,boolean -- Current bg", "function(): integer, boolean - Returns the current background, and whether its a palette index",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_SETBG] = { [NN_GPUNUM_SETBG] = {
"setBackground", "setBackground",
"function(color:number[,palette:boolean])" "function(color: integer, palette?: boolean): integer, integer? - Sets the current background, returns the old one",
":number[,number] -- Set bg",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_GETFG] = { [NN_GPUNUM_GETFG] = {
"getForeground", "getForeground",
"function():number,boolean -- Current fg", "function(): integer,boolean - Returns the current foreground, and whether its a plette index",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_SETFG] = { [NN_GPUNUM_SETFG] = {
"setForeground", "setForeground",
"function(color:number[,palette:boolean])" "function(color: integer, palette: boolean): integer, integer? - Sets the current foreground, returns the old one",
":number[,number] -- Set fg",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_GETPALETTE] = { [NN_GPUNUM_GETPALETTE] = {
"getPaletteColor", "getPaletteColor",
"function(index:number):number" "function(index: integer): integer - Returns a color from the palette",
" -- Get palette color",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_SETPALETTE] = { [NN_GPUNUM_SETPALETTE] = {
"setPaletteColor", "setPaletteColor",
"function(index:number,value:number):number" "function(index: integer, value: integer): integer - Changes a color from the palette, returns the old one",
" -- Set palette color",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_MAXDEPTH] = { [NN_GPUNUM_MAXDEPTH] = {
"maxDepth", "maxDepth",
"function():number -- Max color depth", "function(): integer - Returns the maximum supported color depth (by GPU and/or screen)",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_GETDEPTH] = { [NN_GPUNUM_GETDEPTH] = {
"getDepth", "getDepth",
"function():number -- Current depth", "function(): integer - Returns the current depth",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_SETDEPTH] = { [NN_GPUNUM_SETDEPTH] = {
"setDepth", "setDepth",
"function(depth:number):string -- Set depth", "function(depth:integer): string, integer - Change the current depth, returns the name of the old one, and its value",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_MAXRES] = { [NN_GPUNUM_MAXRES] = {
"maxResolution", "maxResolution",
"function():number,number -- Max resolution", "function(): integer, integer - Retuns the maximum supported resolution (by GPU and/or screen)",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_GETRES] = { [NN_GPUNUM_GETRES] = {
"getResolution", "getResolution",
"function():number,number -- Resolution", "function(): integer, integer - Returns the current screen resolution",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_SETRES] = { [NN_GPUNUM_SETRES] = {
"setResolution", "setResolution",
"function(w:number,h:number):boolean" "function(width: integer, height: integer): boolean - Changes the current screen resolution",
" -- Set resolution",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_GETVIEWPORT] = { [NN_GPUNUM_GETVIEWPORT] = {
"getViewport", "getViewport",
"function():number,number -- Viewport size", "function(): integer, integer - Get the current viewport, the region of the screen that can actually be seen",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_SETVIEWPORT] = { [NN_GPUNUM_SETVIEWPORT] = {
"setViewport", "setViewport",
"function(w:number,h:number):boolean" "function(width: integer, height: integer): boolean - Change the viewport to a new size",
" -- Set viewport",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_GET] = { [NN_GPUNUM_GET] = {
"get", "get",
"function(x:number,y:number):string," "function(x: integer, y: integer): string, integer, integer, integer?, integer? - Get the character, foreground, background, foreground index and "
"number,number,number?,number? -- Read pixel", "background index of a pixel",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_SET] = { [NN_GPUNUM_SET] = {
"set", "set",
"function(x:number,y:number,s:string" "function(x: integer, y: integer, s: string, vertical?: boolean): boolean - Set a horizontal/vertical line of text at a given (x,y) coordinate.",
"[,vertical:boolean]):boolean -- Write text",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_COPY] = { [NN_GPUNUM_COPY] = {
"copy", "copy",
"function(x,y,w,h,tx,ty):boolean" "function(x: integer, y: integer, w: integer, h: integer, tx: integer, ty: integer): boolean - Copy a region on the screen. (tx, ty) is relative "
" -- Copy region", "to the top-left corner",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_FILL] = { [NN_GPUNUM_FILL] = {
"fill", "fill",
"function(x,y,w,h,char):boolean" "function(x: integer, y: integer, w: integer, h: integer, char: string): boolean - Fill a rectangle with a specific character",
" -- Fill region",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_GETACTIVEBUF] = { [NN_GPUNUM_GETACTIVEBUF] = {
"getActiveBuffer", "getActiveBuffer",
"function():number -- Active buffer index", "function(): integer - Get the current active buffer index, 0 means the bound screen. May return 0 even when there is no screen",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_SETACTIVEBUF] = { [NN_GPUNUM_SETACTIVEBUF] = {
"setActiveBuffer", "setActiveBuffer",
"function(index:number):number" "function(index: integer): integer - Set the active buffer, returns the old one",
" -- Set active buffer",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_BUFFERS] = { [NN_GPUNUM_BUFFERS] = {
"buffers", "buffers",
"function():table -- List buffer indices", "function(): integer[] - Returns the list of VRAM buffers; this never includes 0, as it is the screen",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_ALLOCBUF] = { [NN_GPUNUM_ALLOCBUF] = {
"allocateBuffer", "allocateBuffer",
"function([w:number,h:number]):number" "function(width: integer, height: integer): integer - Allocate a new VRAM buffer",
" -- Allocate VRAM page",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_FREEBUF] = { [NN_GPUNUM_FREEBUF] = {
"freeBuffer", "freeBuffer",
@@ -5486,21 +5491,20 @@ nn_Component *nn_createGPU(
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_TOTALMEM] = { [NN_GPUNUM_TOTALMEM] = {
"totalMemory", "totalMemory",
"function():number -- Total VRAM", "function(): integer - Returns the VRAM capacity, in pixels",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_FREEMEM] = { [NN_GPUNUM_FREEMEM] = {
"freeMemory", "freeMemory",
"function():number -- Free VRAM", "function(): integer - Returns the amount of unused VRAM, in pixels",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_GETBUFSIZE] = { [NN_GPUNUM_GETBUFSIZE] = {
"getBufferSize", "getBufferSize",
"function([index:number]):number,number" "function(index?: integer): integer, integer - Returns buffer dimensions",
" -- Buffer dimensions",
NN_DIRECT}, NN_DIRECT},
[NN_GPUNUM_BITBLT] = { [NN_GPUNUM_BITBLT] = {
"bitblt", "bitblt",
"function([dst,col,row,w,h,src,fc,fr])" "function(dst: integer, col: integer, row:integer, width:integer, height: integer, src: integer, fromCol: integer, fromRow: integer): boolean - "
":boolean -- Blit between buffers", "Copy from buffer to buffer, buffer to screen or screen to buffer",
NN_DIRECT}, NN_DIRECT},
}; };
@@ -5522,3 +5526,101 @@ nn_Component *nn_createGPU(
nn_setComponentHandler(c, nn_gpuHandler); nn_setComponentHandler(c, nn_gpuHandler);
return c; return c;
} }
typedef enum nn_ModemNum {
NN_MODEMNUM_ISWIRED,
NN_MODEMNUM_ISWIRELESS,
NN_MODEMNUM_MAXPACKETSIZE,
NN_MODEMNUM_MAXVALUES,
NN_MODEMNUM_GETSTRENGTH,
NN_MODEMNUM_SETSTRENGTH,
NN_MODEMNUM_MAXSTRENGTH,
NN_MODEMNUM_ISOPEN,
NN_MODEMNUM_OPEN,
NN_MODEMNUM_CLOSE,
NN_MODEMNUM_GETPORTS,
NN_MODEMNUM_SEND,
NN_MODEMNUM_BROADCAST,
NN_MODEMNUM_COUNT,
} nn_ModemNum;
typedef struct nn_ModemState {
nn_Context *ctx;
nn_Modem modem;
nn_ModemHandler *handler;
} nn_ModemState;
static nn_Exit nn_modemHandler(nn_ComponentRequest *req) {
nn_Context *ctx = req->ctx;
nn_ModemState *state = req->classState;
nn_Computer *C = req->computer;
bool isWired = state->modem.isWired;
bool isWireless = state->modem.maxRange > 0;
nn_ModemNum method = req->methodIdx;
if(req->action == NN_COMP_CHECKMETHOD) {
if(method == NN_MODEMNUM_GETSTRENGTH || method == NN_MODEMNUM_SETSTRENGTH || method == NN_MODEMNUM_MAXSTRENGTH) {
req->methodEnabled = isWireless;
return NN_OK;
}
return NN_OK;
}
nn_ModemRequest mreq;
mreq.ctx = ctx;
mreq.computer = C;
mreq.state = req->state;
mreq.modem = &state->modem;
mreq.localAddress = req->compAddress;
if(C) nn_setError(C, "modem: not implemented yet");
return NN_EBADCALL;
}
nn_Component *nn_createModem(nn_Universe *universe, const char *address, const nn_Modem *modem, void *state, nn_ModemHandler *handler) {
nn_Component *c = nn_createComponent(
universe, address, "gpu");
if(c == NULL) return NULL;
const nn_Method methods[NN_MODEMNUM_COUNT] = {
[NN_MODEMNUM_ISWIRED] = {"isWired", "function(): boolean - Returns whether the modem supports wired connectivity", NN_DIRECT},
[NN_MODEMNUM_ISWIRELESS] = {"isWireless", "function(): boolean - Returns whether the modem supports wireless connectivity", NN_DIRECT},
[NN_MODEMNUM_MAXPACKETSIZE] = {"maxPacketSize", "function(): integer - Returns the maximum logical packet size", NN_DIRECT},
[NN_MODEMNUM_MAXVALUES] = {"maxValues", "function(): integer - Returns the maximum amount of values", NN_DIRECT},
[NN_MODEMNUM_GETSTRENGTH] = {"getStrength", "function(): integer - Returns the range of wireless message", NN_DIRECT},
[NN_MODEMNUM_SETSTRENGTH] = {"setStrength", "function(strength: integer): integer - Changes the wireless signal strength", NN_INDIRECT},
[NN_MODEMNUM_MAXSTRENGTH] = {"maxStrength", "function(): integer - Returns the maximum strength of wireless messages", NN_DIRECT},
[NN_MODEMNUM_ISOPEN] = {"isOpen", "function(port: integer): boolean - Returns whether a port is open", NN_DIRECT},
[NN_MODEMNUM_OPEN] = {"open", "function(port: integer): boolean - Open a port", NN_DIRECT},
[NN_MODEMNUM_CLOSE] = {"close", "function(port?: integer): boolean - Close a port, or all ports if none specified", NN_DIRECT},
[NN_MODEMNUM_GETPORTS] = {"getOpenPorts", "function(): integer[] - Returns a list of all open ports", NN_DIRECT},
[NN_MODEMNUM_SEND] = {"send", "function(targetAddress: string, port: integer, ...): boolean - Send a packet", NN_INDIRECT},
[NN_MODEMNUM_BROADCAST] = {"broadcast", "function(port: integer, ...): boolean - Broadcast a packet", NN_INDIRECT},
};
nn_Exit e = nn_setComponentMethodsArray(
c, methods, NN_MODEMNUM_COUNT);
if(e) { nn_dropComponent(c); return NULL; }
nn_Context *ctx = &universe->ctx;
nn_ModemState *cls = nn_alloc(ctx, sizeof(*cls));
if(cls == NULL) {
nn_dropComponent(c);
return NULL;
}
cls->ctx = ctx;
cls->modem = *modem;
cls->handler = handler;
nn_setComponentState(c, state);
nn_setComponentClassState(c, cls);
nn_setComponentHandler(c, nn_modemHandler);
return c;
}

View File

@@ -408,6 +408,8 @@ extern size_t nn_ramSizes[8];
nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char *address, size_t totalMemory, size_t maxComponents, size_t maxDevices); nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char *address, size_t totalMemory, size_t maxComponents, size_t maxDevices);
// Destroys the state, effectively shutting down the computer. // Destroys the state, effectively shutting down the computer.
void nn_destroyComputer(nn_Computer *computer); void nn_destroyComputer(nn_Computer *computer);
void nn_lockComputer(nn_Computer *computer);
void nn_unlockComputer(nn_Computer *computer);
// get the userdata pointer // get the userdata pointer
void *nn_getComputerUserdata(nn_Computer *computer); void *nn_getComputerUserdata(nn_Computer *computer);
const char *nn_getComputerAddress(nn_Computer *computer); const char *nn_getComputerAddress(nn_Computer *computer);
@@ -571,9 +573,10 @@ typedef struct nn_Method {
// component signals // component signals
// tells the component to reset its state // mounted
// sent to the components with slot >= 0 and to tmpfs when computer state is dropped #define NN_CSIGMOUNTED "mounted"
#define NN_CSIGRESET "reset" // unmounted
#define NN_CSIGUNMOUNTED "unmounted"
typedef enum nn_ComponentAction { typedef enum nn_ComponentAction {
// component dropped // component dropped
@@ -1529,6 +1532,122 @@ nn_Component *nn_createScreen(
nn_ScreenHandler *handler nn_ScreenHandler *handler
); );
typedef struct nn_Modem {
// maximum range. Set to 0 for non-wireless modems
size_t maxRange;
// maximum values in a packet
size_t maxValues;
// maximum logical packet size. Note that the encoding is more efficient than the packet size algorithm estimates
size_t maxPacketSize;
// the maximum amount of open ports
size_t maxOpenPorts;
// whether the modem supports wired connectivity.
// Support for wireless checks if maxRange > 0.
bool isWired;
// base energy cost of 1 network message
double basePacketCost;
// energy cost of a full packet, at the maximum logical size
double fullPacketCost;
// energy cost per wireless packet strength level
double costPerStrength;
} nn_Modem;
// A buffer with encoded values
typedef struct nn_EncodedNetworkContents {
nn_Context *ctx;
char *buf;
size_t buflen;
size_t valueCount;
} nn_EncodedNetworkContents;
extern nn_Modem nn_defaultWiredModem;
extern nn_Modem nn_defaultWirelessModems[2];
typedef enum nn_ModemAction {
// modem dropped
NN_MODEM_DROP,
// modem mounted to a computer, meant to bind
NN_MODEM_MOUNTED,
// modem unmounted to a computer, meant to unbind
NN_MODEM_UNMOUNTED,
// check whether a port is open
NN_MODEM_ISOPEN,
// open a port
NN_MODEM_OPEN,
// close a port
NN_MODEM_CLOSE,
// get open ports
NN_MODEM_GETPORTS,
// send/broadcast a message
NN_MODEM_SEND,
// get current modem strength
NN_MODEM_GETSTRENGTH,
// returns the wake message
NN_MODEM_GETWAKEMESSAGE,
// set the wake message
NN_MODEM_SETWAKEMESSAGE,
} nn_ModemAction;
typedef struct nn_ModemRequest {
nn_Context *ctx;
nn_Computer *computer;
void *state;
const nn_Modem *modem;
const char *localAddress;
nn_ModemAction action;
union {
struct {
size_t port;
bool opened;
} isOpen;
size_t openPort;
// NN_CLOSEPORTS means close all
size_t closePort;
struct {
// store the port numbers in this buffer
size_t *activePorts;
// the amount of active ports.
// the initial value is the capacity of activePorts
size_t len;
} getPorts;
struct {
const nn_EncodedNetworkContents *contents;
// NULL for broadcast
const char *address;
size_t port;
} send;
// for getStrength, setStrength.
size_t strength;
struct {
char *buf;
size_t len;
bool isFuzzy;
} getWake;
struct {
const char *buf;
size_t len;
bool isFuzzy;
} setWake;
};
} nn_ModemRequest;
typedef nn_Exit (nn_ModemHandler)(nn_ModemRequest *req);
nn_Component *nn_createModem(nn_Universe *universe, const char *address, const nn_Modem *modem, void *state, nn_ModemHandler *handler);
typedef struct nn_Tunnel {
// maximum range. Set to 0 for wired modems
size_t maxRange;
// maximum values in a packet
size_t maxValues;
// maximum logical packet size. Note that the encoding is more efficient than the packet size algorithm estimates
size_t maxPacketSize;
// the maximum amount of open ports
size_t maxOpenPorts;
} nn_Tunnel;
extern nn_Tunnel nn_defaultTunnel;
// Colors and palettes. // Colors and palettes.
// Do note that the // Do note that the
@@ -1778,13 +1897,6 @@ nn_Exit nn_pushRedstoneChanged(nn_Computer *computer, const char *redstoneAddres
// entityName can be NULL if the entity has no name. // entityName can be NULL if the entity has no name.
nn_Exit nn_pushMotion(nn_Computer *computer, double relX, double relY, double relZ, const char *entityName); nn_Exit nn_pushMotion(nn_Computer *computer, double relX, double relY, double relZ, const char *entityName);
typedef struct nn_EncodedNetworkContents {
nn_Context *ctx;
char *buf;
size_t buflen;
size_t valueCount;
} nn_EncodedNetworkContents;
// applies basic encoding to a network message. This encoding has a header, and thus should remain backwards-compatible. // applies basic encoding to a network message. This encoding has a header, and thus should remain backwards-compatible.
// The encoding serves 2 purposes: // The encoding serves 2 purposes:
// 1. Prevent shared memory between computers. Values do not use atomic reference counting, and thus this could lead to UAF or memory leaks. // 1. Prevent shared memory between computers. Values do not use atomic reference counting, and thus this could lead to UAF or memory leaks.