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_mountComponent(c, wrappedC, 255);
|
||||
nn_mountComponent(c, screen, -1);
|
||||
nn_mountComponent(c, ocelotCard, -1);
|
||||
//nn_mountComponent(c, tmpfs, -1);
|
||||
nn_mountComponent(c, keyboard, -1);
|
||||
nn_mountComponent(c, eepromCard, 0);
|
||||
nn_mountComponent(c, managedfs, 1);
|
||||
nn_mountComponent(c, gpuCard, 2);
|
||||
nn_mountComponent(c, testingfs, 3);
|
||||
nn_mountComponent(c, testDrive, 4);
|
||||
nn_mountComponent(c, testFlash, 5);
|
||||
nn_mountComponent(c, wrappedC, 255, false);
|
||||
nn_mountComponent(c, screen, -1, false);
|
||||
nn_mountComponent(c, ocelotCard, -1, false);
|
||||
//nn_mountComponent(c, tmpfs, -1, false);
|
||||
nn_mountComponent(c, keyboard, -1, false);
|
||||
nn_mountComponent(c, eepromCard, 0, false);
|
||||
nn_mountComponent(c, managedfs, 1, false);
|
||||
nn_mountComponent(c, gpuCard, 2, false);
|
||||
nn_mountComponent(c, testingfs, 3, false);
|
||||
nn_mountComponent(c, testDrive, 4, false);
|
||||
nn_mountComponent(c, testFlash, 5, false);
|
||||
while(true) {
|
||||
if(WindowShouldClose()) break;
|
||||
|
||||
|
||||
@@ -1858,7 +1858,7 @@ static nn_Exit nn_pushComponentRemoved(nn_Computer *c, const char *address, cons
|
||||
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;
|
||||
|
||||
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;
|
||||
nn_retainComponent(comp);
|
||||
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_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);
|
||||
if(comp == NULL) return NN_OK;
|
||||
nn_ComponentEntry lookingFor = {.address = address};
|
||||
nn_hashRemove(&c->components, &lookingFor);
|
||||
|
||||
nn_Exit e = NN_OK;
|
||||
if(c->state == NN_RUNNING) {
|
||||
if(c->state == NN_RUNNING && !silent) {
|
||||
e = nn_pushComponentRemoved(c, address, comp->type);
|
||||
}
|
||||
nn_signalComponent(comp, c, NN_CSIGUNMOUNTED);
|
||||
@@ -1891,6 +1891,24 @@ nn_Exit nn_unmountComponent(nn_Computer *c, const char *address) {
|
||||
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) {
|
||||
nn_ComponentEntry ent = {
|
||||
.address = address,
|
||||
|
||||
@@ -673,13 +673,14 @@ const char *nn_getComponentTypeID(nn_Component *c);
|
||||
const char *nn_getComponentAddress(nn_Component *c);
|
||||
|
||||
// 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.
|
||||
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.
|
||||
// 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.
|
||||
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.
|
||||
nn_Component *nn_getComponent(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,
|
||||
// in order to mount every component accessible
|
||||
#define NET_COMPDISCOVER "componentDiscover"
|
||||
#define NET_COMPADDED "componentAdded"
|
||||
#define NET_COMPREMOVED "componentRemoved"
|
||||
#define NET_COMPSWAP "componentSwapped"
|
||||
#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"
|
||||
|
||||
typedef struct net_ModemMessageData {
|
||||
@@ -25,23 +28,34 @@ typedef struct net_RadioMessageData {
|
||||
char *data;
|
||||
} 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 {
|
||||
// maximum radio lifespan in ticks
|
||||
// maxRadioLifespan * radioSpeed is the maximum effective range of radio
|
||||
size_t maxRadioLifespan;
|
||||
// radio speed in coordinates per tick
|
||||
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;
|
||||
// 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.
|
||||
// Set to 0 for infinite hops, but then it is possible to stackoverflow.
|
||||
size_t maxHops;
|
||||
// maximum amount of devices in a single channel
|
||||
size_t maxChannel;
|
||||
// TODO: use an RTree, and thus specify the capacity per node
|
||||
} net_NetworkLimits;
|
||||
|
||||
extern const net_NetworkLimits net_defaultLimits;
|
||||
|
||||
typedef struct net_Network net_Network;
|
||||
typedef struct net_Device net_Device;
|
||||
|
||||
@@ -59,7 +73,7 @@ typedef struct net_RadioPacket {
|
||||
size_t expirationTick;
|
||||
char *data;
|
||||
size_t datalen;
|
||||
} net_Radiopacket;
|
||||
} net_RadioPacket;
|
||||
|
||||
typedef enum net_MessagePropagation {
|
||||
// direct connections
|
||||
@@ -84,6 +98,7 @@ typedef struct net_Message {
|
||||
const char *type;
|
||||
void *data;
|
||||
size_t hops;
|
||||
net_MessagePropagation propagation;
|
||||
union {
|
||||
// for NET_MESSAGE_WIRELESS
|
||||
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);
|
||||
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_unlockNetwork(net_Device *device);
|
||||
|
||||
net_Device *net_createDevice(net_Network *network, const char *type, size_t slotCount, net_DevicePosition position);
|
||||
void net_destroyDevice(net_Device *device);
|
||||
void net_lockDevice(net_Device *device);
|
||||
void net_unlockDevice(net_Device *device);
|
||||
net_Network *net_getNetworkOf(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);
|
||||
// removes from a channel, will delete the channel if it is empty
|
||||
void net_removeFromChannel(net_Device *device, const char *channel);
|
||||
|
||||
// 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_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_setDeviceTick(net_Device *device, net_TickFunc *tick);
|
||||
void net_tickDevice(net_Device *device);
|
||||
// automatically emits a COMPSWAPPED message.
|
||||
void net_setDeviceComponent(net_Device *device, nn_Component *component);
|
||||
nn_Component *net_getDeviceComponent(net_Device *device);
|
||||
size_t net_getDeviceSlotCount(net_Device *device);
|
||||
|
||||
net_Device *net_getDeviceSlot(net_Device *device, size_t slot);
|
||||
// returns -1 if not directly connected
|
||||
// returns whether there is a direction one-way connection from device to target
|
||||
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);
|
||||
// establishes a 1-WAY connection from device to target on a slot. Each slot may only have one, so previous ones are disconnected
|
||||
void net_setDeviceSlot(net_Device *device, size_t slot, net_Device *target);
|
||||
// adds a 1-WAY connection form device to target, but on not slot.
|
||||
nn_Exit net_mountDevice(net_Device *device, net_Device *target);
|
||||
// removes ALL 1-WAY connections from device to target
|
||||
// does a depth-first-scan to see if a network device b remains accessible from a.
|
||||
// It may be, due to one-way connections, that b is accessible from a but a not from b.
|
||||
bool net_isNetworkDeviceAccessible(net_Device *a, net_Device *b);
|
||||
// establishes a 1-WAY connection from device to target on a slot. The target may only be connected once,
|
||||
// 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);
|
||||
// disconnects the devices both-ways
|
||||
void net_disconnectDevices(net_Device *deviceA, net_Device *deviceB);
|
||||
|
||||
typedef void (net_Visitor)(net_Network *network, void *state, net_Device *device);
|
||||
|
||||
// gets the network device count
|
||||
size_t net_countNetworkDevices(net_Network *network);
|
||||
// get the device, buffer must be big enough for all of them.
|
||||
// Make sure to call net_countNetworkDevices.
|
||||
// If running stuff on multiple threads, MAKE SURE THE NETWORK IS LOCKED. THIS IS VERY IMPORTANT
|
||||
void net_getNetworkDevices(net_Network *network, net_Device **devices);
|
||||
// iterates every network device
|
||||
void net_visitNetworkDevices(net_Network *network, void *state, net_Visitor *visitor);
|
||||
// iterates every network device that wants to be ticked
|
||||
void net_visitTickingNetworkDevices(net_Network *network, void *state, net_Visitor *visitor);
|
||||
// visits all devices in a cube with sides of range*2 and origin at origin
|
||||
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);
|
||||
// increase the tick count by 1
|
||||
@@ -157,7 +183,10 @@ void net_incNetworkTickCount(net_Network *network);
|
||||
// set it to 0
|
||||
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);
|
||||
void net_getRadioPackets(net_Network *network, net_RadioPacket *packets);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user