2012-05-05 00:10:49 +00:00
|
|
|
#include "marignotti.h"
|
|
|
|
#include <gno/kerntool.h>
|
|
|
|
#include <errno.h>
|
2012-05-12 23:44:10 +00:00
|
|
|
#include <sys/socket.h>
|
2012-05-05 00:10:49 +00:00
|
|
|
|
2012-05-12 23:44:10 +00:00
|
|
|
#include <memory.h>
|
2012-05-05 00:10:49 +00:00
|
|
|
#include <misctool.h>
|
|
|
|
|
2012-05-12 01:21:29 +00:00
|
|
|
#include "s16debug.h"
|
|
|
|
|
2012-05-05 00:10:49 +00:00
|
|
|
#pragma noroot
|
|
|
|
#pragma optimize 79
|
|
|
|
|
2012-05-12 23:44:10 +00:00
|
|
|
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)
|
2012-05-05 00:10:49 +00:00
|
|
|
{
|
2012-05-12 23:44:10 +00:00
|
|
|
LongWord size;
|
|
|
|
LongWord lowat;
|
|
|
|
Word t;
|
|
|
|
Word terr;
|
2012-05-05 00:10:49 +00:00
|
|
|
rrBuff rr;
|
|
|
|
|
2012-05-13 23:45:51 +00:00
|
|
|
if (e->_SHUT_RD)
|
|
|
|
return 0;
|
2012-05-12 23:44:10 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-05-13 23:46:25 +00:00
|
|
|
int mreadoob(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
|
|
|
{
|
|
|
|
// called via recv, recvfrom.
|
|
|
|
// OOB is always inline, therefore an OOB read will
|
|
|
|
// just return 0.
|
|
|
|
// todo -- just treat as regular read?
|
|
|
|
|
|
|
|
char *buffer = (char *)p1;
|
|
|
|
LongWord nbytes = *(LongWord *)p2;
|
|
|
|
xsockaddr *addr = (xsockaddr *)p3;
|
|
|
|
int addrlen = p4 ? *(int *)p4 : 0;
|
|
|
|
|
|
|
|
LongWord *outbytes = (LongWord *)p2;
|
|
|
|
|
|
|
|
*outbytes = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (Debug > 0)
|
|
|
|
{
|
|
|
|
s16_debug_printf("oob read nbytes = %ld", nbytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-12 23:44:10 +00:00
|
|
|
// called through ReadGS, recv, recvfrom
|
|
|
|
int mread(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
|
|
|
{
|
|
|
|
|
2012-05-05 00:10:49 +00:00
|
|
|
int xerrno = 0;
|
|
|
|
LongWord timeout;
|
2012-05-12 23:44:10 +00:00
|
|
|
|
2012-05-05 00:10:49 +00:00
|
|
|
|
|
|
|
char *buffer = (char *)p1;
|
|
|
|
LongWord nbytes = *(LongWord *)p2;
|
2012-05-12 23:44:10 +00:00
|
|
|
xsockaddr *addr = (xsockaddr *)p3;
|
|
|
|
int addrlen = p4 ? *(int *)p4 : 0;
|
|
|
|
|
|
|
|
LongWord *outbytes = (LongWord *)p2;
|
|
|
|
|
|
|
|
*outbytes = 0;
|
2012-05-05 00:10:49 +00:00
|
|
|
|
2012-05-12 01:21:29 +00:00
|
|
|
if (Debug > 0)
|
|
|
|
{
|
|
|
|
s16_debug_printf("read nbytes = %ld", nbytes);
|
|
|
|
}
|
|
|
|
|
2012-05-05 00:10:49 +00:00
|
|
|
IncBusy();
|
2012-05-12 23:44:10 +00:00
|
|
|
xerrno = sock_read(e, buffer, nbytes, outbytes);
|
2012-05-05 00:10:49 +00:00
|
|
|
DecBusy();
|
|
|
|
|
2012-05-12 23:44:10 +00:00
|
|
|
if (xerrno != EAGAIN || e->_NONBLOCK)
|
2012-05-05 00:10:49 +00:00
|
|
|
{
|
2012-05-12 23:44:10 +00:00
|
|
|
return xerrno;
|
2012-05-05 00:10:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (e->_RCVTIMEO)
|
|
|
|
timeout = GetTick() + e->_RCVTIMEO;
|
|
|
|
else
|
|
|
|
timeout = 0;
|
|
|
|
|
|
|
|
for(;;)
|
|
|
|
{
|
2012-05-12 23:44:10 +00:00
|
|
|
xerrno = queue_command(e, kCommandRead, nbytes, timeout);
|
2012-05-05 00:10:49 +00:00
|
|
|
if (xerrno == EINTR) return EINTR;
|
|
|
|
if (xerrno) return EIO;
|
|
|
|
|
|
|
|
if (e->command) continue; // reset to 0 if processed.
|
|
|
|
|
|
|
|
|
2012-05-12 23:44:10 +00:00
|
|
|
IncBusy();
|
|
|
|
xerrno = sock_read(e, buffer, nbytes, outbytes);
|
|
|
|
DecBusy();
|
|
|
|
|
|
|
|
if (xerrno != EAGAIN) return xerrno;
|
2012-05-05 00:10:49 +00:00
|
|
|
|
2012-05-05 06:20:05 +00:00
|
|
|
if (timeout && timeout <= GetTick())
|
2012-05-05 00:10:49 +00:00
|
|
|
return EAGAIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
// should not hit...
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|