mirror of
https://github.com/ksherlock/marignotti.git
synced 2024-12-21 08:29:31 +00:00
UDP support (socket, read, write)
This commit is contained in:
parent
bd54abed5c
commit
750f8ab0e5
11
mattach.c
11
mattach.c
@ -25,8 +25,15 @@ int mattach(int type, void *p1, void *p2, void *p3, void *p4, void *p5)
|
||||
type, protocol);
|
||||
}
|
||||
|
||||
|
||||
if (type != SOCK_STREAM) return ESOCKTNOSUPPORT;
|
||||
switch (type)
|
||||
{
|
||||
case SOCK_STREAM:
|
||||
case SOCK_DGRAM:
|
||||
break;
|
||||
default:
|
||||
return ESOCKTNOSUPPORT;
|
||||
break;
|
||||
}
|
||||
//if (protocol != 6) return EPROTONOSUPPORT;
|
||||
// TODO -- check protocol? 6 = tcp, 1 = icmp, 17 = udp.
|
||||
|
||||
|
241
mread.c
241
mread.c
@ -1,7 +1,9 @@
|
||||
#include "marignotti.h"
|
||||
#include <gno/kerntool.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include <misctool.h>
|
||||
|
||||
#include "s16debug.h"
|
||||
@ -9,70 +11,183 @@
|
||||
#pragma noroot
|
||||
#pragma optimize 79
|
||||
|
||||
// called through GSOS.
|
||||
int mread(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
||||
typedef struct xipheader {
|
||||
byte verlen;
|
||||
byte tos;
|
||||
word len;
|
||||
word id;
|
||||
word fragoff;
|
||||
byte ttl;
|
||||
byte proto;
|
||||
word cksum;
|
||||
longword src;
|
||||
longword dst;
|
||||
// verlen & 0x0f is the number of 32-but words
|
||||
// if > 5, extra data present and should be skipped.
|
||||
|
||||
// data...
|
||||
|
||||
} xipheader;
|
||||
|
||||
typedef struct xudpheader {
|
||||
word source;
|
||||
word dst;
|
||||
word len;
|
||||
word cksum;
|
||||
// data...
|
||||
} xudpheader;
|
||||
|
||||
// todo -- should have addr/addrlen for recvfrom.
|
||||
static int sock_read(
|
||||
Entry *e,
|
||||
void *buffer,
|
||||
LongWord nbytes,
|
||||
LongWord *outbytes)
|
||||
{
|
||||
LongWord size;
|
||||
LongWord lowat;
|
||||
Word t;
|
||||
Word terr;
|
||||
rrBuff rr;
|
||||
|
||||
|
||||
if (e->_TYPE == SOCK_DGRAM)
|
||||
{
|
||||
// todo -- address support.
|
||||
|
||||
// manually parse the ip header and udp header.
|
||||
//
|
||||
|
||||
|
||||
Handle h;
|
||||
xipheader *ip;
|
||||
Word offset = 0;
|
||||
char *cp;
|
||||
|
||||
|
||||
h = TCPIPGetNextDatagram(e->ipid, protocolUDP, 0);
|
||||
t = _toolErr;
|
||||
|
||||
if (t) return ENETDOWN;
|
||||
if (!h) return EAGAIN;
|
||||
|
||||
size = GetHandleSize(h);
|
||||
|
||||
HLock(h);
|
||||
cp = *(char **)h;
|
||||
|
||||
ip = (xipheader *)cp;
|
||||
offset = (ip->verlen & 0x0f) << 2;
|
||||
|
||||
// would get the address here.
|
||||
// ip->src
|
||||
|
||||
offset += u_data;
|
||||
|
||||
if (offset >= size)
|
||||
{
|
||||
// ???
|
||||
DisposeHandle(h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size -= offset;
|
||||
cp += offset;
|
||||
|
||||
// nbytes is the max read... any overflow is discarded.
|
||||
if (size > nbytes) size = nbytes;
|
||||
BlockMove(cp, buffer, nbytes);
|
||||
|
||||
if (Debug > 1)
|
||||
{
|
||||
s16_debug_dump(buffer, (Word)size);
|
||||
}
|
||||
|
||||
DisposeHandle(h);
|
||||
|
||||
*outbytes = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// todo -- address support (which will always be the dest ip...)
|
||||
|
||||
terr = TCPIPStatusTCP(e->ipid, &e->sr);
|
||||
t = _toolErr;
|
||||
if (t) terr = t;
|
||||
e->terr = terr;
|
||||
|
||||
if (t) return ENETDOWN;
|
||||
|
||||
if (e->sr.srState < TCPSESTABLISHED) return ENOTCONN;
|
||||
|
||||
size = e->sr.srRcvQueued;
|
||||
lowat = e->_RCVLOWAT;
|
||||
|
||||
// if the state is established, read LOWAT...nbytes.
|
||||
// if the connection is closing, LOWAT is 1.
|
||||
|
||||
if (e->sr.srState > TCPSESTABLISHED)
|
||||
{
|
||||
lowat = 1;
|
||||
if (!size) return 0; // eof
|
||||
}
|
||||
|
||||
if (size < nbytes && size >= lowat)
|
||||
nbytes = size;
|
||||
|
||||
if (size < nbytes) return EAGAIN;
|
||||
|
||||
// size >= nbytes.
|
||||
terr = TCPIPReadTCP(e->ipid, 0, (Ref)buffer, nbytes, &rr);
|
||||
t = _toolErr;
|
||||
if (t) terr = t;
|
||||
e->terr = terr;
|
||||
|
||||
// todo -- if there was a push, < nbyte will have been read.
|
||||
// loop until nbytes have been read?
|
||||
|
||||
if (Debug > 1)
|
||||
{
|
||||
s16_debug_dump(buffer, (Word)rr.rrBuffCount);
|
||||
}
|
||||
|
||||
*outbytes = rr.rrBuffCount;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
// called through ReadGS, recv, recvfrom
|
||||
int mread(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
||||
{
|
||||
|
||||
int xerrno = 0;
|
||||
LongWord count;
|
||||
LongWord timeout;
|
||||
Word terr;
|
||||
Word t;
|
||||
|
||||
|
||||
char *buffer = (char *)p1;
|
||||
LongWord nbytes = *(LongWord *)p2;
|
||||
*(LongWord *)p2 = 0;
|
||||
xsockaddr *addr = (xsockaddr *)p3;
|
||||
int addrlen = p4 ? *(int *)p4 : 0;
|
||||
|
||||
LongWord *outbytes = (LongWord *)p2;
|
||||
|
||||
*outbytes = 0;
|
||||
|
||||
if (Debug > 0)
|
||||
{
|
||||
s16_debug_printf("read nbytes = %ld", nbytes);
|
||||
}
|
||||
|
||||
count = e->_RCVLOWAT;
|
||||
if (count > nbytes) count = nbytes;
|
||||
|
||||
// call immediately if possible, otherwise queue it up.
|
||||
IncBusy();
|
||||
terr = TCPIPStatusTCP(e->ipid, &e->sr);
|
||||
t = _toolErr;
|
||||
xerrno = sock_read(e, buffer, nbytes, outbytes);
|
||||
DecBusy();
|
||||
if (t) terr = t;
|
||||
|
||||
if (t || terr == tcperrBadConnection || terr == tcperrNoResources)
|
||||
if (xerrno != EAGAIN || e->_NONBLOCK)
|
||||
{
|
||||
return ENOTCONN;
|
||||
return xerrno;
|
||||
}
|
||||
|
||||
// eof or data available?
|
||||
|
||||
if (e->sr.srRcvQueued >= count || terr == tcperrConClosing)
|
||||
{
|
||||
count = e->sr.srRcvQueued;
|
||||
if (count > nbytes) count = nbytes;
|
||||
|
||||
if (count)
|
||||
{
|
||||
IncBusy();
|
||||
terr = TCPIPReadTCP(e->ipid, 0, (Ref)buffer, count, &rr);
|
||||
t = _toolErr;
|
||||
DecBusy();
|
||||
if (t) terr = t;
|
||||
|
||||
*(LongWord *)p2 = rr.rrBuffCount;
|
||||
|
||||
if (Debug > 1)
|
||||
{
|
||||
s16_debug_dump(buffer, (Word)rr.rrBuffCount);
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (e->_NONBLOCK) return EAGAIN;
|
||||
|
||||
|
||||
if (e->_RCVTIMEO)
|
||||
timeout = GetTick() + e->_RCVTIMEO;
|
||||
else
|
||||
@ -80,51 +195,21 @@ int mread(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
||||
|
||||
for(;;)
|
||||
{
|
||||
xerrno = queue_command(e, kCommandRead, count, timeout);
|
||||
xerrno = queue_command(e, kCommandRead, nbytes, timeout);
|
||||
if (xerrno == EINTR) return EINTR;
|
||||
if (xerrno) return EIO;
|
||||
|
||||
if (e->command) continue; // reset to 0 if processed.
|
||||
|
||||
terr = e->terr;
|
||||
|
||||
if (terr && terr != tcperrConClosing)
|
||||
{
|
||||
return EIO;
|
||||
}
|
||||
|
||||
// 3 things may have happened.
|
||||
// 1. sufficient data available.
|
||||
// 2. connection closed.
|
||||
// 3. timeout.
|
||||
|
||||
IncBusy();
|
||||
xerrno = sock_read(e, buffer, nbytes, outbytes);
|
||||
DecBusy();
|
||||
|
||||
if (e->sr.srRcvQueued >= count || terr == tcperrConClosing)
|
||||
{
|
||||
count = e->sr.srRcvQueued;
|
||||
if (count > nbytes) count = nbytes;
|
||||
if (xerrno != EAGAIN) return xerrno;
|
||||
|
||||
if (count)
|
||||
{
|
||||
IncBusy();
|
||||
terr = TCPIPReadTCP(e->ipid, 0, (Ref)buffer, count, &rr);
|
||||
t = _toolErr;
|
||||
DecBusy();
|
||||
|
||||
*(LongWord *)p2 = rr.rrBuffCount;
|
||||
|
||||
if (Debug > 1)
|
||||
{
|
||||
s16_debug_dump(buffer, (Word)rr.rrBuffCount);
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (timeout && timeout <= GetTick())
|
||||
return EAGAIN;
|
||||
|
||||
}
|
||||
|
||||
// should not hit...
|
||||
|
50
mwrite.c
50
mwrite.c
@ -1,6 +1,7 @@
|
||||
#include "marignotti.h"
|
||||
#include <gno/kerntool.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "s16debug.h"
|
||||
@ -8,7 +9,7 @@
|
||||
#pragma noroot
|
||||
#pragma optimize 79
|
||||
|
||||
// called through GSOS.
|
||||
// WriteGS, send, or sendto
|
||||
int mwrite(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
||||
{
|
||||
Word terr;
|
||||
@ -17,12 +18,48 @@ int mwrite(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
||||
|
||||
char *buffer = (char *)p1;
|
||||
LongWord nbytes = *(LongWord *)p2;
|
||||
xsockaddr *addr = (xsockaddr *)p3;
|
||||
int addrlen = p4 ? *(int *)p4 : 0;
|
||||
|
||||
*(LongWord *)p2 = 0;
|
||||
LongWord *outbytes = (LongWord *)p2;
|
||||
|
||||
*outbytes = 0;
|
||||
|
||||
if (Debug > 0)
|
||||
{
|
||||
s16_debug_printf("write nbytes = %ld", nbytes);
|
||||
if (addr)
|
||||
{
|
||||
s16_debug_puts(" to address...");
|
||||
s16_debug_dump(addr, addrlen);
|
||||
}
|
||||
}
|
||||
if (Debug > 1)
|
||||
{
|
||||
s16_debug_puts("");
|
||||
s16_debug_dump(buffer, (Word)nbytes);
|
||||
}
|
||||
|
||||
if (e->_TYPE == SOCK_DGRAM)
|
||||
{
|
||||
// TCPIPSendUDP builds a header
|
||||
// using the source port, my ip address,
|
||||
// destination port and destination ip address.
|
||||
|
||||
// mconnect should probably just set the destination
|
||||
// address/port and exit.
|
||||
|
||||
// if an address was specified, we would need to
|
||||
// build the udp header here.
|
||||
IncBusy();
|
||||
TCPIPSendUDP(e->ipid, buffer, nbytes);
|
||||
t = _toolErr;
|
||||
DecBusy();
|
||||
|
||||
if (t) return ENETDOWN;
|
||||
|
||||
*outbytes = nbytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// todo -- queue up if pending >= _SNDLOWAT?
|
||||
@ -31,8 +68,9 @@ int mwrite(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
||||
IncBusy();
|
||||
terr = TCPIPWriteTCP(e->ipid, buffer, nbytes, 0, 0);
|
||||
t = _toolErr;
|
||||
DecBusy();
|
||||
if (t) terr = t;
|
||||
e->terr = terr;
|
||||
DecBusy();
|
||||
|
||||
if (t || terr == tcperrBadConnection)
|
||||
return ENOTCONN;
|
||||
@ -42,14 +80,16 @@ int mwrite(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
||||
|
||||
if (terr == tcperrConClosing)
|
||||
{
|
||||
int xerrno;
|
||||
if (!e->_NOSIGPIPE)
|
||||
{
|
||||
int xerrno;
|
||||
Kkill(Kgetpid(), SIGPIPE, &xerrno);
|
||||
}
|
||||
|
||||
return EPIPE;
|
||||
}
|
||||
|
||||
*(LongWord *)p2 = nbytes;
|
||||
*outbytes = nbytes;
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user