marignotti/mread.c

134 lines
3.0 KiB
C
Raw Normal View History

2012-05-05 00:10:49 +00:00
#include "marignotti.h"
#include <gno/kerntool.h>
#include <errno.h>
#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
// 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;
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
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;
2012-05-12 01:21:29 +00:00
*(LongWord *)p2 = rr.rrBuffCount;
if (Debug > 1)
{
s16_debug_dump(buffer, (Word)rr.rrBuffCount);
}
2012-05-05 00:10:49 +00:00
}
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;
2012-05-12 01:21:29 +00:00
if (Debug > 1)
{
s16_debug_dump(buffer, (Word)rr.rrBuffCount);
}
2012-05-05 00:10:49 +00:00
}
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;
}