socket options.

This commit is contained in:
Kelvin Sherlock 2012-05-05 15:44:54 -04:00
parent 94cd1304c4
commit 20ae337205
4 changed files with 309 additions and 4 deletions

View File

@ -32,9 +32,6 @@ int queue_command(Entry *e, Word command, LongWord cookie, LongWord timeout)
#pragma databank 1
int driver(
@ -52,6 +49,7 @@ int driver(
{
return mattach(socknum, p1, p2, p3, p4, p5);
}
e = find_entry(socknum);
if (!e)
@ -153,9 +151,11 @@ int driver(
break;
case PRU_CO_GETOPT:
return mgetsockopt(e, p1, p2, p3, p4, p5);
break;
case PRU_CO_SETOPT:
return msetsockopt(e, p1, p2, p3, p4, p5);
break;
case PRU_SELECT:

View File

@ -39,7 +39,8 @@ typedef struct Entry {
LongWord _SNDLOWAT;
LongWord _RCVLOWAT;
Word _RCVTIMEO;
LongWord _RCVTIMEO;
LongWord _SNDTIMEO;
Word _LINGER_SEC;

179
mgetsockopt.c Normal file
View File

@ -0,0 +1,179 @@
#include "marignotti.h"
#include <gno/kerntool.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/time.h>
#pragma noroot
#pragma optimize 79
static void ticks_to_timeval(LongWord ticks, struct timeval *tv)
{
LongDivRec qr;
if (ticks == 0)
{
tv->tv_sec = 0;
tv->tv_usec = 0;
}
else
{
qr = LongDivide(ticks, 60);
tv->tv_sec = qr.quotient;
tv->tv_usec = Multiply(qr.remainder, 16667);
// qr.remainder * 1,000,000 / 60
}
}
int mgetsockopt(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
{
Word terr;
Word t;
int level = *(int *)p1;
int optname = *(int *)p2;
void *optval = (void *)p3;
int optlen = p4 ? *(int *)p4 : 0;
if (level != SOL_SOCKET) return EINVAL;
if (!optval) return EINVAL;
// todo -- linger
switch (optname)
{
case SO_TYPE:
// todo... non-stream
if (optlen == 4)
{
*(LongWord *)optval = SOCK_STREAM;
return 0;
}
if (optlen == 2)
{
*(Word *)optval = SOCK_STREAM;
return 0;
}
break;
case SO_OOBINLINE:
if (optlen == 4)
{
*(LongWord *)optval = 1;
return 0;
}
if (optlen == 2)
{
*(Word *)optval = 1;
return 0;
}
if (optlen == 1)
{
*(char *)optval = 1;
return 0;
}
break;
case SO_SNDLOWAT:
if (optlen == 4)
{
*(LongWord *)optval = e->_SNDLOWAT;
return 0;
}
if (optlen == 2)
{
*(Word *)optval = e->_SNDLOWAT;
return 0;
}
break;
case SO_RCVLOWAT:
if (optlen == 4)
{
*(LongWord *)optval = e->_RCVLOWAT;
return 0;
}
if (optlen == 2)
{
*(Word *)optval = e->_RCVLOWAT;
return 0;
}
break;
case SO_SNDTIMEO:
if (optlen == sizeof(struct timeval))
{
// stored as ticks aka seconds * 60.
struct timeval *tv = (struct timeval *)optval;
ticks_to_timeval(e->_SNDTIMEO, tv);
return 0;
}
break;
case SO_RCVTIMEO:
if (optlen == sizeof(struct timeval))
{
// stored as ticks aka seconds * 60.
struct timeval *tv = (struct timeval *)optval;
ticks_to_timeval(e->_RCVTIMEO, tv);
return 0;
}
break;
#ifdef SO_NREAD
case SO_NREAD:
IncBusy();
terr = TCPIPStatusTCP(e->ipid, &e->sr);
t = _toolErr;
DecBusy();
if (t) terr = t;
if (optlen == 4)
{
*(LongWord *)optval = e->sr.srRcvQueued;
return 0;
}
if (optlen == 2)
{
*(Word *)optval = e->sr.srRcvQueued;
return 0;
}
break;
#endif
#ifdef SO_NWRITE
case SO_NWRITE:
IncBusy();
terr = TCPIPStatusTCP(e->ipid, &e->sr);
t = _toolErr;
DecBusy();
if (t) terr = t;
if (optlen == 4)
{
*(LongWord *)optval = e->sr.srSndQueued;
return 0;
}
if (optlen == 2)
{
*(Word *)optval = e->sr.srSndQueued;
return 0;
}
return EINVAL;
break;
#endif
}
return EINVAL;
}

125
msetsockopt.c Normal file
View File

@ -0,0 +1,125 @@
#include "marignotti.h"
#include <gno/kerntool.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/time.h>
#pragma noroot
#pragma optimize 79
static LongWord timeval_to_ticks(struct timeval tv)
{
LongWord rv;
rv = 0;
if (tv.tv_usec || tv.tv_sec)
{
if (tv.tv_sec)
rv = 60 * tv.tv_sec;
// usec = 1/1,000,000
// split into 60
if (tv.tv_usec)
rv += ((tv.tv_usec + 16666) / 16667);
if (!rv) rv = 1;
}
return rv;
}
int msetsockopt(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
{
Word terr;
Word t;
int level = *(int *)p1;
int optname = *(int *)p2;
void *optval = (void *)p3;
int optlen = p4 ? *(int *)p4 : 0;
if (level != SOL_SOCKET) return EINVAL;
if (!optval) return EINVAL;
// todo -- linger.
// todo -- oobinline (error if 0?)
switch(optname)
{
case SO_OOBINLINE:
if (optlen == 4)
{
Word flag = *(LongWord *)optval;
if (!flag) return EINVAL;
return 0;
}
if (optlen == 2)
{
Word flag = *(Word *)optval;
if (!flag) return EINVAL;
return 0;
}
if (optlen == 1)
{
Word flag = *(char *)optval;
if (!flag) return EINVAL;
return 0;
}
break;
case SO_SNDLOWAT:
if (optlen == 4)
{
e->_SNDLOWAT = *(LongWord *)optval;
return 0;
}
if (optlen == 2)
{
e->_SNDLOWAT = *(Word *)optval;
return 0;
}
break;
case SO_RCVLOWAT:
if (optlen == 4)
{
e->_RCVLOWAT = *(LongWord *)optval;
return 0;
}
if (optlen == 2)
{
e->_RCVLOWAT = *(Word *)optval;
return 0;
}
break;
case SO_SNDTIMEO:
if (optlen == sizeof(struct timeval))
{
// stored as ticks aka seconds * 60.
struct timeval *tv = (struct timeval *)optval;
e->_SNDTIMEO = timeval_to_ticks(*tv);
return 0;
}
break;
case SO_RCVTIMEO:
if (optlen == sizeof(struct timeval))
{
// stored as ticks aka seconds * 60.
struct timeval *tv = (struct timeval *)optval;
e->_RCVTIMEO = timeval_to_ticks(*tv);
return 0;
}
break;
}
return EINVAL;
}