mirror of
https://github.com/ksherlock/marignotti.git
synced 2024-12-21 23:29:36 +00:00
335 lines
7.4 KiB
C
335 lines
7.4 KiB
C
#include "marignotti.h"
|
|
|
|
#include <string.h>
|
|
#include <misctool.h>
|
|
#include "s16debug.h"
|
|
|
|
|
|
#pragma optimize 79
|
|
#pragma noroot
|
|
|
|
|
|
extern boolean readable(Entry *e);
|
|
|
|
#define TABLE_SIZE 16
|
|
#define TABLE_MASK 15
|
|
static struct Entry *table[TABLE_SIZE];
|
|
|
|
// ipids waiting to close + logout.
|
|
static struct Entry *dlist;
|
|
|
|
static void destroy_entry(Entry *e, Boolean abort);
|
|
|
|
void init_table(void)
|
|
{
|
|
dlist = NULL;
|
|
memset(table, 0, sizeof(table));
|
|
}
|
|
|
|
void destroy_table(void)
|
|
{
|
|
|
|
Entry *e;
|
|
Entry *next;
|
|
unsigned i;
|
|
|
|
for (i = 0; i < TABLE_SIZE; ++i)
|
|
{
|
|
SEI();
|
|
e = table[i];
|
|
table[i] = 0;
|
|
CLI();
|
|
|
|
while (e)
|
|
{
|
|
IncBusy();
|
|
|
|
next = e->next;
|
|
destroy_entry(e, true);
|
|
e = next;
|
|
|
|
DecBusy();
|
|
}
|
|
}
|
|
|
|
e = dlist;
|
|
while (e)
|
|
{
|
|
next = e->next;
|
|
destroy_entry(e, true);
|
|
e = next;
|
|
}
|
|
}
|
|
|
|
static void destroy_entry(Entry *e, Boolean abort)
|
|
{
|
|
if (abort) TCPIPAbortTCP(e->ipid);
|
|
|
|
TCPIPLogout(e->ipid);
|
|
sdelete(e->semaphore);
|
|
free(e);
|
|
}
|
|
|
|
Entry *find_entry(Word ipid)
|
|
{
|
|
Entry *e;
|
|
|
|
IncBusy();
|
|
e = table[ipid & TABLE_MASK];
|
|
|
|
while (e)
|
|
{
|
|
if (e->ipid == ipid) break;
|
|
e = e->next;
|
|
}
|
|
DecBusy();
|
|
|
|
return e;
|
|
}
|
|
|
|
Entry *create_entry(Word ipid)
|
|
{
|
|
Entry *e;
|
|
e = NULL;
|
|
IncBusy();
|
|
e = calloc(sizeof(Entry), 1);
|
|
DecBusy();
|
|
|
|
if (!e) return NULL;
|
|
e->semaphore = screate(0);
|
|
if (e->semaphore < 0)
|
|
{
|
|
IncBusy();
|
|
free(e);
|
|
DecBusy();
|
|
return NULL;
|
|
}
|
|
|
|
e->ipid = ipid;
|
|
e->_OOBINLINE = 1;
|
|
e->_SNDLOWAT = 1024;
|
|
e->_RCVLOWAT = 1;
|
|
|
|
e->select_rd_pid = 0xffff;
|
|
e->select_wr_pid = 0xffff;
|
|
|
|
SEI();
|
|
e->next = table[ipid & TABLE_MASK];
|
|
table[ipid & TABLE_MASK] = e;
|
|
CLI();
|
|
|
|
return e;
|
|
}
|
|
|
|
void process_table(void)
|
|
{
|
|
Word terr;
|
|
Word t;
|
|
LongWord tick;
|
|
|
|
unsigned i;
|
|
Entry *e;
|
|
Entry *next;
|
|
Entry *prev;
|
|
|
|
|
|
for (i = 0; i < TABLE_SIZE; ++i)
|
|
{
|
|
prev = NULL;
|
|
e = table[i];
|
|
while (e)
|
|
{
|
|
Word command;
|
|
next = e->next;
|
|
|
|
|
|
// select.
|
|
// do this first ... a close would invalidate.
|
|
if (e->select_rd_pid != 0xffff)
|
|
{
|
|
if (readable(e))
|
|
{
|
|
Word coll;
|
|
Word pid;
|
|
|
|
SEI()
|
|
|
|
coll = e->select_rd_collision;
|
|
pid = e->select_rd_pid;
|
|
|
|
e->select_rd_pid = 0xffff;
|
|
e->select_rd_collision = 0;
|
|
|
|
CLI()
|
|
if (e->select_fx)
|
|
e->select_fx(coll, pid);
|
|
|
|
if (Debug > 0)
|
|
{
|
|
s16_debug_printf("select/read wakeup.");
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
command = e->command;
|
|
if (command)
|
|
{
|
|
Word expired;
|
|
Word sig;
|
|
Word state;
|
|
|
|
tick = GetTick();
|
|
IncBusy();
|
|
|
|
expired = 0;
|
|
if (e->timeout != 0 && tick > e->timeout)
|
|
expired = 1;
|
|
|
|
terr = TCPIPStatusTCP(e->ipid, &e->sr);
|
|
t = _toolErr;
|
|
if (t) terr = t;
|
|
e->terr = terr;
|
|
|
|
if (Debug > 2)
|
|
{
|
|
s16_debug_printf("- ipid: %d command %d",
|
|
e->ipid, command);
|
|
|
|
s16_debug_srbuff(&e->sr);
|
|
}
|
|
state = e->sr.srState;
|
|
sig = 0;
|
|
|
|
switch(command)
|
|
{
|
|
case kCommandRead:
|
|
// block until data available.
|
|
if (expired
|
|
|| e->sr.srRcvQueued >= e->cookie
|
|
|| e->sr.srRcvQueued >= e->_RCVLOWAT
|
|
|| terr)
|
|
{
|
|
sig = 1;
|
|
}
|
|
break;
|
|
|
|
|
|
case kCommandWrite:
|
|
// block until data sent.
|
|
if (e->sr.srSndQueued <= e->cookie
|
|
|| expired
|
|
|| terr)
|
|
{
|
|
sig = 1;
|
|
}
|
|
break;
|
|
|
|
case kCommandAccept:
|
|
if (e->sr.srAcceptCount > 0)
|
|
{
|
|
sig = 1;
|
|
}
|
|
break;
|
|
|
|
case kCommandConnect:
|
|
// block until connection established.
|
|
if (state >= TCPSESTABLISHED || state == TCPSCLOSED)
|
|
{
|
|
sig = 1;
|
|
}
|
|
if (expired)
|
|
{
|
|
sig = 1;
|
|
}
|
|
break;
|
|
|
|
case kCommandDisconnect:
|
|
// block until connection closed.
|
|
if (state == TCPSCLOSED)
|
|
{
|
|
sig = 1;
|
|
}
|
|
break;
|
|
|
|
case kCommandDisconnectAndLogout:
|
|
|
|
// move to other list
|
|
// since it's no longer a valid fd
|
|
|
|
if (prev)
|
|
{
|
|
prev->next = next;
|
|
}
|
|
else
|
|
{
|
|
table[i] = next;
|
|
}
|
|
|
|
// add to the dlist.
|
|
e->next = dlist;
|
|
dlist = e;
|
|
e = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (sig)
|
|
{
|
|
s16_debug_printf("sending signal to %d", e->semaphore);
|
|
e->command = kCommandNone;
|
|
ssignal(e->semaphore);
|
|
}
|
|
|
|
DecBusy();
|
|
} // e->command
|
|
|
|
|
|
|
|
|
|
if (e) prev = e;
|
|
e = next;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// now process the disconnect list.
|
|
e = dlist;
|
|
prev = NULL;
|
|
while (e)
|
|
{
|
|
next = e->next;
|
|
|
|
IncBusy();
|
|
terr = TCPIPStatusTCP(e->ipid, &e->sr);
|
|
t = _toolErr;
|
|
if (t) terr = t;
|
|
DecBusy();
|
|
|
|
if (e->sr.srState == TCPSCLOSED)
|
|
{
|
|
destroy_entry(e, false);
|
|
|
|
e = NULL;
|
|
// remove..
|
|
if (prev)
|
|
{
|
|
prev->next = next;
|
|
}
|
|
else
|
|
{
|
|
dlist = next;
|
|
}
|
|
}
|
|
|
|
if (e) prev = e;
|
|
e = next;
|
|
}
|
|
|
|
} |