mirror of
https://github.com/ksherlock/marignotti.git
synced 2025-03-11 06:29:26 +00:00
initial version (it even works)
This commit is contained in:
commit
cc79ed4ede
648
marignotti.c
Normal file
648
marignotti.c
Normal file
@ -0,0 +1,648 @@
|
||||
/*
|
||||
* MariGNOtti
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma optimize 79
|
||||
|
||||
#include <memory.h>
|
||||
#include <tcpip.h>
|
||||
#include <texttool.h>
|
||||
#include <misctool.h>
|
||||
#include <locator.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
//#include <gno/kerntool.h>
|
||||
#include <gno/gno.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
//#include <netinet/in.h>
|
||||
|
||||
#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.
|
||||
|
||||
typedef struct ipidHash {
|
||||
Word ipid;
|
||||
Word flags;
|
||||
struct ipidHash *next;
|
||||
} ipidHash;
|
||||
|
||||
ipidHash *htable[64] = { };
|
||||
|
||||
ipidHash *dlist = NULL;
|
||||
|
||||
|
||||
|
||||
// not yet sure what this is for...
|
||||
typedef void (*selwakeup)(int col_flag, int pid);
|
||||
|
||||
void debug_str(const char *cp)
|
||||
{
|
||||
asm {
|
||||
ldx <cp+2
|
||||
ldy <cp
|
||||
cop 0x84
|
||||
}
|
||||
}
|
||||
|
||||
void dump_srbuff(const srBuff *sb)
|
||||
{
|
||||
static char buffer[256];
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
asm {
|
||||
ldx #^buffer
|
||||
ldy #buffer
|
||||
cop 0x84
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 *)malloc(sizeof(ipidHash));
|
||||
e->ipid = ipid;
|
||||
e->flags = 0;
|
||||
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_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 <port
|
||||
xba
|
||||
sta <port
|
||||
}
|
||||
|
||||
TCPIPSetNewDestination(ipid,
|
||||
sin->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");
|
||||
|
||||
// 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");
|
||||
|
||||
terr = TCPIPCloseTCP(ipid);
|
||||
|
||||
// semaphore...
|
||||
swait(semID);
|
||||
|
||||
prev = NULL;
|
||||
e = htable[ipid & (64-1)];
|
||||
for(;;)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
ssignal(semID);
|
||||
// end semaphore.
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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?
|
||||
|
||||
Word terr;
|
||||
Word ipid = (Word)socknum;
|
||||
void *data = (void *)m;
|
||||
size_t *len = (size_t *)m_len;
|
||||
|
||||
rrBuff rr;
|
||||
|
||||
//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.
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
||||
srBuff sr;
|
||||
|
||||
terr = TCPIPStatusTCP(ipid, &sr);
|
||||
|
||||
dump_srbuff(&sr);
|
||||
|
||||
|
||||
terr = TCPIPReadTCP(ipid, 0, (Ref)data, *len, &rr);
|
||||
|
||||
if (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;
|
||||
|
||||
|
||||
// if NON_BLOCKING, return EWOULDBLOCK.
|
||||
|
||||
asm {
|
||||
cop 0x7f
|
||||
}
|
||||
// poll in main loop not called, apparently.
|
||||
|
||||
TCPIPPoll(); //
|
||||
//sleep(1); // cop 0x7f?
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
{
|
||||
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:
|
||||
//WriteLine("\pbind!");
|
||||
// todo
|
||||
return 0;
|
||||
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:
|
||||
// int SOCKclose(int sock) part 2
|
||||
return do_detach(socknum, m, m_len, addr, addrlen, rights);
|
||||
break;
|
||||
|
||||
case PRU_DISCONNECT:
|
||||
// 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:
|
||||
// SOCKrdwr(struct rwPBlock *pb, word cmd, int sock)
|
||||
return do_rcvd(socknum, m, m_len, addr, addrlen, rights);
|
||||
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:
|
||||
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 0
|
||||
// require 3.0b3
|
||||
if (TCPIPLongVersion() < 0x03006003)
|
||||
{
|
||||
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);
|
||||
|
||||
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()");
|
||||
TCPIPPoll();
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
||||
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;
|
||||
}
|
35
net.h
Normal file
35
net.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* GNO/ME Network Support
|
||||
*
|
||||
* Copyright 1994-1998, Procyon Enterprises Inc.
|
||||
*
|
||||
* Written by Derek Taubert and Jawaid Bazyar
|
||||
*
|
||||
*/
|
||||
|
||||
/* Request types for pr_usrreq() */
|
||||
|
||||
#define PRU_ABORT 0
|
||||
#define PRU_ACCEPT 1
|
||||
#define PRU_ATTACH 2
|
||||
#define PRU_BIND 3
|
||||
#define PRU_CONNECT 4
|
||||
#define PRU_CONNECT2 5
|
||||
#define PRU_CONTROL 6
|
||||
#define PRU_DETACH 7
|
||||
#define PRU_DISCONNECT 8
|
||||
#define PRU_LISTEN 9
|
||||
#define PRU_PEERADDR 10
|
||||
#define PRU_RCVD 11
|
||||
#define PRU_RCVOOB 12
|
||||
#define PRU_SEND 13
|
||||
#define PRU_SENDOOB 14
|
||||
#define PRU_SENSE 15
|
||||
#define PRU_SHUTDOWN 16
|
||||
#define PRU_SOCKADDR 17
|
||||
#define PRU_CO_GETOPT 18
|
||||
#define PRU_CO_SETOPT 19
|
||||
#define PRU_SELECT 20
|
||||
|
Loading…
x
Reference in New Issue
Block a user