/*
* NetworkStreamSupportTCPGlue.c
*
* Demers, November 6, 1989 3:35:46 pm PST
*
* C support for TCP network streams in PCR
*/
#include "xr/Errno.h"
#include "xr/UIO.h"
#include <sys/types.h>
#include <sys/fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <poll.h>
#define LISTENKLOG 5
static int
XR←PIDForFildes();
static int
XR←NSSTCPConditionStreamFildes(sock)
XR𡤏ildes sock;
{
int ans;
int one = 1;
ans = XR←SetSockOpt(sock, SOL←SOCKET, SO←OOBINLINE, &one, (sizeof one));
if( ans >= 0 )
ans = XR←SetSockOpt(sock, IPPROTO←TCP, TCP←NODELAY, &one, (sizeof one));
/* This should go away when XR is fixed to do the SETOWN at socket */
/* creation. */
if( ans >= 0 )
ans = XRntl(sock, F←SETOWN, XR←PIDForFildes(sock));
if( ans >= 0 )
ans = XR←SetGetTimeout(sock, XR←WAIT𡤏OREVER←MSEC);
if( ans >= 0 )
ans = XR←SetPutTimeout(sock, XR←WAIT𡤏OREVER←MSEC);
if( ans >= 0 )
ans = XR←SetGetBlocking(sock, XR←UIO𡤋LOCKING←SOMETA);
if( ans >= 0 )
ans = XR←SetPutBlocking(sock, XR←UIO𡤋LOCKING𡤊LLTA);
return ans;
}
int howFailed = 0;
int failedErrno = 0;
XR𡤏ildes
XR←NSSTCPCreateStreamFildes(inap, timeout)
struct sockaddr←in *inap;
unsigned timeout;
{
XR𡤏ildes sock = XR←nullFildes;
int one = 1;
int ans;
# define GoToBad(x) { howFailed = (x); goto Bad; }
sock = XR←Socket(PF←INET, SOCK←STREAM, IPPROTO←TCP);
if( sock == XR←nullFildes ) GoToBad(1);
ans = XR←SetPutTimeout( sock, timeout );
if( ans < 0 ) GoToBad(2);
ans = XR𡤌onnect( sock, inap, (sizeof (*inap)) );
if( ans < 0 ) GoToBad(3);
ans = XR←NSSTCPConditionStreamFildes(sock);
if( ans < 0 ) GoToBad(4);
return sock;
Bad:
failedErrno = XR←GetErrno();
if( sock != XR←nullFildes ) {
int savedErrno = XR←GetErrno();
(void) XR𡤌lose(sock);
XR←SetErrno(savedErrno);
}
return XR←nullFildes;
}
int
XR←NSSTCPDestroyStreamFildes(sock, abort)
XR𡤏ildes sock;
bool abort;
{
# define NO←SEND←OR←RECV 2
struct linger sol;
int ans = 0;
if( abort ) {
sol.l←onoff = FALSE; /* dont linger */
sol.l←linger = 0; /* for 0 msec */
ans = XR←SetSockOpt(sock, SOL←SOCKET, SO←LINGER, &sol, (sizeof sol));
if( ans == -1 ) XR𡤌onsoleMsg("Can't set DONTLINGER on socket %d, err %d\n",
sock, XR←GetErrno() );
}
if( ans != -1 ) {
ans = XR←Shutdown(sock, NO←SEND←OR←RECV);
if( ans == -1 ) XR𡤌onsoleMsg("Can't shutdown socket %d, err %d\n",
sock, XR←GetErrno() );
}
ans = XR𡤌lose(sock);
if( ans == -1 ) XR𡤌onsoleMsg("Can't close socket %d, err %d\n",
sock, XR←GetErrno() );
return ans;
}
int
XR←NSSTCPAddressesFromStreamFildes(sock, local, remote)
XR𡤏ildes sock;
struct sockaddr←in *local;
struct sockaddr←in *remote;
{
int addrLen;
struct sockaddr←in al, ar;
int ans;
addrLen = (sizeof ar);
ans = XR←GetPeerName(sock, &ar, &addrLen);
if( ans < 0 ) return(-1);
if( addrLen != (sizeof ar) ) { XR←SetErrno(EINVAL); return(-1); }
addrLen = (sizeof al);
ans = XR←GetSockName(sock, &al, &addrLen);
if( ans < 0 ) return(-1);
if( addrLen != (sizeof al) ) { XR←SetErrno(EINVAL); return(-1); }
*local = al;
*remote = ar;
return 0;
}
int
XR←NSSTCPSend(sock, buf, nBytes)
XR𡤏ildes sock;
char *buf;
int nBytes;
{
return XR←Write(sock, buf, nBytes);
}
int
XR←NSSTCPSendAttn(sock, attnType)
XR𡤏ildes sock;
int attnType;
{
int ans;
char buf;
if( attnType & 0xffffff00 ) {
XR←SetErrno(EINVAL);
return(-1);
}
buf = attnType;
ans = XR←Send(sock, &buf, (sizeof buf), MSG←OOB);
return ans;
}
int
XR←NSSTCPReceive(sock, buf, nBytes)
XR𡤏ildes sock;
char *buf;
int nBytes;
{
return XR←Read(sock, buf, nBytes);
}
int
XR←NSSTCPInputReady(sock, timeout)
XR𡤏ildes sock;
int timeout;
{
struct pollfd fds;
int ans;
fds.fd = sock;
fds.events = POLLIN;
fds.revents = 0;
ans = XR←Poll(&fds, 1, timeout);
if( ans > 0 ) return ((fds.revents & POLLIN) ? 1 : 0);
if( ans == 0 ) return 0;
if( XR←GetErrno() == ETIMEDOUT ) return 0; /* workaround for PCR bug */
return ans;
}
int
XR←NSSTCPWaitOOBAttn(sock, timeout)
XR𡤏ildes sock;
int timeout;
{
struct pollfd fds;
int ans;
fds.fd = sock;
fds.events = POLLPRI;
fds.revents = 0;
ans = XR←Poll(&fds, 1, timeout);
if( (ans > 0) && (fds.revents & POLLPRI) ) return 0;
if( ans == 0 ) {
XR←SetErrno(ETIMEDOUT);
return (-1);
}
return ans;
}
int
XR←NSSTCPAtIBAttn(sock)
XR𡤏ildes sock;
{
int ans;
int atMarkResult = 0;
ans = XR←IOCtl(sock, SIOCATMARK, &atMarkResult);
return ( (ans >= 0) ? atMarkResult : ans );
}
XR𡤏ildes
XR←NSSTCPCreateListenerFildes(inap)
struct sockaddr←in *inap;
{
XR𡤏ildes listener = XR←nullFildes;
int ans;
listener = XR←Socket(PF←INET, SOCK←STREAM, IPPROTO←TCP);
if( listener == XR←nullFildes ) goto Bad;
ans = XR𡤋ind(listener, inap, (sizeof (*inap)));
if( ans < 0 ) goto Bad;
ans = XR←Listen(listener, LISTENKLOG);
if( ans < 0 ) goto Bad;
return listener;
Bad:
if( listener != XR←nullFildes ) {
int savedErrno = XR←GetErrno();
(void) XR𡤌lose(listener);
XR←SetErrno(savedErrno);
}
return XR←nullFildes;
}
int
XR←NSSTCPDestroyListenerFildes(listener)
XR𡤏ildes listener;
{
return XR𡤌lose(listener);
}
int
XR←NSSTCPAddressFromListenerFildes(listener, local)
XR𡤏ildes listener;
struct sockaddr←in *local;
{
int addrLen;
struct sockaddr←in al;
int ans;
addrLen = (sizeof al);
ans = XR←GetSockName(listener, &al, &addrLen);
if( ans < 0 ) return(-1);
if( addrLen != (sizeof al) ) { XR←SetErrno(EINVAL); return(-1); }
*local = al;
return 0;
}
XR𡤏ildes
XR←NSSTCPAccept(listener)
XR𡤏ildes listener;
{
XR𡤏ildes sock;
struct sockaddr←in a;
int alen = (sizeof a);
int ans;
sock = XRpt(listener, &a, &alen);
ans = XR←NSSTCPConditionStreamFildes(sock);
if( ans < 0 ) return XR←nullFildes;
return sock;
}
/*
* For debugging
*/
struct sockaddr←in *
XR←NewSockAddr(a, b, c, d, p)
int a, b, c, d, p;
{
struct sockaddr←in *sin;
unsigned w;
sin = (struct sockaddr←in *) XRlloc( sizeof(struct sockaddr←in), 1);
sin->sinmily = AF←INET;
sin->sin←port = htons(((short)(p)));
w = (a << 24) + (b << 16) + (c << 8) + d;
sin->sinr.sr = htonl(w);
return sin;
}
char *
XR←StringFromSockAddr(sin)
struct sockaddr←in *sin;
{
char *s;
unsigned w;
s = (char *)XR←malloc(64);
w = ntohl(sin->sinr.sr);
(void)XR←SPrintF(s, "%d.%d.%d.%d:%d",
(w >> 24) & 0xff, (w >> 16) & 0xff, (w >> 8) & 0xff, w & 0xff,
ntohs(sin->sin←port) );
return s;
}
/*
* The rest of this file should go away when the XR system is fixed
* to do the SETOWN at socket-creation time.
* The following declarations are copied from "xr/ThreadsBackdoor.h"
*/
#define XR←IOPOrder struct XR←IOPOrderRep *
typedef struct XR←IOPERep {
unsigned iope←index; /* index of this iope in table */
unsigned iope←pid; /* UNIX pid, 0 if IOPE not in use */
} * XR←IOPE;
/*
* The following declarations are copied from "xr/UIOPrivate.h"
* to let XR←uioArea be a common symbol.
*/
typedef unsigned XRState;
#define XR struct XRRep *
#define XR struct XRRep *
typedef struct XRRep {
int fde←index;
unsigned fde←gen; /* generation number */
int fde←opCnt; /* # ops in progress */
XRState fde←state;
XR←IOPE fde←owner; /* IOP that owns descriptor */
int fde←ownerIndex; /* owner's descriptor index */
XRKind fdeKind; /* kind of associated descriptors */
/* (same as kind of IOP) */
XR←UIOBlocking fde←getBlocking; /* input blocking behavior */
XR←UIOBlocking fde←putBlocking; /* output blocking behavior */
XR←Ticks fde←getTimeout; /* input timeout */
XR←Ticks fde←putTimeout; /* output timeout */
bool fde←inputPri; /* poll input => pri */
XR fde /* -> cached fdc or NIL */
struct XR𡤌VRep fde𡤊vail; /* wait here e.g. for FDC */
#undef XR
} * XR
#define XR←UIOWDBuf struct XR←UIOWDBufRep *
typedef struct XR←UIOAreaRep {
/* monitor locks */
struct XR←MLRep uioa←ml;
struct XR←MLRep uioa←wdML;
/* PCR working directory cache */
XR←UIOWDBuf uioa←pcrWD;
/* IOPs */
XR←IOPE uioa←iope;
int uioa←numIOPE;
# define XR←UIOIOPELimit \
(&(XR←uioArea->uioa←iope[XR←uioArea->uioa←numIOPE]))
/* FDEs */
XR uioa
int uioa←numFDE;
# define XR←UIOFDELimit \
(&(XR←uioArea->uioa[XR←uioArea->uioa←numFDE]))
/*
* the rest of the structure is not needed ...
*/
} * XR←UIOArea;
XR←UIOArea XR←uioArea; /* readonly, shared */
/*
* The entire content of this file:
*/
static int
XR←PIDForFildes(fd)
XR𡤏ildes fd;
{
if( XR←uioArea == NIL ) /* not an XR system */ return XR←GetPID();
return (XR←uioArea->uioa[fd].fde←owner->iope←pid);
}