begin work on netlib
This commit is contained in:
22
src/main.c
22
src/main.c
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
55
src/netlib.c
Normal 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;
|
||||||
77
src/netlib.h
77
src/netlib.h
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user