📄 connection.c
字号:
struct itimerval itv; signal(SIGALRM, TimeOut); fTimeOut = FALSE; /* only 1 alarm, please, not 1 per minute */ timerclear(&itv.it_interval); itv.it_value.tv_sec = TimeOutValue; itv.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itv, (struct itimerval *)NULL); /* It better not take a full minute to get to the read call */ while (charsWanted && (fTimeOut = setjmp(env)) == FALSE) {#ifdef ISOCONN got = SRead(conn, bptr, charsWanted, NOTOK);#else /* ISOCONN */ got = read(conn, bptr, charsWanted); #endif /* ISOCONN */ if (got <= 0) return FALSE; if(got > 0) { charsWanted -= got; bptr += got; /* Ok, we got something, reset the timer */ itv.it_value.tv_sec = TimeOutValue; itv.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itv, (struct itimerval *)NULL); } } /* disable the timer */ timerclear(&itv.it_value); setitimer(ITIMER_REAL, &itv, (struct itimerval *)NULL); /* If we got here and we didn't time out, then return TRUE, because * we must have read what we wanted. If we timed out, return FALSE */ if(fTimeOut && debug_conns) ErrorF("Timed out on connection %d\n", conn); return (!fTimeOut);}#ifdef ISOCONN/* * Who's calling us? */getISOpeername (conn, from, alen) int conn;struct TSAPaddr *from;int *alen;{ struct TSAPdisconnect td; if (TGetAddresses (conn, from, NULLTA, &td) == NOTOK) { Error(TErrString(td.td_reason)); return TRUE; }; *alen = sizeof(struct TSAPaddr); return FALSE;}#endif /* ISOCONN *//***************************************************************** * ClientAuthorized * * Sent by the client at connection setup: * typedef struct _xConnClientPrefix { * CARD8 byteOrder; * BYTE pad; * CARD16 majorVersion, minorVersion; * CARD16 nbytesAuthProto; * CARD16 nbytesAuthString; * } xConnClientPrefix; * * It is hoped that eventually one protocol will be agreed upon. In the * mean time, a server that implements a different protocol than the * client expects, or a server that only implements the host-based * mechanism, will simply ignore this information. * *****************************************************************/int ClientAuthorized(conn, pswapped, reason) long conn; int *pswapped; char **reason; /* if authorization fails, put reason in here */{ short slen; union { struct sockaddr sa;#ifdef UNIXCONN struct sockaddr_un un;#endif /* UNIXCONN */#ifdef TCPCONN struct sockaddr_in in;#endif /* TCPCONN */#ifdef DNETCONN struct sockaddr_dn dn;#endif /* DNETCONN */#ifdef ISOCONN struct TSAPaddr ts;#endif /* ISOCONN */ } from; int fromlen; xConnClientPrefix xccp; char auth_proto[100]; char auth_string[100];#ifdef ISOCONN/* * For now we always auth an ISO client!! * should use directory etc etc */ *reason = 0;#endif /* ISOCONN */ if (!ReadBuffer(conn, (char *)&xccp, sizeof(xConnClientPrefix))) { /* If they can't even give us this much, just blow them off * without an error message */ *reason = 0; return 0; } if (xccp.byteOrder != whichByteIsFirst) { SwapConnClientPrefix(&xccp); *pswapped = TRUE; } else *pswapped = FALSE; if ((xccp.majorVersion != X_PROTOCOL) || (xccp.minorVersion != X_PROTOCOL_REVISION)) { #define STR "Protocol version mismatch" *reason = (char *)xalloc(sizeof(STR)); strcpy(*reason, STR); if (debug_conns) ErrorF("%s\n", STR);#undef STR return 0; } fromlen = sizeof (from);#ifdef ISOCONN if (SGetPeerName (conn, &(from.ts), &fromlen) || InvalidHost (&(from.ts), fromlen)) #else /* ISOCONN */ if (getpeername (conn, &from.sa, &fromlen) || InvalidHost (&from.sa, fromlen)) #endif /* ISOCONN */ {#define STR "Server is not authorized to connect to host" *reason = (char *)xalloc(sizeof(STR)); strcpy(*reason, STR);#undef STR return 0; } slen = (xccp.nbytesAuthProto + 3) & ~3; if ( slen ) if (!ReadBuffer(conn, auth_proto, slen)) {#define STR "Length error in xConnClientPrefix for protocol authorization " *reason = (char *)xalloc(sizeof(STR)); strcpy(*reason, STR); return 0;#undef STR } auth_proto[slen] = '\0'; slen = (xccp.nbytesAuthString + 3) & ~3; if ( slen) if (!ReadBuffer(conn, auth_string, slen)) {#define STR "Length error in xConnClientPrefix for protocol string" *reason = (char *)xalloc(sizeof(STR)); strcpy(*reason, STR); return 0;#undef STR } auth_string[slen] = '\0'; /* At this point, if the client is authorized to change the access control * list, we should getpeername() information, and add the client to * the selfhosts list. It's not really the host machine, but the * true purpose of the selfhosts list is to see who may change the * access control list. */ return(1);} static int padlength[4] = {0, 3, 2, 1};/***************** * EstablishNewConnections * If anyone is waiting on listened sockets, accept them. * Returns a mask with indices of new clients. Updates AllClients * and AllSockets. *****************/void#ifdef ISOCONNEstablishNewConnections(newclients, nnew, vecp, vec) ClientPtr *newclients; int *nnew; int vecp; char **vec;#else /* ISOCONN */EstablishNewConnections(newclients, nnew) ClientPtr *newclients; int *nnew;#endif /* ISOCONN */{ long readyconnections; /* mask of listeners that are ready */ long curconn; /* fd of listener that's ready */ long newconn; /* fd of new client */ int swapped; /* set by ClientAuthorized if connection is * swapped */ char *reason; struct iovec iov[2];#ifdef ISOCONN struct udvec uv[3]; struct TSAPdisconnect tds; struct TSAPdisconnect *td = &tds; struct TSAPstart tsts; struct TSAPstart *tst = &tsts;#endif /* ISOCONN */ char p[3];#ifdef TCP_NODELAY union { struct sockaddr sa;#ifdef UNIXCONN struct sockaddr_un un;#endif /* UNIXCONN */#ifdef TCPCONN struct sockaddr_in in;#endif /* TCPCONN */#ifdef DNETCONN struct sockaddr_dn dn;#endif /* DNETCONN */ } from; int fromlen;#endif TCP_NODELAY *nnew = 0; if (readyconnections = (LastSelectMask[0] & WellKnownConnections)) { while (readyconnections) { curconn = ffs (readyconnections) - 1;#ifdef ISOCONN /* * At this point, a TAccept has finished with a vec > 0 * so we need to init them... */ if ((newconn = SAccept(curconn, vecp, vec)) >= 0) { fd2family[newconn] = ISODE_IO;#else /* ISOCONN */ if ((newconn = accept (curconn, (struct sockaddr *) NULL, (int *)NULL)) >= 0) { fd2family[newconn] = UNIX_IO;#endif /* ISOCONN */ if (newconn >= lastfdesc) { if (debug_conns)ErrorF("Didn't make connection: Out of file descriptors for connections\n");#ifdef ISOCONN SClose(newconn);#else /* ISOCONN */ close (newconn);#endif /* ISOCONN */ } else { ClientPtr next = (ClientPtr)NULL;#ifdef TCP_NODELAY#ifdef ISOCONN if (fd2family(newconn) == UNIX_IO) {#endif /* ISOCONN */ fromlen = sizeof (from); if (!getpeername (newconn, &from.sa, &fromlen)) { if (fromlen && (from.sa.sa_family == AF_INET)) { int mi = 1; setsockopt (newconn, IPPROTO_TCP, TCP_NODELAY, (char *)&mi, sizeof (int)); } }#ifdef ISOCONN }#endif /* ISOCONN */#endif /* TCP_NODELAY */ if (ClientAuthorized(newconn, &swapped, &reason)) {#ifdef hpux /* * HPUX does not have FNDELAY */ { int arg; arg = 1; ioctl(newconn, FIOSNBIO, &arg); }#else fcntl (newconn, F_SETFL, FNDELAY);#endif /* hpux */ inputBuffers[newconn].used = 1; if (! inputBuffers[newconn].size) { inputBuffers[newconn].buffer = (char *)xalloc(BUFSIZE); inputBuffers[newconn].size = BUFSIZE; inputBuffers[newconn].bufptr = inputBuffers[newconn].buffer; } if (GrabDone) { BITSET(SavedAllClients, newconn); BITSET(SavedAllSockets, newconn); } else { BITSET(AllClients, newconn); BITSET(AllSockets, newconn); } next = NextAvailableClient(); if (next != (ClientPtr)NULL) { OsCommPtr priv; newclients[(*nnew)++] = next; next->swapped = swapped; ConnectionTranslation[newconn] = next; priv = (OsCommPtr)xalloc(sizeof(OsCommRec)); priv->fd = newconn; priv->buf = (unsigned char *) xalloc(OutputBufferSize); priv->bufsize = OutputBufferSize; priv->count = 0; next->osPrivate = (pointer)priv; } else {#define STR "Maximum number of clients exceeded" reason = (char *)xalloc(sizeof(STR)); strcpy(reason, STR);#undef STR } } if (next == (ClientPtr)NULL) { xConnSetupPrefix c; if(reason) { c.success = xFalse; c.lengthReason = strlen(reason); c.length = (c.lengthReason + 3) >> 2; c.majorVersion = X_PROTOCOL; c.minorVersion = X_PROTOCOL_REVISION; if(swapped) { int n; swaps(&c.majorVersion, n); swaps(&c.minorVersion, n); swaps(&c.length, n); }#ifdef ISOCONN (void)SWrite(newconn, (char *)&c, sizeof(xConnSetupPrefix)); #else /* ISOCONN */ write(newconn, (char *)&c, sizeof(xConnSetupPrefix)); #endif /* ISOCONN */ iov[0].iov_len = c.lengthReason; iov[0].iov_base = reason; iov[1].iov_len = padlength[c.lengthReason & 3]; iov[1].iov_base = p;#ifdef ISOCONN SWritev(newconn, iov, 2);#else /* ISOCONN */ writev(newconn, iov, 2);#endif /* ISOCONN */ if (debug_conns) ErrorF("Didn't make connection:%s\n", reason); }#ifdef ISOCONN SClose(newconn);#else /* ISOCONN */ close(newconn);#endif /* ISOCONN */ xfree(reason); } } } readyconnections &= ~(1 << curconn); } }}/************ * CloseDownFileDescriptor: * Remove this file descriptor and it's inputbuffers, etc. ************/voidCloseDownFileDescriptor(connection) int connection;{#ifdef ISOCONN struct TSAPdisconnect tds;#ifdef ISODEBUG if (isodexbug) fprintf(stderr, "server: TDiscReq\n");#endif /* ISODEBUG */ SClose(connection);#else /* ISOCONN */ close(connection);#endif /* ISOCONN */ if (inputBuffers[connection].size) { xfree(inputBuffers[connection].buffer); inputBuffers[connection].buffer = (char *) NULL; inputBuffers[connection].bufptr = (char *) NULL; inputBuffers[connection].size = 0; } inputBuffers[connection].bufcnt = 0; inputBuffers[connection].lenLastReq = 0; inputBuffers[connection].used = 0; BITCLEAR(AllSockets, connection); BITCLEAR(AllClients, connection); BITCLEAR(ClientsWithInput, connection); BITCLEAR(ClientsWriteBlocked, connection); if (!ANYSET(ClientsWriteBlocked)) AnyClientsWriteBlocked = FALSE;}/***************** * CheckConections * Some connection has died, go find which one and shut it down * The file descriptor has been closed, but is still in AllClients. * If would truly be wonderful if select() would put the bogus * file descriptors in the exception mask, but nooooo. So we have * to check each and every socket individually. *****************/voidCheckConnections(){ long mask[mskcnt]; long tmask[mskcnt]; register int curclient; int i; struct timeval notime; ClientPtr bad; int r;#ifdef ISOCONN struct TSAPdisconnect tds; struct TSAPdisconnect *td = &tds; char *vec[4]; int vecp;#endif /* ISOCONN */ notime.tv_sec = 0; notime.tv_usec = 0; COPYBITS(AllClients, mask); for (i=0; i<mskcnt; i++) { while (mask[i]) { curclient = ffs (mask[i]) - 1 + (i << 5); CLEARBITS(tmask); BITSET(tmask, curclient);#ifdef ISOCONN r = TNetAccept (&vecp, vec, curclient + 1, tmask, (int *)NULL, (int *)NULL, OK, td); if (r == NOTOK) { Error(TErrString(td->td_reason)); Error("TNetAccept");#else /* ISOCONN */ r = select (curclient + 1, tmask, (int *)NULL, (int *)NULL, ¬ime); if (r < 0) {#endif /* ISOCONN */ if (bad = ConnectionTranslation[curclient]) CloseDownClient(bad); else CloseDownFileDescriptor(curclient); } BITCLEAR(mask, curclient); } } }/***************** * CloseDownConnection * Delete client from AllClients and free resources *****************/CloseDownConnection(client) ClientPtr client;{ OsCommPtr oc = (OsCommPtr)client->osPrivate; ConnectionTranslation[oc->fd] = (ClientPtr)NULL; CloseDownFileDescriptor(oc->fd); if (oc->buf != NULL) /* an Xrealloc may have returned NULL */ xfree(oc->buf); xfree(client->osPrivate);}AddEnabledDevice(fd) int fd;{ EnabledDevices |= (1<<fd); BITSET(AllSockets, fd);}RemoveEnabledDevice(fd) int fd;{ EnabledDevices &= ~(1<<fd); BITCLEAR(AllSockets, fd);}/***************** * OnlyListenToOneClient: * Only accept requests from one client. Continue to handle new * connections, but don't take any protocol requests from the new * ones. Note that if GrabDone is set, EstablishNewConnections * needs to put new clients into SavedAllSockets and SavedAllClients. * Note also that there is no timeout for this in the protocol. * This routine is "undone" by ListenToAllClients() *****************/OnlyListenToOneClient(client) ClientPtr client;{ OsCommPtr oc = (OsCommPtr)client->osPrivate; int connection = oc->fd; if (! GrabDone) { COPYBITS (ClientsWithInput, SavedClientsWithInput); BITCLEAR (SavedClientsWithInput, connection); if (GETBIT(ClientsWithInput, connection)) { CLEARBITS(ClientsWithInput); BITSET(ClientsWithInput, connection); } else { CLEARBITS(ClientsWithInput); } COPYBITS(AllSockets, SavedAllSockets); COPYBITS(AllClients, SavedAllClients); UNSETBITS(AllSockets, AllClients); BITSET(AllSockets, connection); CLEARBITS(AllClients); BITSET(AllClients, connection); GrabDone = TRUE; }}/**************** * ListenToAllClients: * Undoes OnlyListentToOneClient() ****************/ListenToAllClients(){ if (GrabDone) { ORBITS(AllSockets, AllSockets, SavedAllSockets); ORBITS(AllClients, AllClients, SavedAllClients); ORBITS(ClientsWithInput, ClientsWithInput, SavedClientsWithInput); GrabDone = FALSE; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -