2012-05-05 00:10:49 +00:00
|
|
|
#include "marignotti.h"
|
|
|
|
#include <gno/kerntool.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include <misctool.h>
|
|
|
|
|
|
|
|
#pragma noroot
|
|
|
|
#pragma optimize 79
|
|
|
|
|
|
|
|
// called through GSOS.
|
2012-05-05 05:08:06 +00:00
|
|
|
int mread(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
2012-05-05 00:10:49 +00:00
|
|
|
{
|
|
|
|
rrBuff rr;
|
|
|
|
|
|
|
|
int xerrno = 0;
|
|
|
|
LongWord count;
|
|
|
|
LongWord timeout;
|
|
|
|
Word terr;
|
|
|
|
Word t;
|
|
|
|
|
|
|
|
char *buffer = (char *)p1;
|
|
|
|
LongWord nbytes = *(LongWord *)p2;
|
|
|
|
*(LongWord *)p2 = 0;
|
|
|
|
|
|
|
|
|
|
|
|
count = e->_RCVLOWAT;
|
|
|
|
if (count > nbytes) count = nbytes;
|
|
|
|
|
|
|
|
// call immediately if possible, otherwise queue it up.
|
|
|
|
IncBusy();
|
2012-05-05 05:08:06 +00:00
|
|
|
terr = TCPIPStatusTCP(e->ipid, &e->sr);
|
2012-05-05 00:10:49 +00:00
|
|
|
t = _toolErr;
|
|
|
|
DecBusy();
|
|
|
|
if (t) terr = t;
|
|
|
|
|
|
|
|
if (t || terr == tcperrBadConnection || terr == tcperrNoResources)
|
|
|
|
{
|
|
|
|
return ENOTCONN;
|
|
|
|
}
|
|
|
|
|
|
|
|
// eof or data available?
|
|
|
|
|
|
|
|
if (e->sr.srRcvQueued >= count || terr == tcperrConClosing)
|
|
|
|
{
|
|
|
|
count = e->sr.srRcvQueued;
|
|
|
|
if (count > nbytes) count = nbytes;
|
|
|
|
|
|
|
|
if (count)
|
|
|
|
{
|
|
|
|
IncBusy();
|
2012-05-05 05:08:06 +00:00
|
|
|
terr = TCPIPReadTCP(e->ipid, 0, (Ref)buffer, count, &rr);
|
2012-05-05 00:10:49 +00:00
|
|
|
t = _toolErr;
|
|
|
|
DecBusy();
|
|
|
|
if (t) terr = t;
|
|
|
|
|
|
|
|
*(LongWord *)p2 = rr.rrBuffCount;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e->_NONBLOCK) return EAGAIN;
|
|
|
|
|
|
|
|
|
|
|
|
if (e->_RCVTIMEO)
|
|
|
|
timeout = GetTick() + e->_RCVTIMEO;
|
|
|
|
else
|
|
|
|
timeout = 0;
|
|
|
|
|
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
xerrno = queue_command(e, kCommandRead, count, 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.
|
|
|
|
|
|
|
|
|
|
|
|
if (e->sr.srRcvQueued >= count || terr == tcperrConClosing)
|
|
|
|
{
|
|
|
|
count = e->sr.srRcvQueued;
|
|
|
|
if (count > nbytes) count = nbytes;
|
|
|
|
|
|
|
|
if (count)
|
|
|
|
{
|
|
|
|
IncBusy();
|
2012-05-05 05:08:06 +00:00
|
|
|
terr = TCPIPReadTCP(e->ipid, 0, (Ref)buffer, count, &rr);
|
2012-05-05 00:10:49 +00:00
|
|
|
t = _toolErr;
|
|
|
|
DecBusy();
|
|
|
|
|
|
|
|
*(LongWord *)p2 = rr.rrBuffCount;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|