/* * 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 #include #include #include #include #include #include #define LISTEN_BACKLOG 5 static int XR_PIDForFildes(); static int XR_NSSTCPConditionStreamFildes(sock) XR_Fildes 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 = XR_FCntl(sock, F_SETOWN, XR_PIDForFildes(sock)); if( ans >= 0 ) ans = XR_SetGetTimeout(sock, XR_WAIT_FOREVER_MSEC); if( ans >= 0 ) ans = XR_SetPutTimeout(sock, XR_WAIT_FOREVER_MSEC); if( ans >= 0 ) ans = XR_SetGetBlocking(sock, XR_UIO_BLOCKING_SOME_DATA); if( ans >= 0 ) ans = XR_SetPutBlocking(sock, XR_UIO_BLOCKING_ALL_DATA); return ans; } int howFailed = 0; int failedErrno = 0; XR_Fildes XR_NSSTCPCreateStreamFildes(inap, timeout) struct sockaddr_in *inap; unsigned timeout; { XR_Fildes 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_Connect( 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_Close(sock); XR_SetErrno(savedErrno); } return XR_nullFildes; } int XR_NSSTCPDestroyStreamFildes(sock, abort) XR_Fildes 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_ConsoleMsg("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_ConsoleMsg("Can't shutdown socket %d, err %d\n", sock, XR_GetErrno() ); } ans = XR_Close(sock); if( ans == -1 ) XR_ConsoleMsg("Can't close socket %d, err %d\n", sock, XR_GetErrno() ); return ans; } int XR_NSSTCPAddressesFromStreamFildes(sock, local, remote) XR_Fildes 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_Fildes sock; char *buf; int nBytes; { return XR_Write(sock, buf, nBytes); } int XR_NSSTCPSendAttn(sock, attnType) XR_Fildes 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_Fildes sock; char *buf; int nBytes; { return XR_Read(sock, buf, nBytes); } int XR_NSSTCPInputReady(sock, timeout) XR_Fildes 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_Fildes 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_Fildes sock; { int ans; int atMarkResult = 0; ans = XR_IOCtl(sock, SIOCATMARK, &atMarkResult); return ( (ans >= 0) ? atMarkResult : ans ); } XR_Fildes XR_NSSTCPCreateListenerFildes(inap) struct sockaddr_in *inap; { XR_Fildes listener = XR_nullFildes; int ans; listener = XR_Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if( listener == XR_nullFildes ) goto Bad; ans = XR_Bind(listener, inap, (sizeof (*inap))); if( ans < 0 ) goto Bad; ans = XR_Listen(listener, LISTEN_BACKLOG); if( ans < 0 ) goto Bad; return listener; Bad: if( listener != XR_nullFildes ) { int savedErrno = XR_GetErrno(); (void) XR_Close(listener); XR_SetErrno(savedErrno); } return XR_nullFildes; } int XR_NSSTCPDestroyListenerFildes(listener) XR_Fildes listener; { return XR_Close(listener); } int XR_NSSTCPAddressFromListenerFildes(listener, local) XR_Fildes 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_Fildes XR_NSSTCPAccept(listener) XR_Fildes listener; { XR_Fildes sock; struct sockaddr_in a; int alen = (sizeof a); int ans; sock = XR_Accept(listener, &a, &alen); ans = XR_NSSTCPConditionStreamFildes(sock); if( ans < 0 ) return XR_nullFildes; return sock; } /* * For debugging */ struct sockaddr_in * XR_DB_NewSockAddr(a, b, c, d, p) int a, b, c, d, p; { struct sockaddr_in *sin; unsigned w; sin = (struct sockaddr_in *) XR_calloc( sizeof(struct sockaddr_in), 1); sin->sin_family = AF_INET; sin->sin_port = htons(((short)(p))); w = (a << 24) + (b << 16) + (c << 8) + d; sin->sin_addr.s_addr = htonl(w); return sin; } char * XR_DB_StringFromSockAddr(sin) struct sockaddr_in *sin; { char *s; unsigned w; s = (char *)XR_malloc(64); w = ntohl(sin->sin_addr.s_addr); (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 XR_FDEState; #define XR_FDC struct XR_FDCRep * #define XR_FDE struct XR_FDERep * typedef struct XR_FDERep { int fde_index; unsigned fde_gen; /* generation number */ int fde_opCnt; /* # ops in progress */ XR_FDEState fde_state; XR_IOPE fde_owner; /* IOP that owns descriptor */ int fde_ownerIndex; /* owner's descriptor index */ XR_FDKind fde_fdKind; /* 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_FDC fde_fdc; /* -> cached fdc or NIL */ struct XR_CVRep fde_avail; /* wait here e.g. for FDC */ #undef XR_FDE } * XR_FDE; #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_FDE uioa_fde; int uioa_numFDE; # define XR_UIOFDELimit \ (&(XR_uioArea->uioa_fde[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_Fildes fd; { if( XR_uioArea == NIL ) /* not an XR system */ return XR_GetPID(); return (XR_uioArea->uioa_fde[fd].fde_owner->iope_pid); }  9NewlineDelimiter JJ5J$$