Mon 16 Mar 11:09:06 CET 2026
This commit is contained in:
parent
0ce3ca9e74
commit
d402bb4128
200
src/net.h
Normal file
200
src/net.h
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
#ifndef _NET_H
|
||||
#define _NET_H
|
||||
#if HAS_NET > 0
|
||||
/*
|
||||
==== Communication Ports ====
|
||||
Link: Connection between ports
|
||||
|
||||
Logical/virtual ports are buffered async. IO devices:
|
||||
- External access via buffers only,
|
||||
- Internal reading and writing from physical serial channels in the background (via main IO loop).
|
||||
Ports and links between ports operate message-based. VM send messages to port.
|
||||
Serial Channel -> PortReceiver(L) -> AllocateMessage(M) -> Process(M) -> FinalizeMessage(M=
|
||||
VM IN/OUT API via generic INBYTE/OUTBYTE passed to port InByte(M),OutByte(M)
|
||||
Outgoing messages: PortOutByte -> AllocateMessage(M) -> PortRoute(P)
|
||||
INBYTE/OUTBYTE: IO multiplexer: Real file desciptor IO and logical port access …(via port structures and buffers)
|
||||
*/
|
||||
|
||||
#ifndef PORTBUFFERSIZE
|
||||
#define PORTBUFFERSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef EOM
|
||||
#define EOM '\n'
|
||||
#endif
|
||||
|
||||
// Maximal number of ports
|
||||
#ifndef NUMPORTS
|
||||
#define NUMPORTS 4
|
||||
#endif
|
||||
|
||||
#ifndef NETTIMEOUT
|
||||
// rx timeout in ms
|
||||
#define NETTIMEOUT 200
|
||||
#endif
|
||||
|
||||
#define RINGDECR(index,size) index=(index==0?size-1:index-1)
|
||||
#define RINGINCR(index,size) index=((index+1)%size)
|
||||
#define RINGLEN(start,end,size) end<start?end+size-start:end-start+1
|
||||
|
||||
#define MSGRX 0x1000
|
||||
#define MSGTX 0x2000
|
||||
#define MSGTYPEMASK 0x1F
|
||||
#define MSGTYPE(t) t&MSGTYPEMASK
|
||||
#define MSGDIR(t) t&(MSGRX|MSGTX)
|
||||
|
||||
typedef enum {
|
||||
MSGCOMMAND = 1, // ]command[ : one single program line executed immed. if VM is PIDLE
|
||||
MSGPROGRAM, // [program] : one single (multi-line) main program, compiled, reset VM, run
|
||||
MSGPROGRAMPART, // [[program]] : one part of a main program, compiled
|
||||
MSGDATA, // !data! : not passed to VM program, must be processed by host application
|
||||
MSGEVENT, // %event% : raises VM event
|
||||
MSGUSER, // $message$ : passed to VM program, can be processed by ? operator
|
||||
MSGNET, // Prefix control message (for routing), @dx,dy@, @^@, @~@, @*@, @id..@, @locate..@
|
||||
MSGCONSOLE, // #message# : like MSGDATA
|
||||
MSGMAXNUM,
|
||||
MSGSKIP, // A virtual marker that requires a ring buffer wrap around (to bottom of buffer),
|
||||
// i.e., the next message starts at 0 (remaining space cannot hold buffer mapped binary structures, which must be linear in memory)
|
||||
MSGFREE // free message block in rx/tx buffer
|
||||
} message_type_t;
|
||||
|
||||
typedef enum {
|
||||
LDEAD=0,
|
||||
LIDLE,
|
||||
LSTART, // waiting for first message delimiter
|
||||
LPARSING, // processing content of a message
|
||||
LPREEND, // awaiting second message delimiter?
|
||||
LEND // finalize, go to start
|
||||
} port_state_t;
|
||||
|
||||
#if HAS_NET_ROUTING > 0
|
||||
|
||||
/*
|
||||
Message handled by ports (input as well as output), administrative message header stored in rx/tx buffers
|
||||
*/
|
||||
typedef struct {
|
||||
index_t type; //message_type_t
|
||||
index_t start;
|
||||
index_t end; // wrap around in ring buffer?
|
||||
index_t port;
|
||||
} message_t;
|
||||
|
||||
|
||||
/*
|
||||
Network module with extended routing, ingoing (rx) and outgoing (tx) messages are buffered.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Network control message (prefix of another message or stand-alone)
|
||||
It is directly mappend in rx/tx buffer (parsed in place(
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
NCMUP = 'u',
|
||||
NCMDOWN = 'd',
|
||||
NCMMULTICAST = 'm',
|
||||
NCMUNICAST = '1',
|
||||
NCMID = 'i',
|
||||
NCMDELTA = 'D'
|
||||
} control_type_t;
|
||||
|
||||
/*
|
||||
(Optional) Message prefix for routing
|
||||
@u@ | @u,hopx,hopy@
|
||||
@d@ | @d,hopx,hopy@
|
||||
@D,dx,dy,dx0,dy0@
|
||||
@m,range@
|
||||
Some messages have default routing strategies:
|
||||
!! => Up
|
||||
[] => Down (always broadcast)
|
||||
%% => Down (always broadcast)
|
||||
## => Up
|
||||
*/
|
||||
#ifndef MAXNCMARGS
|
||||
#define MAXNCMARGS 8
|
||||
#endif
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
char type; // control_type_t
|
||||
int8_t narg; // number of args
|
||||
int8_t args[MAXNCMARGS]; // dynamic array
|
||||
} message_control_t;
|
||||
|
||||
typedef struct {
|
||||
/* linear buffer */
|
||||
char *rxBuffer;
|
||||
/* ring buffer */
|
||||
char *txBuffer;
|
||||
index_t rxBottom;
|
||||
index_t rxTop; // points to next free message block
|
||||
index_t txBottom;
|
||||
index_t txTop;
|
||||
char busy;
|
||||
index_t rd; // unix: fd
|
||||
index_t wr; // unix: fd
|
||||
port_state_t state; // message parser state
|
||||
message_t *rxCurrent; // currently processed (non-fixed) message
|
||||
message_t *txCurrent;
|
||||
int (**handlers)(); // int foo(port_t *,message_t *)
|
||||
index_t index;
|
||||
} port_t;
|
||||
|
||||
extern port_t **Ports;
|
||||
message_t *CurrentInputMessage[NUMPORTS]; // for PLX ? operator
|
||||
message_t *CurrentOutputMessage[NUMPORTS]; // for PLX ! operator
|
||||
int PortsDown[NUMPORTS],PortsUp[NUMPORTS]; // keep track for up and down ports
|
||||
|
||||
/* if buffer==NULL the rx+tx buffer is allocated, else buffer=char[NUMPORTS*PORTBUFFERSIZE] */
|
||||
void NetInit(int (**handlers)(),port_t **ports, char *buffer);
|
||||
|
||||
message_t *AllocateMessage(port_t *P,message_type_t t);
|
||||
message_t *FinalizeMessage(message_t *m);
|
||||
void FreeMessage(message_t *m);
|
||||
#if HAS_NET_ROUTING > 0
|
||||
int NetControlMessage(port_t *P, char type,index_t a, index_t b);
|
||||
#endif
|
||||
int PortReceiver(port_t *L);
|
||||
/*
|
||||
Read one byte from message
|
||||
*/
|
||||
int PortInByte(message_t *m);
|
||||
/*
|
||||
Add one byte to message
|
||||
*/
|
||||
int PortOutByte(message_t *m, char ch);
|
||||
|
||||
void PrintPortMessages(port_t *L);
|
||||
#else /* ! HAS_NET_ROUTING: NET0 */
|
||||
/* net0: only 1 port */
|
||||
typedef struct {
|
||||
/* shared buffer=[rxBuffer,inputBuffer] */
|
||||
/* linear buffer, grows to top */
|
||||
char *rxBuffer; // all messages not passed to the VM input layer
|
||||
/* circular buffer, grows to bottom, wrap around at PORTBUFFERSIZE/2, reset to high water if top==bottom */
|
||||
char *inputBuffer; // all messages passed to the VM input layer
|
||||
index_t rxBottom;
|
||||
index_t rxTop; // points to next free byte
|
||||
index_t rxStart; // begin of current message in buffer (rx/input)
|
||||
int rxLast; // timestamp of last received char
|
||||
index_t inputBottom;
|
||||
index_t inputTop; // points to next free byte
|
||||
message_type_t rxCurrent; // current received message
|
||||
|
||||
char busy;
|
||||
index_t rd; // unix: fd
|
||||
index_t wr; // unix: fd
|
||||
port_state_t rxState; // receiver message parser state
|
||||
int (**handlers)(); // int foo(port_t *,message_type_t)
|
||||
} port_t;
|
||||
|
||||
extern port_t *Port;
|
||||
/* if buffer==NULL the rx+in buffer is allocated, else buffer=char[NUMPORTS*PORTBUFFERSIZE] */
|
||||
void NetInit(int (**handlers)(),port_t *port, char *buffer);
|
||||
int PortAvailByte(int id);
|
||||
int PortInByte(int id);
|
||||
int PortOutByte(int od, char ch);
|
||||
int PortReceiver();
|
||||
#endif
|
||||
#endif /* !HAS_NET */
|
||||
#endif /* _NET_H */
|
||||
Loading…
Reference in New Issue
Block a user