new code.

This commit is contained in:
Kelvin Sherlock 2012-05-05 01:08:27 -04:00
parent 94c54160d8
commit c58d6d456d
8 changed files with 805 additions and 4 deletions

165
driver.c Normal file
View File

@ -0,0 +1,165 @@
#include "marignotti.h"
#include <gno/kerntool.h>
#include <errno.h>
#include "net.h"
#pragma noroot
#pragma optimize 79
int block(int sem)
{
int xerrno = 0;
Kswait(sem, &xerrno);
return xerrno;
}
int queue_command(Entry *e, word command, LongWord cookie, LongWord timeout)
{
int xerrno;
SEI();
e->command = kCommandRead;
e->cookie = cookie;
e->timeout = timeout;
CLI();
xerrno = 0;
Kswait(e->semaphore, &xerrno);
return xerrno;
}
#pragma databank 1
int driver(
int socknum, int req,
void *p1, void *p2,
void *p3, void *p4, void *p5)
{
int rv;
Entry *e;
if (req == PRU_ATTACH)
{
return mattach(socknum, p1, p2, p3, p4, p5);
}
e = find_entry(socknum);
if (!e)
{
if (req == PRU_RCVD || req == PRU_SEND)
*(LongWord *)p2 = 0;
return EBADF;
}
switch (req)
{
case PRU_ABORT:
break;
case PRU_ACCEPT:
break;
case PRU_ATTACH:
// KERNsocket(int domain, int type, int protocol, int *ERRNO);
// handled above.
break;
case PRU_BIND:
// KERNbind(int fd, struct sockaddr *my_addr, int addrlen, int *ERRNO)
//return do_bind(socknum, m, m_len, addr, addrlen, rights);
return 0;
break;
case PRU_CONNECT:
// KERNconnect(int fd, struct sockaddr *serv_addr,
// int addrlen, int *ERRNO)
return mconnect(e, p1, p2, p3, p4, p5);
break;
case PRU_CONNECT2:
break;
case PRU_CONTROL:
break;
case PRU_DETACH:
// called from GS/OS
// int SOCKclose(int sock) part 2
DecBusy();
rv = mdetach(e, p1, p2, p3, p4, p5);
IncBusy();
return rv;
break;
case PRU_DISCONNECT:
// called from GS/OS
// int SOCKclose(int sock) part 1
//return do_disconnect(socknum, m, m_len, addr, addrlen, rights);
return 0;
break;
case PRU_LISTEN:
break;
case PRU_PEERADDR:
break;
case PRU_RCVD:
// this may be called from GSOS (in which case IncBusy()
// is in effect
// or from KERNrecvfrom (in which case it isn't).
//
// may block, so be nice.
// SOCKrdwr(struct rwPBlock *pb, word cmd, int sock)
DecBusy();
rv = mread(e, p1, p2, p3, p4, p5);
IncBusy();
return rv;
break;
case PRU_RCVOOB:
break;
case PRU_SEND:
// SOCKrdwr(struct rwPBlock *pb, word cmd, int sock)
// same as above.
DecBusy();
rv = mwrite(e, p1, p2, p3, p4, p5);
IncBusy();
return rv;
break;
case PRU_SENDOOB:
break;
case PRU_SENSE:
break;
case PRU_SHUTDOWN:
break;
case PRU_SOCKADDR:
break;
case PRU_CO_GETOPT:
break;
case PRU_CO_SETOPT:
break;
case PRU_SELECT:
// int SOCKselect(int pid, int fl, int sock)
break;
}
return EINVAL;
}
#pragma databank 0

150
main.c Normal file
View File

@ -0,0 +1,150 @@
#include "marignotti.h"
#include <memory.h>
#include <texttool.h>
#include <misctool.h>
#include <locator.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <gno/gno.h>
#pragma optimize 79
int semID = 0;
Word MyID;
Word QuitFlag;
#pragma databank 0
void signal_handler(int sig, int code)
{
WriteLine("\pWe got signal!");
QuitFlag = 1;
}
void DisplayMessage(const char *string)
{
if (string) WriteLine(string);
}
#pragma databank 0
// startup/shutdown flags.
enum {
kLoaded = 1,
kStarted = 2,
kConnected = 4
};
Word StartUp(displayPtr fx)
{
word status;
word flags = 0;
// TCPIP is an init, not a tool, so it should always
// be loaded.
status = TCPIPStatus();
if (_toolErr)
{
LoadOneTool(54, 0x0300);
if (_toolErr) return -1;
status = 0;
flags |= kLoaded;
}
#if 1
// require 3.0b3
if (TCPIPLongVersion() < 0x03006003)
{
if (fx) fx("Marinetti 3.0b3 is required.");
if (flags & kLoaded)
UnloadOneTool(54);
return -1;
}
#endif
if (!status)
{
TCPIPStartUp();
if (_toolErr) return -1;
flags |= kStarted;
}
status = TCPIPGetConnectStatus();
if (!status)
{
TCPIPConnect(fx);
flags |= kConnected;
}
return flags;
}
void ShutDown(word flags, Boolean force, displayPtr fx)
{
if (flags & kConnected)
{
TCPIPDisconnect(force, fx);
if (_toolErr) return;
}
if (flags & kStarted)
{
TCPIPShutDown();
if (_toolErr) return;
}
if (flags & kLoaded)
{
UnloadOneTool(54);
}
}
int main(int argc, char **argv)
{
int flags;
MyID = MMStartUp();
flags = StartUp(DisplayMessage);
if (flags == -1) exit(1);
semID = screate(1);
InstallNetDriver(driver, 0);
QuitFlag = 0;
signal(SIGQUIT, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGHUP, signal_handler);
// SIGUSR to dump table ala netstat?
while (!QuitFlag)
{
IncBusy();
TCPIPPoll();
DecBusy();
process_table();
asm { cop 0x7f }
}
InstallNetDriver(NULL, 0);
sdelete(semID);
destroy_table();
ShutDown(flags, 0, DisplayMessage);
return 0;
}

View File

@ -1,14 +1,25 @@
CFLAGS += $(DEFINES) -v -w
OBJS = marignotti.o
OBJS = main.o table.o driver.o s16debug.o mattach.o mconnect.o \
mread.o mwrite.o mdetach.o
TARGET = marignotti
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
marignotti.o: marignotti.c net.h
pull:
gopher gopher://192.168.1.117:7070/0/marignotti.c > marignotti.c
s16debug.o: s16debug.c s16debug.h
main.o: main.c marignotti.h
table.o: table.c marignotti.h
driver.o: driver.c marignotti.h net.h
mread.o: mread.c marignotti.h
mwrite.o: mwrite.c marignotti.h
mattach.o: mattach.c marignotti.h
mconnect.o: mconnect.c marignotti.h
mdetach.o: mdetach.c marignotti.h
clean:
$(RM) *.o *.root

97
marignotti.h Normal file
View File

@ -0,0 +1,97 @@
#include <tcpip.h>
#include <gno/gno.h>
enum {
kCommandNone = 0,
kCommandConnect,
kCommandDisconnect,
kCommandDisconnectAndLogout,
kCommandRead,
kCommandWrite,
kCommandAbortAndLogout
};
typedef struct Entry {
struct Entry *next;
Word ipid;
int semaphore;
srBuff sr;
Word terr;
Word command;
LongWord cookie;
LongWord timeout;
// shutdown(2)
unsigned _SHUT_RD:1;
unsigned _SHUT_WR:1;
// fcntl(2)
unsigned _NONBLOCK:1;
//setsockopt(2)
unsigned _OOBINLINE:1;
unsigned _LINGER:1;
unsigned _NOSIGPIPE:1;
LongWord _SNDLOWAT;
LongWord _RCVLOWAT;
Word _RCVTIMEO;
Word _LINGER_SEC;
} Entry;
extern Word MyID;
typedef struct xsockaddr_in {
short sin_family;
unsigned short sin_port;
unsigned long sin_addr;
char sin_zero[8];
} xsockaddr_in;
#define IncBusy() asm { jsl 0xE10064 }
#define DecBusy() asm { jsl 0xE10068 }
#define Resched() asm { cop 0x7f }
#define SEI() asm { sei }
#define CLI() asm { cli }
int block(int sem);
int queue_command(Entry *e, word command, LongWord cookie, LongWord timeout);
void init_table(void);
void destroy_table(void);
void process_table(void);
Entry *find_entry(Word ipid);
Entry *create_entry(Word ipid);
// driver stuff.
int driver(int, int, void *, void *, void *, void *, void *);
int mattach(int ipid, void *p1, void *p2, void *p3, void *p4, void *p5);
int mread(Entry *, void *p1, void *p2, void *p3, void *p4, void *p5);
int mwrite(Entry *, void *p1, void *p2, void *p3, void *p4, void *p5);
int mconnect(Entry *, void *p1, void *p2, void *p3, void *p4, void *p5);
int mbind(Entry *, void *p1, void *p2, void *p3, void *p4, void *p5);
int mdetach(Entry *, void *p1, void *p2, void *p3, void *p4, void *p5);
int mdisconnect(Entry *, void *p1, void *p2, void *p3, void *p4, void *p5);
int mgetsockopt(Entry *, void *p1, void *p2, void *p3, void *p4, void *p5);
int msetsockopt(Entry *, void *p1, void *p2, void *p3, void *p4, void *p5);
int mioctl(Entry *, void *p1, void *p2, void *p3, void *p4, void *p5);

40
mattach.c Normal file
View File

@ -0,0 +1,40 @@
#include "marignotti.h"
#include <gno/kerntool.h>
#include <errno.h>
#include <sys/socket.h>
#pragma noroot
#pragma optimize 79
// better known as socket(2)
int mattach(int type, void *p1, void *p2, void *p3, void *p4, void *p5)
{
Word t;
Word ipid;
Entry *e;
// p2 = selwakeup.
int protocol = *(int *)p3;
if (type != SOCK_STREAM) return ESOCKTNOSUPPORT;
if (protocol != 6) return EPROTONOSUPPORT;
// TODO -- check protocol? 6 = tcp, 1 = icmp, 17 = udp.
IncBusy();
ipid = TCPIPLogin(MyID, 0, 0, 0, 0x0040);
t = _toolErr;
DecBusy();
if (t) return ENETDOWN;
e = create_entry(ipid);
if (!e)
{
TCPIPLogout(ipid);
return ENOMEM;
}
*(Word *)p1 = ipid;
return 0;
}

114
mconnect.c Normal file
View File

@ -0,0 +1,114 @@
#include "marignotti.h"
#include <gno/kerntool.h>
#include <errno.h>
#include <misctool.h>
#pragma noroot
#pragma optimize 79
int mconnect(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
{
Word port;
Word t;
Word terr;
int xerrno;
LongWord timeout;
// todo -- if non-blocking,
// return EINPROGRESS
//
xsockaddr_in *sin = (xsockaddr_in *)p3;
int addrlen = *(int *)p4;
port = sin->sin_port;
asm {
lda <port
xba
sta <port
}
// check if already connected.
IncBusy();
terr = TCPIPStatusTCP(e->ipid, &e->sr);
t = _toolErr;
if (t) terr = t;
DecBusy();
// todo -- if non-blocking,
// return EINPROGRESS first time,
// return EALREADY on subsequent calls.
if (e->sr.srState != TCPSCLOSED)
return EISCONN;
IncBusy();
TCPIPSetNewDestination(e->ipid, sin->sin_addr, port);
t = _toolErr;
DecBusy();
if (t)
{
return ENETDOWN;
}
IncBusy();
terr = TCPIPOpenTCP(e->ipid);
t = _toolErr;
if (t) terr = t;
DecBusy();
// todo -- better errors.
if (terr)
{
return ENETDOWN;
}
timeout = GetTick() + 60 * 30;
for (;;)
{
int xerrno;
int state;
xerrno = queue_command(e, kCommandConnect, 0, timeout);
// hmmm .. should these abort?
if (xerrno == EINTR)
{
IncBusy();
e->command = kCommandNone;
TCPIPAbortTCP(e->ipid);
DecBusy();
return EINTR; // ?
}
if (xerrno) return EIO; // semaphore destroyed?
if (e->command) continue; // reset to 0 if processed.
state = e->sr.srState;
if (state == TCPSESTABLISHED)
return 0;
if (state == TCPSCLOSED)
// todo -- differentiate ECONNREFUSED vs EHOSTUNREACH
return ECONNREFUSED;
if (timeout && timeout > GetTick())
{
IncBusy();
TCPIPAbortTCP(e->ipid);
DecBusy();
return ETIMEDOUT;
}
}
return 0; // should never hit.
}

22
mdetach.c Normal file
View File

@ -0,0 +1,22 @@
#include "marignotti.h"
#include <gno/kerntool.h>
#include <errno.h>
#pragma noroot
#pragma optimize 79
//
int mdetach(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
{
// TODO -- SO_LINGER/SO_LINGER_SEC
SEI();
e->command = kCommandDisconnectAndLogout;
e->cookie = 0;
e->timeout = 0;
CLI();
return 0;
}

202
table.c Normal file
View File

@ -0,0 +1,202 @@
#include "marignotti.h"
#include <string.h>
#include <misctool.h>
#pragma optimize 79
#pragma noroot
#define TABLE_SIZE 16
#define TABLE_MASK 15
static struct Entry *table[TABLE_SIZE];
void init_table(void)
{
memset(table, 0, sizeof(table));
}
void destroy_table(void)
{
Entry *e;
unsigned i;
for (i = 0; i < TABLE_SIZE; ++i)
{
SEI();
e = table[i];
table[i] = 0;
CLI();
while (e)
{
Entry *next;
IncBusy();
next = e->next;
TCPIPAbortTCP(e->ipid);
TCPIPLogout(e->ipid);
sdelete(e->semaphore);
free(e);
e = next;
DecBusy();
}
}
}
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;
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;
tick = GetTick();
for (i = 0; i < TABLE_SIZE; ++i)
{
prev = NULL;
e = table[i];
while (e)
{
next = e->next;
if (e->command)
{
Word expired = 0;
Word sig = 0;
Word state;
IncBusy();
if (e->timeout && tick > e->timeout)
expired = 1;
terr = TCPIPStatusTCP(e->ipid, &e->sr);
t = _toolErr;
if (t) terr = t;
e->terr = terr;
state = e->sr.srState;
switch(e->command)
{
case kCommandRead:
if (e->sr.srRcvQueued >= e->cookie
|| expired
|| terr)
{
sig = 1;
}
break;
case kCommandConnect:
if (state >= TCPSESTABLISHED || state == TCPSCLOSED)
{
sig = 1;
}
break;
case kCommandDisconnect:
if (state == TCPSCLOSED)
{
sig = 1;
}
break;
case kCommandDisconnectAndLogout:
// logout and remove entry.
if (state == TCPSCLOSED)
{
TCPIPLogout(e->ipid);
sdelete(e->semaphore);
free(e);
e = NULL;
if (prev)
{
prev->next = next;
}
else
{
table[i] = next;
}
}
break;
}
if (sig)
{
e->command = kCommandNone;
ssignal(e->semaphore);
}
DecBusy();
} // e->command
e = next;
}
}
}