diff --git a/marignotti.c b/marignotti.c deleted file mode 100644 index 566f7fc..0000000 --- a/marignotti.c +++ /dev/null @@ -1,1049 +0,0 @@ -/* - * MariGNOtti - * - */ - -#pragma optimize 79 - -#include -#include -#include -#include -#include - -#include -#include -#include - -//#include -#include -#include -#include -#include -#include -#include -#include - -//#include - -#include "net.h" - -volatile int QuitFlag; -static Word MyID; -int semID; - - -// this will be used to hold extra info (sockopts, etc) -// as well as to keep a list of ipids waiting to close. - -struct flags { - // shutdown(2) - Word _SHUT_RD:1; - Word _SHUT_WR:1; - - // fcntl(2) - Word _NONBLOCK:1; - - // setsockopt() - Word _OOBINLINE:1; - Word _LINGER:1; - Word _NOSIGPIPE:1; - -}; - -typedef struct ipidHash { - Word ipid; - struct flags flags; - - Word _SNDLOWAT; - Word _RCVLOWAT; - - struct ipidHash *next; -} ipidHash; - -ipidHash *htable[64] = { }; - -ipidHash *dlist = NULL; - - -ipidHash *findIpidHash(Word ipid) -{ - ipidHash *e; - - e = htable[ipid & (64 - 1)]; - - while (e) - { - if (e->ipid == ipid) return e; - e = e->next; - } - - return NULL; -} - -// not yet sure what this is for... -typedef void (*selwakeup)(int col_flag, int pid); - -void debug_str(const char *cp) -{ - - static Word Sweet16 = -1; - - - if (Sweet16 == -1) - { - //volatile char *ereg = (char *)0x00c04f; - /* - // Apple II tech note 201 - */ - word emu_id = 0; - word emu_version = 0; - asm { - // the lda ..,x is to prevent - // the 2nd read from being optimized out. - //brk 0xea - lda #0 - ldx #0 - sep #0x20 - sta >0x00c04f,x - lda >0x00c04f,x - sta 0x00c04f,x - sta = 0x23) Sweet16 = 1; - else Sweet16 = 0; - - //*EMUBYTE = 0; - //if (*EMUBYTE == 0x16) Sweet16 = 1; - //else Sweet16 = 0; - #undef EMUBYTE - } - - if (Sweet16 == 0) return; - - asm { - ldx length) l = length; - - memset(buffer, ' ', sizeof(buffer)); - - for (i = 0, j = 0; i < l; ++i) - { - unsigned x = bytes[i]; - buffer[j++] = HexMap[x >> 4]; - buffer[j++] = HexMap[x & 0x0f]; - j++; - if (i == 7) j++; - - buffer[50 + i] = isascii(x) && isprint(x) ? x : '.'; - } - - buffer[50 + 16 + 1] = 0; - debug_str(buffer); - - length -= l; - bytes += l; - } - -} - -void dump_srbuff(const srBuff *sb) -{ -static char buffer[128]; - - sprintf(buffer, "%04x %04x %08lx %08lx %08lx %04x %04x %04x", - sb->srState, - sb->srNetworkError, - sb->srSndQueued, - sb->srRcvQueued, - sb->srDestIP, - sb->srDestPort, - sb->srConnectType, - sb->srAcceptCount - ); - - debug_str(buffer); - -} - -int do_attach( - int socknum, - void *m, size_t *m_len, - struct sockaddr *addr, int *addrlen, - void *rights -) -{ - // returns errno or 0. - Word ipid; - ipidHash *e; - - int type = socknum; - int *sockptr = (int *)m; - selwakeup *fx = (selwakeup *)m_len; - int *protocol = (int *)addr; - - //WriteLine("\pdo_attach"); - debug_str("do_attach"); - - if (type != SOCK_STREAM) return EPROTONOSUPPORT; - - ipid = TCPIPLogin(MyID, 0, 0, 0, 0x0040); - if (_toolErr) return EPFNOSUPPORT; - - // semaphore ... - swait(semID); - - e = (ipidHash *)calloc(sizeof(ipidHash), 1); - e->ipid = ipid; - - e->_RCVLOWAT = 1; - e->_SNDLOWAT = 1024; - e->flags._OOBINLINE = 1; - - - e->next = htable[ipid & (64-1)]; - htable[ipid & (64 - 1)] = e; - - ssignal(semID); - // end semaphore - - *sockptr = ipid; - - return 0; -} - - -// netinet/in.h is giving me compile errors... - -struct xsockaddr_in { - short sin_family; - unsigned short sin_port; - unsigned long sin_addr; - char sin_zero[8]; -}; - - -int do_bind( - int socknum, - void *m, size_t *m_len, - struct sockaddr *addr, int *addrlen, - void *rights) -{ - // freebsd 2.0 whois does a bind before - // the connect. - // this was removed in freebsd 3.0 - - Word ipid = (Word)socknum; - struct xsockaddr_in *sin = (struct xsockaddr_in *)addr; - - port = sin->sin_port; - asm { - lda sin_addr, - port); - - if (_toolErr) return EPFNOSUPPORT; - - return 0; -} - - -int do_connect( - int socknum, - void *m, size_t *m_len, - struct sockaddr *addr, int *addrlen, - void *rights) -{ - // returns errno or 0. - Word terr; - Longword tick, qtick; - Word port; - - - Word ipid = (Word)socknum; - struct xsockaddr_in *sin = (struct xsockaddr_in *)addr; - - //WriteLine("\pdo_connect"); - debug_str("do_connect"); - - // port is byte-swapped. - - port = sin->sin_port; - asm { - lda sin_addr, - port); - - if (_toolErr) return EPFNOSUPPORT; - - terr = TCPIPOpenTCP(ipid); - if (_toolErr || terr) - { - return EPFNOSUPPORT; - } - - // wait to loop until actually connected. - - // 30-second timeout. - qtick = GetTick() + 60 * 30; - for(;;) - { - srBuff sr; - - terr = TCPIPStatusTCP(ipid, &sr); - - dump_srbuff(&sr); - - if (sr.srState == TCPSESTABLISHED) - return 0; - - if (sr.srState == TCPSCLOSED) - return ECONNREFUSED; - - if (sr.srState > TCPSESTABLISHED) - return ECONNREFUSED; - - if (GetTick() >= qtick) - return ETIMEDOUT; - - // is this safe? - sleep(1); - } - - - return 0; -} - - -int do_disconnect( - int socknum, - void *m, size_t *m_len, - struct sockaddr *addr, int *addrlen, - void *rights) -{ - Word ipid = socknum; - - debug_str("do_disconnect"); - //WriteLine("\pdo_disconnect"); - - // TODO -- SO_LINGER / SO_LINGER_SEC - // monitor the out queue and don't return until all - // data is sent (or it times out). - - // return value ignored. - - return 0; -} - -int do_detach( - int socknum, - void *m, size_t *m_len, - struct sockaddr *addr, int *addrlen, - void *rights) -{ - Word ipid = socknum; - - Word terr; - ipidHash *e; - ipidHash *prev; - - // returns a GS/OS error. - - // remove from hashtable. - // begin disconnect sequence. - // add to dlist. - - // need to use semaphore to block other thread... - - //WriteLine("\pdo_detach"); - debug_str("do_detach"); - - debug_str("TCPIPCloseTCP"); - terr = TCPIPCloseTCP(ipid); - - // semaphore... - debug_str("swait"); - swait(semID); - - prev = NULL; - e = htable[ipid & (64-1)]; - while (e) - { - if (e->ipid == ipid) break; - prev = e; - e = e->next; - } - if (e) - { - if (prev) prev->next = e->next; - else htable[ipid & (64 - 1)] = e->next; - - e->next = dlist; - dlist = e; - } - - debug_str("ssignal"); - ssignal(semID); - // end semaphore. - - debug_str("return 0"); - return 0; -} - -int do_send( - int socknum, - void *m, size_t *m_len, - struct sockaddr *addr, int *addrlen, - void *rights) -{ - // called from GS/OS, busyflag set - // (seems like a bug to me....) - - Word terr; - Word ipid = (Word)socknum; - void *data = (void *)m; - size_t *len = (size_t *)m_len; - - //WriteLine("\pdo_send"); - - { - static char buffer[64]; - sprintf(buffer, "do_send: ipid = %04x len = %04x", - ipid, (Word)*len - ); - debug_str(buffer); - } - - terr = TCPIPWriteTCP(ipid, data, *len, 0, 0); - - // closing == eof. - if (terr == tcperrConClosing) - { - *len = 0; - return ECONNRESET; // ? EPIPE? - } - - return 0; -} - - -int do_rcvd( - int socknum, - void *m, size_t *m_len, - struct sockaddr *addr, int *addrlen, - void *rights) -{ - // called from GS/OS, busy flag is set. - - // todo -- EWOULDBLOCK / EAGAIN - - // Marinetti will not read less than the requested - // size unless there is a push or the connection is closing. - - // TODO -- SO_RCVLOWAT (default is 1?) - // if SO_RCVLOWAT < queued data < requested length, - // read SO_RCVLOWAT bytes - - Word terr; - Word ipid = (Word)socknum; - void *data = (void *)m; - size_t *len = (size_t *)m_len; - - ipidHash *e; - rrBuff rr; - - Word readCount; - Word minCount; - - if (!len || !data) return EFAULT; - - e = findIpidHash(ipid); - - readCount = *len; - minCount = e ? e->_RCVLOWAT; - - //WriteLine("\pdo_rcvd"); - - { - static char buffer[64]; - sprintf(buffer, "do_rcvd: ipid = %04x len = %04x", - ipid, (Word)*len - ); - debug_str(buffer); - } - - // todo -- should block unless O_NONBLOCK set. - - - // todo -- could the read return 0 if there was a push at byte 0 - // but data afterwards? - for (;;) - { - - srBuff sr; - - terr = TCPIPStatusTCP(ipid, &sr); - - dump_srbuff(&sr); - - - if (!sr.srRcvQueued && e && e->flags._NONBLOCK) - { - *len = 0; - return EAGAIN; - } - - // - if (sr.srRcvQueued < readCount && sr.srRcvQueued >= minCount) - { - readCount = minCount; - } - - - - terr = TCPIPReadTCP(ipid, 0, (Ref)data, readCount, &rr); - - if (rr.rrBuffCount) - { - { - static char buffer[80]; - - sprintf(buffer, "read %04x bytes %04x %04x %04x", - (Word)rr.rrBuffCount, - rr.rrMoreFlag, - rr.rrPushFlag, - rr.rrUrgentFlag - ); - debug_str(buffer); - - dump_bytes(data, rr.rrBuffCount); - } - - *len = rr.rrBuffCount; - return 0; - } - - if (terr == tcperrBadConnection) - return ENOTCONN; - - // no data, no more data, then closing. - if (terr == tcperrConClosing && !rr.rrMoreFlag) - return ECONNRESET; - - //asm { - // cop 0x7f - //} - // poll in main loop not called, apparently. - - //TCPIPPoll(); // - sleep(1); - } - - return 0; -} - - -int do_select( - int socknum, - void *m, size_t *m_len, - struct sockaddr *addr, int *addrlen, - void *rights) -{ - - ipidHash *e; - srBuff sr; - Word terr; - - Word ipid = (Word)sock; - int *pid = (int *)m_len; - int *flag = (int *)(addr); - - // *flag is return value as well as input value - // (which select type) - // SEL_READ = 0 - // SEL_WRITE = 1 - // SEL_EXCEPT = 2 - - if (*flag == 0) - { - // sel read. - terr = TCPIPStatusTCP(ipid, &sr); - - if (sr.srRcvQueued) - *flag = 1; - else - *flag = 0; - - return 0; - } - - if (*flag == 1) - { - // sel write. - // check the high water mark. - terr = TCPIPStatusTCP(ipid, &sr); - - e = findIpidHash(ipid); - - if (e && sr.srSndQueued >= e->_SNDLOWAT) - *flag = 0; - else - *flag = 1; - - } - - if (*flag == 2) - { - // exceptions?? - *flag = 0; - } - - - return 0; -} - -int do_getsockopt( - Word ipid, - void *p1, void *p2, - void *p3, void *p4, - void *p5) -{ - - ipidHash *e; - int level = *(int *)p1; - int optname = *(int *)p2; - void *optval = (void *)p3; - int *optlen = (int *)p4; - - if (!optval) return EINVAL; - - e = findIpidHash(ipid); - - switch (optname) - { - case SO_NREAD: - // return the amount of data available to read. - break; - - case SO_NWRITE: - // return the amount of data queued for writing. - break; - - case SO_TYPE: - *(Word *)optval = SOCK_STREAM; - return 0; - - case SO_NOSIGPIPE: - if (e) *(Word *)optval = e->flags._NOSIGPIPE; - else *(Word *)optval = 0; - return 0; - break; - - case SO_RCVLOWAT: - if (e) *(Word)optval = e->_RCVLOWAT; - else *(Word)optval = 1; - return 0; - - case SO_SNDLOWAT: - if (e) *(Word)optval = e->_SNDLOWAT; - else *(Word)optval = 1024; - return 0; - - case SO_LINGER: - if (e) *(Word *)optval = e->flags._LINGER; - else *(Word *)optval = 0; - return 0; - break; - - case SO_OOBINLINE: - if (e) *(Word *)optval = e->flags._OOBINLINE; - else *(Word *)optval = 1; - return 0; - break; - - // unsupported ish. - case SO_SNDBUF: - case SO_RCVBUF: - // input/output buffer size - - case SO_RCVTIMEO: - case SO_SNDTIMEO: - // read/send timeout. - - case SO_ERROR: - // return any pending error and clear the error status. - - - default: - return ENOPROTOOPT; - } - - return ENOPROTOOPT; -} - - -int do_shutdown( - Word ipid, - void *p1, void *p2, - void *p3, void *p4, - void *p5) -{ - ipidHash *e = findIpidHash(ipid); - - int how = *(int *)p1; - - // mark the read/write op disabled - // TODO -- main thread should read & ignore any - // incoming data if SHUT_RD? - - if (!e) return EINVAL; - - switch(how) - { - case 0: - e->flags._SHUT_RD = 1; - break; - case 1: - e->flags._SHUT_WR = 1; - break; - case 2: - e->flags._SHUT_RD = 1; - e->flags._SHUT_WR = 1; - break; - - default: - return EINVAL; - } - - return 0; -} - -#pragma databank 1 -static int driver( - int socknum, int req, - void *m, size_t *m_len, - struct sockaddr *addr, int *addrlen, - void *rights) -{ - int rv; - - { - static char buffer[64]; - sprintf(buffer, "driver: req = %d", req); - debug_str(buffer); - } - - switch (req) - { - case PRU_ABORT: - break; - - case PRU_ACCEPT: - break; - - case PRU_ATTACH: - // KERNsocket(int domain, int type, int protocol, int *ERRNO); - return do_attach(socknum, m, m_len, addr, addrlen, rights); - 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); - break; - - case PRU_CONNECT: - // KERNconnect(int fd, struct sockaddr *serv_addr, - // int addrlen, int *ERRNO) - return do_connect(socknum, m, m_len, addr, addrlen, rights); - break; - - case PRU_CONNECT2: - break; - - case PRU_CONTROL: - break; - - case PRU_DETACH: - // called from GS/OS - // int SOCKclose(int sock) part 2 - return do_detach(socknum, m, m_len, addr, addrlen, rights); - break; - - case PRU_DISCONNECT: - // called from GS/OS - // int SOCKclose(int sock) part 1 - return do_disconnect(socknum, m, m_len, addr, addrlen, rights); - break; - - case PRU_LISTEN: - break; - - case PRU_PEERADDR: - break; - - case PRU_RCVD: - // called from GS/OS. - // may block, so be nice. - // SOCKrdwr(struct rwPBlock *pb, word cmd, int sock) - asm { - // dec busy. - jsl 0xE10068 - } - rv = do_rcvd(socknum, m, m_len, addr, addrlen, rights); - asm { - // inc busy. - jsl 0xE10064 - } - return rv; - break; - - case PRU_RCVOOB: - break; - - case PRU_SEND: - // SOCKrdwr(struct rwPBlock *pb, word cmd, int sock) - return do_send(socknum, m, m_len, addr, addrlen, rights); - 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) - return do_select(socknum, m, m_len, addr, addrlen, rights); - - break; - } - - return EINVAL; -} - - -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); - - while(!QuitFlag) - { - ipidHash *e; - ipidHash *prev; - - debug_str("TCPIPPoll() begin"); - if (dlist) - { - // suspend so we can be fg. - kill(getpid(),SIGSTOP); - asm { - brk 0xea - } - } - TCPIPPoll(); - debug_str("TCPIPPoll() end"); - - // monitor disconnects... - // semaphore ... - - swait(semID); - if (errno == EINTR) continue; - - e = dlist; - prev = NULL; - - while (e) - { - Word terr; - srBuff sr; - ipidHash *next; - - next = e->next; - - terr = TCPIPStatusTCP(e->ipid, &sr); - - dump_srbuff(&sr); - - // timed wait or closed ... - if (sr.srState == TCPSCLOSED) - { - - debug_str("TCPLogout"); - TCPIPLogout(e->ipid); - free(e); - - if (prev) - { - prev->next = next; - } - else - { - dlist = next; - } - } - else - { - prev = e; - } - - e = next; - } - - ssignal(semID); - // end semaphore. - - sleep(1); // need a sleep10 to match alarm10 - } - - InstallNetDriver(NULL, 0); - sdelete(semID); - - - ShutDown(flags, 0, DisplayMessage); - - return 0; -}