1 /* $TOG: connection.c /main/156 1997/06/05 18:43:01 sekhar $ */
2 /***********************************************************
4 Copyright (c) 1987, 1989 X Consortium
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of the X Consortium shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from the X Consortium.
28 Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
32 Permission to use, copy, modify, and distribute this software and its
33 documentation for any purpose and without fee is hereby granted,
34 provided that the above copyright notice appear in all copies and that
35 both that copyright notice and this permission notice appear in
36 supporting documentation, and that the name of Digital not be
37 used in advertising or publicity pertaining to distribution of the
38 software without specific, written prior permission.
40 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
41 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
42 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
43 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
44 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
45 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
48 ******************************************************************/
49 /* $XFree86: xc/programs/Xserver/os/connection.c,v 3.25.2.2 1997/07/05 15:55:45 dawes Exp $ */
50 /*****************************************************************
51 * Stuff to create connections --- OS dependent
53 * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
54 * CloseDownConnection, CheckConnections, AddEnabledDevice,
55 * RemoveEnabledDevice, OnlyListToOneClient,
58 * (WaitForSomething is in its own file)
60 * In this implementation, a client socket table is not kept.
61 * Instead, what would be the index into the table is just the
62 * file descriptor of the socket. This won't work for if the
63 * socket ids aren't small nums (0 - 2^8)
65 *****************************************************************/
68 #include <X11/Xwinsock.h>
72 #include <X11/Xtrans.h>
84 #include <sys/socket.h>
91 #include <sys/utsname.h>
92 #include <sys/ioctl.h>
96 #include <sys/ioctl.h>
100 #include <sys/nbio.h>
102 #define select(n,r,w,x,t) nbio_select(n,r,w,x,t)
106 #define select(n,r,w,x,t) os2PseudoSelect(n,r,w,x,t)
107 extern __const__ int _nfiles;
110 #if defined(TCPCONN) || defined(STREAMSCONN)
111 # include <netinet/in.h>
113 /*================================================================
114 BEGIN ORL VNC modification
115 include arpa/inet.h for inet_ntoa function prototype */
117 #include <arpa/inet.h>
119 /* END ORL VNC modification
120 ================================================================*/
125 # include <netinet/tcp.h>
129 # include <sys/param.h>
132 # include <netinet/tcp.h>
139 #include <server/ip/types.h>
140 #include <server/ip/gen/in.h>
141 #include <server/ip/gen/inet.h>
144 #if !defined(AMOEBA) && !defined(_MINIX) && !defined(__EMX__)
152 #include "misc.h" /* for typedef of pointer */
153 #include <X11/Xpoll.h>
156 #include "dixstruct.h"
158 #include "extensions/Xagsrv.h"
161 #define _SECURITY_SERVER
162 #include "extensions/security.h"
165 #include "lbxserve.h"
175 #include <netdnet/dn.h>
176 #endif /* DNETCONN */
178 extern char *display; /* The display number */
179 int lastfdesc; /* maximum file descriptor */
181 fd_set WellKnownConnections; /* Listener mask */
182 fd_set EnabledDevices; /* mask for input devices that are on */
183 fd_set AllSockets; /* select on this */
184 fd_set AllClients; /* available clients */
185 fd_set LastSelectMask; /* mask returned from last select call */
186 fd_set ClientsWithInput; /* clients with FULL requests in buffer */
187 fd_set ClientsWriteBlocked; /* clients who cannot receive output */
188 fd_set OutputPending; /* clients with reply/event data ready to go */
189 int MaxClients = MAXSOCKS;
190 Bool NewOutputPending; /* not yet attempted to write some new output */
191 Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
193 Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
194 Bool PartialNetwork; /* continue even if unable to bind all addrs */
195 char *protNoListen; /* don't listen on this protocol */
196 static Pid_t ParentProcess;
198 static Bool debug_conns = FALSE;
200 fd_set IgnoredClientsWithInput;
201 static fd_set GrabImperviousClients;
202 static fd_set SavedAllClients;
203 static fd_set SavedAllSockets;
204 static fd_set SavedClientsWithInput;
205 int GrabInProgress = 0;
208 int ConnectionTranslation[MAXSOCKS];
211 * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is
212 * not even a known maximum value, so use something quite arbitrary for now.
213 * This is clearly boggus and another form of storage which doesn't use the fd
214 * as a direct index should really be implemented for NT.
217 int ConnectionTranslation[MAXFD];
220 XtransConnInfo *ListenTransConns = NULL;
221 int *ListenTransFds = NULL;
222 int ListenTransCount;
224 extern int auditTrailLevel;
226 static void ErrorConnMax(
227 #if NeedFunctionPrototypes
228 XtransConnInfo /* trans_conn */
235 void CloseDownFileDescriptor(
236 #if NeedFunctionPrototypes
240 register OsCommPtr /*oc*/
246 extern int LbxFlushClient();
247 extern void LbxCloseClient();
250 static XtransConnInfo
251 lookup_trans_conn (fd)
257 for (i = 0; i < ListenTransCount; i++)
258 if (ListenTransFds[i] == fd)
259 return ListenTransConns[i];
266 void XdmcpOpenDisplay(), XdmcpInit(), XdmcpReset(), XdmcpCloseDisplay();
270 * CreateWellKnownSockets
271 * At initialization, create the sockets to listen on for new clients.
275 CreateWellKnownSockets()
281 FD_ZERO(&AllSockets);
282 FD_ZERO(&AllClients);
283 FD_ZERO(&LastSelectMask);
284 FD_ZERO(&ClientsWithInput);
287 for (i=0; i<MAXSOCKS; i++) ConnectionTranslation[i] = 0;
289 for (i=0; i<MAXFD; i++) ConnectionTranslation[i] = 0;
291 #ifdef XNO_SYSCONF /* should only be on FreeBSD 1.x and NetBSD 0.x */
296 lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
298 #ifdef hpux /* || defined(__EMX__) ? */
299 lastfdesc = _NFILE - 1;
301 lastfdesc = getdtablesize() - 1;
305 lastfdesc = _nfiles - 1;
308 if (lastfdesc > MAXSOCKS)
310 lastfdesc = MAXSOCKS;
312 ErrorF( "GOT TO END OF SOCKETS %d\n", MAXSOCKS);
315 FD_ZERO (&WellKnownConnections);
317 sprintf (port, "%d", atoi (display));
320 if (_XSERVTransNoListen(protNoListen))
322 FatalError ("Failed to disable listen for %s", protNoListen);
325 if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
326 &ListenTransCount, &ListenTransConns) >= 0) &&
327 (ListenTransCount >= 1))
329 if (!PartialNetwork && partial)
331 FatalError ("Failed to establish all listening sockets");
335 ListenTransFds = (int *) xalloc (ListenTransCount * sizeof (int));
337 for (i = 0; i < ListenTransCount; i++)
339 int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
341 ListenTransFds[i] = fd;
342 FD_SET (fd, &WellKnownConnections);
344 if (!_XSERVTransIsLocal (ListenTransConns[i]))
352 if (!XFD_ANYSET (&WellKnownConnections))
353 FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
355 OsSignal (SIGPIPE, SIG_IGN);
356 OsSignal (SIGHUP, AutoResetServer);
358 OsSignal (SIGINT, GiveUp);
359 OsSignal (SIGTERM, GiveUp);
360 XFD_COPYSET (&WellKnownConnections, &AllSockets);
363 * Magic: If SIGUSR1 was set to SIG_IGN when
364 * the server started, assume that either
366 * a- The parent process is ignoring SIGUSR1
370 * b- The parent process is expecting a SIGUSR1
371 * when the server is ready to accept connections
373 * In the first case, the signal will be harmless,
374 * in the second case, the signal will be quite
378 /*================================================================
379 BEGIN ORL VNC modification
380 Don't use SIGUSR1 - linuxthread uses this internally */
382 /* apparently no longer true. */
384 if (OsSignal (SIGUSR1, SIG_IGN) == SIG_IGN)
385 RunFromSmartParent = TRUE;
386 ParentProcess = getppid ();
387 if (RunFromSmartParent) {
388 if (ParentProcess > 0) {
389 kill (ParentProcess, SIGUSR1);
394 /* END ORL VNC modification
395 ================================================================*/
403 ResetWellKnownSockets ()
409 for (i = 0; i < ListenTransCount; i++)
411 int status = _XSERVTransResetListener (ListenTransConns[i]);
413 if (status != TRANS_RESET_NOOP)
415 if (status == TRANS_RESET_FAILURE)
418 * ListenTransConns[i] freed by xtrans.
419 * Remove it from out list.
422 FD_CLR (ListenTransFds[i], &WellKnownConnections);
423 ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
424 ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
425 ListenTransCount -= 1;
428 else if (status == TRANS_RESET_NEW_FD)
431 * A new file descriptor was allocated (the old one was closed)
434 int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
436 FD_CLR (ListenTransFds[i], &WellKnownConnections);
437 ListenTransFds[i] = newfd;
438 FD_SET(newfd, &WellKnownConnections);
443 ResetAuthorization ();
446 * See above in CreateWellKnownSockets about SIGUSR1
449 /*================================================================
450 BEGIN ORL VNC modification
451 Don't use SIGUSR1 - linuxthread uses this internally */
453 if (RunFromSmartParent) {
454 if (ParentProcess > 0) {
455 kill (ParentProcess, SIGUSR1);
459 /* END ORL VNC modification
460 ================================================================*/
471 AuthAudit (client, letin, saddr, len, proto_n, auth_proto, auth_id)
474 struct sockaddr *saddr;
476 unsigned short proto_n;
483 if (!((OsCommPtr)client->osPrivate)->trans_conn) {
484 strcpy(addr, "LBX proxy at ");
488 strcpy(out, "local host");
490 switch (saddr->sa_family)
493 #if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
496 strcpy(out, "local host");
498 #if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
500 sprintf(out, "IP %s port %d",
501 inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr),
502 ntohs(((struct sockaddr_in *) saddr)->sin_port));
507 sprintf(out, "DN %s",
508 dnet_ntoa(&((struct sockaddr_dn *) saddr)->sdn_add));
513 sprintf(addr, "AM %s", saddr);
516 #if defined(AMTCPCONN) && !(defined(TCPCONN) || defined(STREAMSCONN))
518 sprintf(addr, "AMIP %s", inet_ntoa(*((ipaddr_t *) saddr)));
522 strcpy(out, "unknown address");
525 AuditF("client %d connected from %s\n", client->index, addr);
527 AuditF("client %d rejected from %s\n", client->index, addr);
529 AuditF(" Auth name: %.*s ID: %d\n", proto_n, auth_proto, auth_id);
533 AuthorizationIDOfClient(client)
536 if (client->osPrivate)
537 return ((OsCommPtr)client->osPrivate)->auth_id;
543 /*****************************************************************
546 * Sent by the client at connection setup:
547 * typedef struct _xConnClientPrefix {
550 * CARD16 majorVersion, minorVersion;
551 * CARD16 nbytesAuthProto;
552 * CARD16 nbytesAuthString;
553 * } xConnClientPrefix;
555 * It is hoped that eventually one protocol will be agreed upon. In the
556 * mean time, a server that implements a different protocol than the
557 * client expects, or a server that only implements the host-based
558 * mechanism, will simply ignore this information.
560 *****************************************************************/
563 ClientAuthorized(client, proto_n, auth_proto, string_n, auth_string)
565 char *auth_proto, *auth_string;
566 unsigned int proto_n, string_n;
568 register OsCommPtr priv;
569 Xtransaddr *from = NULL;
574 XtransConnInfo trans_conn;
576 auth_id = CheckAuthorization (proto_n, auth_proto,
577 string_n, auth_string, client, &reason);
579 priv = (OsCommPtr)client->osPrivate;
580 trans_conn = priv->trans_conn;
583 ClientPtr lbxpc = LbxProxyClient(priv->proxy);
584 trans_conn = ((OsCommPtr)lbxpc->osPrivate)->trans_conn;
585 if (auth_id == (XID) ~0L && !GetAccessControl())
586 auth_id = ((OsCommPtr)lbxpc->osPrivate)->auth_id;
588 else if (auth_id != (XID) ~0L && !SecuritySameLevel(lbxpc, auth_id)) {
590 reason = "Client trust level differs from that of LBX Proxy";
595 if (auth_id == (XID) ~0L)
600 strncmp (auth_proto, XSecurityAuthorizationName, proto_n) != 0) &&
602 _XSERVTransGetPeerAddr (trans_conn,
603 &family, &fromlen, &from) != -1)
606 /* Amoeba RPC connections are already checked by the capability. */
607 if (family == FamilyAmoeba) {
616 InvalidHost ((struct sockaddr *) from, fromlen))
617 AuthAudit(client, FALSE, (struct sockaddr *) from,
618 fromlen, proto_n, auth_proto, auth_id);
622 if (auditTrailLevel > 1)
623 AuthAudit(client, TRUE,
624 (struct sockaddr *) from, fromlen,
625 proto_n, auth_proto, auth_id);
628 xfree ((char *) from);
631 if (auth_id == (XID) ~0L)
635 return "Client is not authorized to connect to Server";
637 else if (auditTrailLevel > 1)
639 if (_XSERVTransGetPeerAddr (trans_conn,
640 &family, &fromlen, &from) != -1)
642 AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
643 proto_n, auth_proto, auth_id);
645 xfree ((char *) from);
648 priv->auth_id = auth_id;
652 /* indicate to Xdmcp protocol that we've opened new client */
653 XdmcpOpenDisplay(priv->fd);
656 if (ClientStateCallback)
657 XagCallClientStateChange (client);
659 /* At this point, if the client is authorized to change the access control
660 * list, we should getpeername() information, and add the client to
661 * the selfhosts list. It's not really the host machine, but the
662 * true purpose of the selfhosts list is to see who may change the
663 * access control list.
665 return((char *)NULL);
670 AllocNewConnection (trans_conn, fd, conn_time, Flush, Close, proxy)
672 AllocNewConnection (trans_conn, fd, conn_time)
674 XtransConnInfo trans_conn;
693 XFD_SETCOUNT(&AllClients) >= MaxClients
697 oc = (OsCommPtr)xalloc(sizeof(OsCommRec));
700 oc->trans_conn = trans_conn;
702 oc->input = (ConnectionInputPtr)NULL;
703 oc->output = (ConnectionOutputPtr)NULL;
705 oc->conn_time = conn_time;
710 oc->largereq = (ConnectionInputPtr) NULL;
712 if (!(client = NextAvailableClient((pointer)oc)))
721 ConnectionTranslation[fd] = client->index;
724 FD_SET(fd, &SavedAllClients);
725 FD_SET(fd, &SavedAllSockets);
729 FD_SET(fd, &AllClients);
730 FD_SET(fd, &AllSockets);
739 ClientConnectionNumber (client)
742 OsCommPtr oc = (OsCommPtr) client->osPrivate;
748 AllocLbxClientConnection (client, proxy)
752 OsCommPtr oc = (OsCommPtr) client->osPrivate;
754 return AllocNewConnection ((XtransConnInfo)NULL, oc->fd, GetTimeInMillis(),
755 LbxFlushClient, LbxCloseClient, proxy);
759 LbxProxyConnection (client, proxy)
763 OsCommPtr oc = (OsCommPtr) client->osPrivate;
765 FlushClient(client, oc, (char *)NULL, 0);
767 oc->Flush = LbxFlushClient;
768 oc->Close = LbxCloseClient;
769 LbxPrimeInput(client, proxy);
775 * EstablishNewConnections
776 * If anyone is waiting on listened sockets, accept them.
777 * Returns a mask with indices of new clients. Updates AllClients
783 EstablishNewConnections(clientUnused, closure)
784 ClientPtr clientUnused;
788 fd_mask readyconnections; /* mask of listeners that are ready */
790 fd_set readyconnections; /* set of listeners that are ready */
792 int curconn; /* fd of listener that's ready */
793 register int newconn; /* fd of new client */
796 register ClientPtr client;
797 register OsCommPtr oc;
801 XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
803 readyconnections = tmask.fds_bits[0];
804 if (!readyconnections)
807 XFD_COPYSET(&tmask, &readyconnections);
808 if (!XFD_ANYSET(&readyconnections))
811 connect_time = GetTimeInMillis();
812 /* kill off stragglers */
813 for (i=1; i<currentMaxClients; i++)
815 if (client = clients[i])
817 oc = (OsCommPtr)(client->osPrivate);
818 if (oc && (oc->conn_time != 0) &&
819 (connect_time - oc->conn_time) >= TimeOutValue ||
820 client->noClientException != Success && !client->clientGone)
821 CloseDownClient(client);
825 /* EstablishNewConnections is only called when there is one new
826 * connection waiting on the first transport.
828 readyconnections = 1;
831 while (readyconnections)
833 for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++)
836 XtransConnInfo trans_conn, new_trans_conn;
840 curconn = ffs (readyconnections) - 1;
841 readyconnections &= ~(1 << curconn);
843 curconn = XFD_FD(&readyconnections, i);
846 if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
849 if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
852 newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
854 _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
856 if (!AllocNewConnection (new_trans_conn, newconn, connect_time
858 , StandardFlushClient,
859 CloseDownFileDescriptor, (LbxProxyPtr)NULL
863 ErrorConnMax(new_trans_conn);
864 _XSERVTransClose(new_trans_conn);
870 #define NOROOM "Maximum number of clients reached"
874 * Fail a connection due to lack of client or file descriptor space
878 ErrorConnMax(trans_conn)
879 XtransConnInfo trans_conn;
881 register int fd = _XSERVTransGetConnectionNumber (trans_conn);
882 xConnSetupPrefix csp;
888 struct timeval waittime;
891 /* if these seems like a lot of trouble to go to, it probably is */
892 waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
893 waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
894 (1000000 / MILLI_PER_SECOND);
897 (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
899 /* try to read the byte-order of the connection */
900 (void)_XSERVTransRead(trans_conn, &byteOrder, 1);
901 if ((byteOrder == 'l') || (byteOrder == 'B'))
903 csp.success = xFalse;
904 csp.lengthReason = sizeof(NOROOM) - 1;
905 csp.length = (sizeof(NOROOM) + 2) >> 2;
906 csp.majorVersion = X_PROTOCOL;
907 csp.minorVersion = X_PROTOCOL_REVISION;
908 if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
909 (!(*(char *) &whichbyte) && (byteOrder == 'l')))
911 swaps(&csp.majorVersion, whichbyte);
912 swaps(&csp.minorVersion, whichbyte);
913 swaps(&csp.length, whichbyte);
915 iov[0].iov_len = sz_xConnSetupPrefix;
916 iov[0].iov_base = (char *) &csp;
917 iov[1].iov_len = csp.lengthReason;
918 iov[1].iov_base = NOROOM;
919 iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
920 iov[2].iov_base = pad;
921 (void)_XSERVTransWritev(trans_conn, iov, 3);
926 * CloseDownFileDescriptor:
927 * Remove this file descriptor and it's I/O buffers, etc.
932 CloseDownFileDescriptor(client)
936 CloseDownFileDescriptor(oc)
937 register OsCommPtr oc;
941 register OsCommPtr oc = (OsCommPtr) client->osPrivate;
943 int connection = oc->fd;
945 if (oc->trans_conn) {
946 _XSERVTransDisconnect(oc->trans_conn);
947 _XSERVTransClose(oc->trans_conn);
950 ConnectionTranslation[connection] = 0;
954 FD_CLR(connection, &AllSockets);
955 FD_CLR(connection, &AllClients);
956 FD_CLR(connection, &ClientsWithInput);
957 FD_CLR(connection, &GrabImperviousClients);
960 FD_CLR(connection, &SavedAllSockets);
961 FD_CLR(connection, &SavedAllClients);
962 FD_CLR(connection, &SavedClientsWithInput);
964 FD_CLR(connection, &ClientsWriteBlocked);
965 if (!XFD_ANYSET(&ClientsWriteBlocked))
966 AnyClientsWriteBlocked = FALSE;
967 FD_CLR(connection, &OutputPending);
975 * Some connection has died, go find which one and shut it down
976 * The file descriptor has been closed, but is still in AllClients.
977 * If would truly be wonderful if select() would put the bogus
978 * file descriptors in the exception mask, but nooooo. So we have
979 * to check each and every socket individually.
989 register int curclient, curoff;
991 struct timeval notime;
994 fd_set savedAllClients;
1002 for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
1004 mask = AllClients.fds_bits[i];
1007 curoff = ffs (mask) - 1;
1008 curclient = curoff + (i << 5);
1010 FD_SET(curclient, &tmask);
1011 r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime);
1013 CloseDownClient(clients[ConnectionTranslation[curclient]]);
1014 mask &= ~(1 << curoff);
1018 XFD_COPYSET(&AllClients, &savedAllClients);
1019 for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
1021 curclient = XFD_FD(&savedAllClients, i);
1023 FD_SET(curclient, &tmask);
1024 r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime);
1026 CloseDownClient(clients[ConnectionTranslation[curclient]]);
1034 * CloseDownConnection
1035 * Delete client from AllClients and free resources
1039 CloseDownConnection(client)
1042 OsCommPtr oc = (OsCommPtr)client->osPrivate;
1044 if (oc->output && oc->output->count)
1045 FlushClient(client, oc, (char *)NULL, 0);
1047 XdmcpCloseDisplay(oc->fd);
1050 CloseDownFileDescriptor(oc);
1052 (*oc->Close) (client);
1056 client->osPrivate = (pointer)NULL;
1057 if (auditTrailLevel > 1)
1058 AuditF("client %d disconnected\n", client->index);
1062 AddEnabledDevice(fd)
1065 FD_SET(fd, &EnabledDevices);
1066 FD_SET(fd, &AllSockets);
1070 RemoveEnabledDevice(fd)
1073 FD_CLR(fd, &EnabledDevices);
1074 FD_CLR(fd, &AllSockets);
1078 * OnlyListenToOneClient:
1079 * Only accept requests from one client. Continue to handle new
1080 * connections, but don't take any protocol requests from the new
1081 * ones. Note that if GrabInProgress is set, EstablishNewConnections
1082 * needs to put new clients into SavedAllSockets and SavedAllClients.
1083 * Note also that there is no timeout for this in the protocol.
1084 * This routine is "undone" by ListenToAllClients()
1087 OnlyListenToOneClient(client)
1090 OsCommPtr oc = (OsCommPtr)client->osPrivate;
1091 int connection = oc->fd;
1093 if (! GrabInProgress)
1095 XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
1096 XFD_ANDSET(&ClientsWithInput,
1097 &ClientsWithInput, &GrabImperviousClients);
1098 if (FD_ISSET(connection, &SavedClientsWithInput))
1100 FD_CLR(connection, &SavedClientsWithInput);
1101 FD_SET(connection, &ClientsWithInput);
1103 XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
1104 XFD_COPYSET(&AllSockets, &SavedAllSockets);
1105 XFD_COPYSET(&AllClients, &SavedAllClients);
1106 XFD_UNSET(&AllSockets, &AllClients);
1107 XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
1108 FD_SET(connection, &AllClients);
1109 XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
1110 GrabInProgress = client->index;
1115 * ListenToAllClients:
1116 * Undoes OnlyListentToOneClient()
1119 ListenToAllClients()
1123 XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
1124 XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
1125 XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
1132 * Removes one client from input masks.
1133 * Must have cooresponding call to AttendClient.
1136 IgnoreClient (client)
1139 OsCommPtr oc = (OsCommPtr)client->osPrivate;
1140 int connection = oc->fd;
1142 LbxClientPtr lbxClient = LbxClient(client);
1145 isItTimeToYield = TRUE;
1148 lbxClient->ignored = TRUE;
1152 if (!GrabInProgress || FD_ISSET(connection, &AllClients))
1154 if (FD_ISSET (connection, &ClientsWithInput))
1155 FD_SET(connection, &IgnoredClientsWithInput);
1157 FD_CLR(connection, &IgnoredClientsWithInput);
1158 FD_CLR(connection, &ClientsWithInput);
1159 FD_CLR(connection, &AllSockets);
1160 FD_CLR(connection, &AllClients);
1161 FD_CLR(connection, &LastSelectMask);
1165 if (FD_ISSET (connection, &SavedClientsWithInput))
1166 FD_SET(connection, &IgnoredClientsWithInput);
1168 FD_CLR(connection, &IgnoredClientsWithInput);
1169 FD_CLR(connection, &SavedClientsWithInput);
1170 FD_CLR(connection, &SavedAllSockets);
1171 FD_CLR(connection, &SavedAllClients);
1177 * Adds one client back into the input masks.
1180 AttendClient (client)
1183 OsCommPtr oc = (OsCommPtr)client->osPrivate;
1184 int connection = oc->fd;
1186 LbxClientPtr lbxClient = LbxClient(client);
1189 lbxClient->ignored = FALSE;
1193 if (!GrabInProgress || GrabInProgress == client->index ||
1194 FD_ISSET(connection, &GrabImperviousClients))
1196 FD_SET(connection, &AllClients);
1197 FD_SET(connection, &AllSockets);
1198 FD_SET(connection, &LastSelectMask);
1199 if (FD_ISSET (connection, &IgnoredClientsWithInput))
1200 FD_SET(connection, &ClientsWithInput);
1204 FD_SET(connection, &SavedAllClients);
1205 FD_SET(connection, &SavedAllSockets);
1206 if (FD_ISSET(connection, &IgnoredClientsWithInput))
1207 FD_SET(connection, &SavedClientsWithInput);
1211 /* make client impervious to grabs; assume only executing client calls this */
1213 MakeClientGrabImpervious(client)
1216 OsCommPtr oc = (OsCommPtr)client->osPrivate;
1217 int connection = oc->fd;
1219 FD_SET(connection, &GrabImperviousClients);
1221 if (ServerGrabCallback)
1223 ServerGrabInfoRec grabinfo;
1224 grabinfo.client = client;
1225 grabinfo.grabstate = CLIENT_IMPERVIOUS;
1226 CallCallbacks(&ServerGrabCallback, &grabinfo);
1230 /* make client pervious to grabs; assume only executing client calls this */
1232 MakeClientGrabPervious(client)
1235 OsCommPtr oc = (OsCommPtr)client->osPrivate;
1236 int connection = oc->fd;
1238 FD_CLR(connection, &GrabImperviousClients);
1239 if (GrabInProgress && (GrabInProgress != client->index))
1241 if (FD_ISSET(connection, &ClientsWithInput))
1243 FD_SET(connection, &SavedClientsWithInput);
1244 FD_CLR(connection, &ClientsWithInput);
1246 FD_CLR(connection, &AllSockets);
1247 FD_CLR(connection, &AllClients);
1248 isItTimeToYield = TRUE;
1251 if (ServerGrabCallback)
1253 ServerGrabInfoRec grabinfo;
1254 grabinfo.client = client;
1255 grabinfo.grabstate = CLIENT_PERVIOUS;
1256 CallCallbacks(&ServerGrabCallback, &grabinfo);