begin work on netlib

This commit is contained in:
2026-04-11 12:22:20 +02:00
parent 6244a2f7a4
commit d803783f35
5 changed files with 146 additions and 43 deletions

View File

@@ -473,17 +473,17 @@ int main(int argc, char **argv) {
//nn_setTmpAddress(c, nn_getComponentAddress(tmpfs)); //nn_setTmpAddress(c, nn_getComponentAddress(tmpfs));
nn_mountComponent(c, wrappedC, 255); nn_mountComponent(c, wrappedC, 255, false);
nn_mountComponent(c, screen, -1); nn_mountComponent(c, screen, -1, false);
nn_mountComponent(c, ocelotCard, -1); nn_mountComponent(c, ocelotCard, -1, false);
//nn_mountComponent(c, tmpfs, -1); //nn_mountComponent(c, tmpfs, -1, false);
nn_mountComponent(c, keyboard, -1); nn_mountComponent(c, keyboard, -1, false);
nn_mountComponent(c, eepromCard, 0); nn_mountComponent(c, eepromCard, 0, false);
nn_mountComponent(c, managedfs, 1); nn_mountComponent(c, managedfs, 1, false);
nn_mountComponent(c, gpuCard, 2); nn_mountComponent(c, gpuCard, 2, false);
nn_mountComponent(c, testingfs, 3); nn_mountComponent(c, testingfs, 3, false);
nn_mountComponent(c, testDrive, 4); nn_mountComponent(c, testDrive, 4, false);
nn_mountComponent(c, testFlash, 5); nn_mountComponent(c, testFlash, 5, false);
while(true) { while(true) {
if(WindowShouldClose()) break; if(WindowShouldClose()) break;

View File

@@ -1858,7 +1858,7 @@ static nn_Exit nn_pushComponentRemoved(nn_Computer *c, const char *address, cons
return nn_pushSignal(c, 3); return nn_pushSignal(c, 3);
} }
nn_Exit nn_mountComponent(nn_Computer *c, nn_Component *comp, int slot) { nn_Exit nn_mountComponent(nn_Computer *c, nn_Component *comp, int slot, bool silent) {
if(nn_getComponent(c, comp->address) != NULL) return NN_EBADSTATE; if(nn_getComponent(c, comp->address) != NULL) return NN_EBADSTATE;
nn_ComponentEntry ent = { nn_ComponentEntry ent = {
@@ -1870,20 +1870,20 @@ 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); nn_signalComponent(comp, c, NN_CSIGMOUNTED);
if(c->state == NN_RUNNING) { if(c->state == NN_RUNNING && !silent) {
return nn_pushComponentAdded(c, comp->address, comp->type); return nn_pushComponentAdded(c, comp->address, comp->type);
} }
return NN_OK; return NN_OK;
} }
nn_Exit nn_unmountComponent(nn_Computer *c, const char *address) { nn_Exit nn_unmountComponent(nn_Computer *c, const char *address, bool silent) {
nn_Component *comp = nn_getComponent(c, address); nn_Component *comp = nn_getComponent(c, address);
if(comp == NULL) return NN_OK; if(comp == NULL) return NN_OK;
nn_ComponentEntry lookingFor = {.address = address}; nn_ComponentEntry lookingFor = {.address = address};
nn_hashRemove(&c->components, &lookingFor); nn_hashRemove(&c->components, &lookingFor);
nn_Exit e = NN_OK; nn_Exit e = NN_OK;
if(c->state == NN_RUNNING) { if(c->state == NN_RUNNING && !silent) {
e = nn_pushComponentRemoved(c, address, comp->type); e = nn_pushComponentRemoved(c, address, comp->type);
} }
nn_signalComponent(comp, c, NN_CSIGUNMOUNTED); nn_signalComponent(comp, c, NN_CSIGUNMOUNTED);
@@ -1891,6 +1891,24 @@ nn_Exit nn_unmountComponent(nn_Computer *c, const char *address) {
return e; return e;
} }
nn_Exit nn_swapComponents(nn_Computer *c, nn_Component *previous, nn_Component *next, int slot) {
bool silent = false;
if(previous && next) {
// means for reasons beyond our understanding the config changed
silent = nn_strcmp(previous->address, next->address) == 0;
}
nn_Exit e;
if(previous != NULL) {
e = nn_unmountComponent(c, previous->address, silent);
if(e) return e;
}
if(next != NULL) {
e = nn_mountComponent(c, next, slot, silent);
if(e) return e;
}
return NN_OK;
}
static nn_ComponentEntry *nn_getComponentEntry(nn_Computer *c, const char *address) { static nn_ComponentEntry *nn_getComponentEntry(nn_Computer *c, const char *address) {
nn_ComponentEntry ent = { nn_ComponentEntry ent = {
.address = address, .address = address,

View File

@@ -673,13 +673,14 @@ const char *nn_getComponentTypeID(nn_Component *c);
const char *nn_getComponentAddress(nn_Component *c); const char *nn_getComponentAddress(nn_Component *c);
// Adds a component to the computer on a given slot. // Adds a component to the computer on a given slot.
// This will also queue a component_added signal if the computer is in a running state. // This will also queue a component_added signal if the computer is in a running state, unless silent is true.
// If the component already is mounted, an error is returned. // If the component already is mounted, an error is returned.
nn_Exit nn_mountComponent(nn_Computer *c, nn_Component *comp, int slot); nn_Exit nn_mountComponent(nn_Computer *c, nn_Component *comp, int slot, bool silent);
// Removes a component from the computer. // Removes a component from the computer.
// This will also queue a component_removed signal if the computer is in a running state. // This will also queue a component_removed signal if the computer is in a running state, unless silent is true.
// If the component is not mounted, no error is returned. // If the component is not mounted, no error is returned.
nn_Exit nn_unmountComponent(nn_Computer *c, const char *address); nn_Exit nn_unmountComponent(nn_Computer *c, const char *address, bool silent);
nn_Exit nn_swapComponents(nn_Computer *c, nn_Component *previous, nn_Component *next, int slot);
// gets a component by address. Will return NULL if there is none. // gets a component by address. Will return NULL if there is none.
nn_Component *nn_getComponent(nn_Computer *c, const char *address); nn_Component *nn_getComponent(nn_Computer *c, const char *address);
int nn_getComponentSlot(nn_Computer *c, const char *address); int nn_getComponentSlot(nn_Computer *c, const char *address);

55
src/netlib.c Normal file
View File

@@ -0,0 +1,55 @@
#include "netlib.h"
// libm needed, rip
#include <math.h>
const net_NetworkLimits net_defaultLimits = (net_NetworkLimits) {
.maxRadioLifespan = 6000,
.radioSpeed = 10000,
.maxRadioPackets = 4096,
.maxConnections = 128,
.maxHops = 32,
.maxChannel = 128,
};
typedef struct net_Channel {
char *address;
net_Device **devices;
size_t len;
struct net_Channel *prevChannel;
struct net_Channel *nextChannel;
} net_Channel;
typedef struct net_Network {
nn_Universe *universe;
nn_Context *ctx;
nn_Lock *lock;
net_NetworkLimits limits;
net_Device *allDevices;
net_Device *allTicked;
net_Channel *allChannels;
size_t nextMessageID;
size_t nextDiscoverID;
net_RadioPacket *radioPackets;
size_t radioPacketCount;
} net_Network;
typedef struct net_DeviceConn {
net_Device *target;
int slot;
} net_DeviceConn;
typedef struct net_Device {
net_Network *network;
net_Channel *channel;
net_Device *prevDevice;
net_Device *nextDevice;
net_Device *prevTicked;
net_Device *nextTicked;
void *state;
net_Filter *filter;
net_TickFunc *tickFunc;
net_DeviceConn *connections;
size_t connectionLen;
size_t lastMessageID;
size_t lastDiscoverID;
} net_Device;

View File

@@ -6,9 +6,12 @@
// should be sent by computers when they start, // should be sent by computers when they start,
// in order to mount every component accessible // in order to mount every component accessible
#define NET_COMPDISCOVER "componentDiscover" #define NET_COMPDISCOVER "componentDiscover"
#define NET_COMPADDED "componentAdded" #define NET_COMPSWAP "componentSwapped"
#define NET_COMPREMOVED "componentRemoved"
#define NET_OCMESSAGE "modemMessage" #define NET_OCMESSAGE "modemMessage"
// sent when devices with components are disconnected to tell
// computers to recheck accessibility.
// If not, remove the component
#define NET_RECOMPUTE "netRecompute"
#define NET_RADIOMESSAGE "radioMessage" #define NET_RADIOMESSAGE "radioMessage"
typedef struct net_ModemMessageData { typedef struct net_ModemMessageData {
@@ -25,23 +28,34 @@ typedef struct net_RadioMessageData {
char *data; char *data;
} net_RadioMessageData; } net_RadioMessageData;
typedef struct net_ComponentSwappedData {
// if NULL, no component was removed
nn_Component *removed;
// if NULL, no component was added
nn_Component *added;
} net_ComponentSwappedData;
typedef struct net_NetworkLimits { typedef struct net_NetworkLimits {
// maximum radio lifespan in ticks // maximum radio lifespan in ticks
// maxRadioLifespan * radioSpeed is the maximum effective range of radio
size_t maxRadioLifespan; size_t maxRadioLifespan;
// radio speed in coordinates per tick // radio speed in coordinates per tick
double radioSpeed; double radioSpeed;
// maximum connections in a device // max radio packets at one instant
// If it overflows, the oldest is forcefully removed
size_t maxRadioPackets;
// maximum *DIRECT* connections in a device
size_t maxConnections; size_t maxConnections;
// maximum amount of devices in a octo-tree node.
// For efficient wireless comms, the devices are stored in an octo-tree, the 3D version of a quadtree.
size_t maxTreeNodeSize;
// maximum number of hops past which the packet gets dropped. // maximum number of hops past which the packet gets dropped.
// Set to 0 for infinite hops, but then it is possible to stackoverflow. // Set to 0 for infinite hops, but then it is possible to stackoverflow.
size_t maxHops; size_t maxHops;
// maximum amount of devices in a single channel // maximum amount of devices in a single channel
size_t maxChannel; size_t maxChannel;
// TODO: use an RTree, and thus specify the capacity per node
} net_NetworkLimits; } net_NetworkLimits;
extern const net_NetworkLimits net_defaultLimits;
typedef struct net_Network net_Network; typedef struct net_Network net_Network;
typedef struct net_Device net_Device; typedef struct net_Device net_Device;
@@ -59,7 +73,7 @@ typedef struct net_RadioPacket {
size_t expirationTick; size_t expirationTick;
char *data; char *data;
size_t datalen; size_t datalen;
} net_Radiopacket; } net_RadioPacket;
typedef enum net_MessagePropagation { typedef enum net_MessagePropagation {
// direct connections // direct connections
@@ -84,6 +98,7 @@ typedef struct net_Message {
const char *type; const char *type;
void *data; void *data;
size_t hops; size_t hops;
net_MessagePropagation propagation;
union { union {
// for NET_MESSAGE_WIRELESS // for NET_MESSAGE_WIRELESS
size_t range; size_t range;
@@ -102,19 +117,23 @@ typedef void (net_TickFunc)(net_Device *device, size_t tickCount);
net_Network *net_createNetwork(nn_Universe *universe, const net_NetworkLimits *limits); net_Network *net_createNetwork(nn_Universe *universe, const net_NetworkLimits *limits);
void net_destroyNetwork(net_Network *network); void net_destroyNetwork(net_Network *network);
// locks the network. Only one thread may do ANYTHING to this network or its devices
// at the same time
void net_lockNetwork(net_Device *device); void net_lockNetwork(net_Device *device);
void net_unlockNetwork(net_Device *device); void net_unlockNetwork(net_Device *device);
net_Device *net_createDevice(net_Network *network, const char *type, size_t slotCount, net_DevicePosition position); net_Device *net_createDevice(net_Network *network, const char *type, size_t slotCount, net_DevicePosition position);
void net_destroyDevice(net_Device *device); void net_destroyDevice(net_Device *device);
void net_lockDevice(net_Device *device); net_Network *net_getNetworkOf(net_Device *device);
void net_unlockDevice(net_Device *device);
// adds to a channel, will create the channel if it does not exist
nn_Exit net_addToChannel(net_Device *device, const char *channel); nn_Exit net_addToChannel(net_Device *device, const char *channel);
// removes from a channel, will delete the channel if it is empty
void net_removeFromChannel(net_Device *device, const char *channel); void net_removeFromChannel(net_Device *device, const char *channel);
// will automatically give the message an ID and hops count, so don't bother // will automatically give the message an ID and hops count, so don't bother
// this will lock the network for its entire duration // the sender must be set to the correct sender. This is primarily to allow faking senders if need be.
void net_emit(net_Device *device, const net_Message *message); void net_emit(net_Device *device, const net_Message *message);
void net_setDevicePosition(net_Device *device, net_DevicePosition position); void net_setDevicePosition(net_Device *device, net_DevicePosition position);
@@ -125,30 +144,37 @@ void *net_getDeviceState(net_Device *device);
void net_setDeviceFilter(net_Device *device, net_Filter *filter); void net_setDeviceFilter(net_Device *device, net_Filter *filter);
void net_setDeviceTick(net_Device *device, net_TickFunc *tick); void net_setDeviceTick(net_Device *device, net_TickFunc *tick);
void net_tickDevice(net_Device *device); void net_tickDevice(net_Device *device);
// automatically emits a COMPSWAPPED message.
void net_setDeviceComponent(net_Device *device, nn_Component *component); void net_setDeviceComponent(net_Device *device, nn_Component *component);
nn_Component *net_getDeviceComponent(net_Device *device); nn_Component *net_getDeviceComponent(net_Device *device);
size_t net_getDeviceSlotCount(net_Device *device); size_t net_getDeviceSlotCount(net_Device *device);
net_Device *net_getDeviceSlot(net_Device *device, size_t slot); // returns whether there is a direction one-way connection from device to target
// returns -1 if not directly connected bool net_isDirectlyConnectedTo(net_Device *device, net_Device *target);
// returns -1 if not directly connected, but that can also be the slot its on
int net_getSlotOfDevice(net_Device *device, net_Device *target); int net_getSlotOfDevice(net_Device *device, net_Device *target);
// establishes a 1-WAY connection from device to target on a slot. Each slot may only have one, so previous ones are disconnected // does a depth-first-scan to see if a network device b remains accessible from a.
void net_setDeviceSlot(net_Device *device, size_t slot, net_Device *target); // It may be, due to one-way connections, that b is accessible from a but a not from b.
// adds a 1-WAY connection form device to target, but on not slot. bool net_isNetworkDeviceAccessible(net_Device *a, net_Device *b);
nn_Exit net_mountDevice(net_Device *device, net_Device *target); // establishes a 1-WAY connection from device to target on a slot. The target may only be connected once,
// removes ALL 1-WAY connections from device to target // else this will return EBADSTATE.
nn_Exit net_addDeviceSlot(net_Device *device, int slot, net_Device *target);
// removes ALL 1-WAY connections from device to target.
// Also emits a RECOMPUTE for the target
void net_removeDeviceOneWay(net_Device *device, net_Device *target); void net_removeDeviceOneWay(net_Device *device, net_Device *target);
// disconnects the devices both-ways // disconnects the devices both-ways
void net_disconnectDevices(net_Device *deviceA, net_Device *deviceB); void net_disconnectDevices(net_Device *deviceA, net_Device *deviceB);
typedef void (net_Visitor)(net_Network *network, void *state, net_Device *device); typedef void (net_Visitor)(net_Network *network, void *state, net_Device *device);
// gets the network device count // iterates every network device
size_t net_countNetworkDevices(net_Network *network); void net_visitNetworkDevices(net_Network *network, void *state, net_Visitor *visitor);
// get the device, buffer must be big enough for all of them. // iterates every network device that wants to be ticked
// Make sure to call net_countNetworkDevices. void net_visitTickingNetworkDevices(net_Network *network, void *state, net_Visitor *visitor);
// If running stuff on multiple threads, MAKE SURE THE NETWORK IS LOCKED. THIS IS VERY IMPORTANT // visits all devices in a cube with sides of range*2 and origin at origin
void net_getNetworkDevices(net_Network *network, net_Device **devices); void net_visitNetworkDevicesBetween(net_Network *network, net_DevicePosition origin, double range, void *state, net_Visitor *visitor);
// visits all devices connected to a channel
void net_visitNetworkChannel(net_Network *network, const char *devices, void *state, net_Visitor *visitor);
size_t net_getNetworkTickCount(net_Network *network); size_t net_getNetworkTickCount(net_Network *network);
// increase the tick count by 1 // increase the tick count by 1
@@ -157,7 +183,10 @@ void net_incNetworkTickCount(net_Network *network);
// set it to 0 // set it to 0
void net_resetNetworkTickCount(net_Network *network); void net_resetNetworkTickCount(net_Network *network);
void net_spawnRadioPacket(net_Network *network); // Increments the network tick count and iterates over all devices with ticking (using an internal linked list)
void net_tickNetwork(net_Network *network);
void net_spawnRadioPacket(net_Device *sourceDevice, double range, const char *data, size_t len);
size_t net_countRadioPackets(net_Network *network); size_t net_countRadioPackets(net_Network *network);
void net_getRadioPackets(net_Network *network, net_RadioPacket *packets); void net_getRadioPackets(net_Network *network, net_RadioPacket *packets);