/*ARGSUSED*/ static void XdmcpWakeupHandler( pointer data, /* unused */ int i, pointer pReadmask) { fd_set* LastSelectMask = (fd_set*)pReadmask; fd_set devicesReadable; if (state == XDM_OFF) return; if (i > 0) { if (FD_ISSET(xdmcpSocket, LastSelectMask)) { receive_packet(xdmcpSocket); FD_CLR(xdmcpSocket, LastSelectMask); } #if defined(IPv6) && defined(AF_INET6) if (xdmcpSocket6 >= 0 && FD_ISSET(xdmcpSocket6, LastSelectMask)) { receive_packet(xdmcpSocket6); FD_CLR(xdmcpSocket6, LastSelectMask); } #endif XFD_ANDSET(&devicesReadable, LastSelectMask, &EnabledDevices); if (XFD_ANYSET(&devicesReadable)) { if (state == XDM_AWAIT_USER_INPUT) restart(); else if (state == XDM_RUN_SESSION) keepaliveDormancy = defaultKeepaliveDormancy; } if (XFD_ANYSET(&AllClients) && state == XDM_RUN_SESSION) timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000; } else if (timeOutTime && (int) (GetTimeInMillis() - timeOutTime) >= 0) { if (state == XDM_RUN_SESSION) { state = XDM_KEEPALIVE; send_packet(); } else timeout(); } }
/* ARGSUSED */ void xf86Wakeup(pointer blockData, int err, pointer pReadmask) { fd_set *LastSelectMask = (fd_set *) pReadmask; fd_set devicesWithInput; InputInfoPtr pInfo; if (err >= 0) { XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices); if (XFD_ANYSET(&devicesWithInput)) { pInfo = xf86InputDevs; while (pInfo) { if (pInfo->read_input && pInfo->fd >= 0 && (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) { OsBlockSIGIO(); /* * Remove the descriptior from the set because more than one * device may share the same file descriptor. */ FD_CLR(pInfo->fd, &devicesWithInput); pInfo->read_input(pInfo); OsReleaseSIGIO(); } pInfo = pInfo->next; } } } if (err >= 0) { /* we don't want the handlers called if select() */ IHPtr ih; /* returned with an error condition, do we? */ for (ih = InputHandlers; ih; ih = ih->next) { if (ih->enabled && ih->fd >= 0 && ih->ihproc && (FD_ISSET(ih->fd, ((fd_set *) pReadmask)) != 0)) { ih->ihproc(ih->fd, ih->data); } } } if (xf86VTSwitchPending()) xf86VTSwitch(); }
int WaitForSomething(int *pClientsReady) { struct timeval *wt, waittime; fd_set clientsReadable; fd_set clientsWriteable; long curclient; int selecterr; long current_time = 0; long timeout; int nready, i; while (1) { /* handle the work Q */ if (workQueue) ProcessWorkQueue(); if (XFD_ANYSET(&ClientsWithInput)) { XFD_COPYSET(&ClientsWithInput, &clientsReadable); break; } /* * deal with KeepAlive timeouts. if this seems to costly, SIGALRM * could be used, but its more dangerous since some it could catch us * at an inopportune moment (like inside un-reentrant malloc()). */ current_time = GetTimeInMillis(); timeout = current_time - LastReapTime; if (timeout > ReapClientTime) { ReapAnyOldClients(); LastReapTime = current_time; timeout = ReapClientTime; } timeout = ReapClientTime - timeout; waittime.tv_sec = timeout / MILLI_PER_SECOND; waittime.tv_usec = (timeout % MILLI_PER_SECOND) * (1000000 / MILLI_PER_SECOND); wt = &waittime; XFD_COPYSET(&AllSockets, &LastSelectMask); BlockHandler(&wt, (pointer) &LastSelectMask); if (NewOutputPending) FlushAllOutput(); if (AnyClientsWriteBlocked) { XFD_COPYSET(&ClientsWriteBlocked, &clientsWriteable); i = Select(MAXSOCKS, &LastSelectMask, &clientsWriteable, NULL, wt); } else { i = Select(MAXSOCKS, &LastSelectMask, NULL, NULL, wt); } selecterr = errno; WakeupHandler(i, (unsigned long *) &LastSelectMask); if (i <= 0) { /* error or timeout */ FD_ZERO(&clientsWriteable); if (i < 0) { if (selecterr == EBADF) { /* somebody disconnected */ CheckConnections(); } else if (selecterr != EINTR) { ErrorF("WaitForSomething: select(): errno %d\n", selecterr); } else { /* * must have been broken by a signal. go deal with any * exception flags */ return 0; } } else { /* must have timed out */ ReapAnyOldClients(); LastReapTime = GetTimeInMillis(); } } else { if (AnyClientsWriteBlocked && XFD_ANYSET(&clientsWriteable)) { NewOutputPending = TRUE; XFD_ORSET(&OutputPending, &clientsWriteable, &OutputPending); XFD_UNSET(&ClientsWriteBlocked, &clientsWriteable); if (!XFD_ANYSET(&ClientsWriteBlocked)) AnyClientsWriteBlocked = FALSE; } XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients); if (LastSelectMask.fds_bits[0] & WellKnownConnections.fds_bits[0]) MakeNewConnections(); if (XFD_ANYSET(&clientsReadable)) break; } } nready = 0; if (XFD_ANYSET(&clientsReadable)) { ClientPtr client; int conn; if (current_time) /* may not have been set */ current_time = GetTimeInMillis(); for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) { while (clientsReadable.fds_bits[i]) { curclient = xfd_ffs(clientsReadable.fds_bits[i]) - 1; conn = ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))]; clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient); client = clients[conn]; if (!client) continue; pClientsReady[nready++] = conn; client->last_request_time = current_time; client->clientGone = CLIENT_ALIVE; if (nready >= MaxClients) { /* pClientsReady buffer has no more room, get the rest on the next time through select() loop */ return nready; } } } } return nready; }
/*ARGSUSED*/ Bool EstablishNewConnections(ClientPtr clientUnused, pointer closure) { fd_set readyconnections; /* set of listeners that are ready */ int curconn; /* fd of listener that's ready */ register int newconn; /* fd of new client */ CARD32 connect_time; register int i; register ClientPtr client; register OsCommPtr oc; fd_set tmask; XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections); XFD_COPYSET(&tmask, &readyconnections); if (!XFD_ANYSET(&readyconnections)) return TRUE; connect_time = GetTimeInMillis(); /* kill off stragglers */ for (i=1; i<currentMaxClients; i++) { if ((client = clients[i])) { oc = (OsCommPtr)(client->osPrivate); if ((oc && (oc->conn_time != 0) && (connect_time - oc->conn_time) >= TimeOutValue) || (client->noClientException != Success && !client->clientGone)) CloseDownClient(client); } } #ifndef WIN32 for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) { while (readyconnections.fds_bits[i]) #else for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++) #endif { XtransConnInfo trans_conn, new_trans_conn; int status; #ifndef WIN32 curconn = mffs (readyconnections.fds_bits[i]) - 1; readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn); curconn += (i * (sizeof(fd_mask)*8)); #else curconn = XFD_FD(&readyconnections, i); #endif if ((trans_conn = lookup_trans_conn (curconn)) == NULL) continue; if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL) continue; newconn = _XSERVTransGetConnectionNumber (new_trans_conn); if (newconn < lastfdesc) { int clientid; #if !defined(WIN32) clientid = ConnectionTranslation[newconn]; #else clientid = GetConnectionTranslation(newconn); #endif if(clientid && (client = clients[clientid])) CloseDownClient(client); } _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); if (!AllocNewConnection (new_trans_conn, newconn, connect_time)) { ErrorConnMax(new_trans_conn); _XSERVTransClose(new_trans_conn); } if(trans_conn->flags & TRANS_NOXAUTH) new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH; } #ifndef WIN32 } #endif return TRUE; }
void CreateWellKnownSockets(void) { int i; int partial; char port[20]; FD_ZERO(&AllSockets); FD_ZERO(&AllClients); FD_ZERO(&LastSelectMask); FD_ZERO(&ClientsWithInput); #if !defined(WIN32) for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0; #else ClearConnectionTranslation(); #endif FD_ZERO (&WellKnownConnections); sprintf (port, "%d", atoi (display)); if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial, &ListenTransCount, &ListenTransConns) >= 0) && (ListenTransCount >= 1)) { if (!PartialNetwork && partial) { FatalError ("Failed to establish all listening sockets"); } else { ListenTransFds = xalloc (ListenTransCount * sizeof (int)); for (i = 0; i < ListenTransCount; i++) { int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); ListenTransFds[i] = fd; FD_SET (fd, &WellKnownConnections); if (!_XSERVTransIsLocal (ListenTransConns[i])) { DefineSelf (fd); } } } } if (!XFD_ANYSET (&WellKnownConnections)) FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running"); #if !defined(WIN32) OsSignal (SIGPIPE, SIG_IGN); OsSignal (SIGHUP, AutoResetServer); #endif OsSignal (SIGINT, GiveUp); OsSignal (SIGTERM, GiveUp); XFD_COPYSET (&WellKnownConnections, &AllSockets); ResetHosts(display); InitParentProcess(); #ifdef XDMCP XdmcpInit (); #endif }
void CreateWellKnownSockets(void) { int i; int partial; FD_ZERO(&AllSockets); FD_ZERO(&AllClients); FD_ZERO(&LastSelectMask); FD_ZERO(&ClientsWithInput); #if !defined(WIN32) for (i = 0; i < MaxClients; i++) ConnectionTranslation[i] = 0; #else ClearConnectionTranslation(); #endif FD_ZERO(&WellKnownConnections); /* display is initialized to "0" by main(). It is then set to the display * number if specified on the command line. */ if (NoListenAll) { ListenTransCount = 0; } else if ((displayfd < 0) || explicit_display) { if (TryCreateSocket(atoi(display), &partial) && ListenTransCount >= 1) if (!PartialNetwork && partial) FatalError ("Failed to establish all listening sockets"); } else { /* -displayfd and no explicit display number */ Bool found = 0; for (i = 0; i < 65536 - X_TCP_PORT; i++) { if (TryCreateSocket(i, &partial) && ListenTransCount >= 1 && (PartialNetwork || !partial)) { found = 1; break; } else CloseWellKnownConnections(); } if (!found) FatalError("Failed to find a socket to listen on"); dynamic_display_id=i; snprintf(dynamic_display, sizeof(dynamic_display), "%d", i); display = dynamic_display; } ListenTransFds = xallocarray(ListenTransCount, sizeof (int)); if (ListenTransFds == NULL) FatalError ("Failed to create listening socket array"); for (i = ListenTransCount; i > 0; i--) { int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i-1]); ListenTransFds[i-1] = fd; FD_SET(fd, &WellKnownConnections); if (!_XSERVTransIsLocal (ListenTransConns[i-1])) { int protocol = 0; if (!strcmp("inet", ListenTransConns[i-1]->transptr->TransName)) protocol = 4; else if (!strcmp("inet6", ListenTransConns[i-1]->transptr->TransName)) protocol = 6; DefineSelf (fd, protocol); } } if (!XFD_ANYSET(&WellKnownConnections) && !NoListenAll) FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running"); #if !defined(WIN32) OsSignal(SIGPIPE, SIG_IGN); OsSignal(SIGHUP, AutoResetServer); #endif OsSignal(SIGINT, GiveUp); OsSignal(SIGTERM, GiveUp); XFD_COPYSET(&WellKnownConnections, &AllSockets); ResetHosts(display); InitParentProcess(); #ifdef XDMCP XdmcpInit(); #endif }
/* * creates the sockets for listening to clients * * only called when server first started */ void CreateSockets(int old_listen_count, OldListenRec *old_listen) { int i; FD_ZERO(&AllSockets); FD_ZERO(&AllClients); FD_ZERO(&LastSelectMask); FD_ZERO(&ClientsWithInput); FD_ZERO(&WellKnownConnections); for (i = 0; i < MAXSOCKS; i++) ConnectionTranslation[i] = 0; #ifdef XNO_SYSCONF /* should only be on FreeBSD 1.x and NetBSD 0.x */ #undef _SC_OPEN_MAX #endif #ifdef _SC_OPEN_MAX lastfdesc = sysconf(_SC_OPEN_MAX) - 1; #else #if defined(hpux) || defined(__UNIXOS2__) lastfdesc = _NFILE - 1; #else lastfdesc = getdtablesize() - 1; #endif /* hpux */ #endif if (lastfdesc > MAXSOCKS) { lastfdesc = MAXSOCKS; } if (old_listen_count > 0) { /* * The font server cloned itself. Re-use previously opened * transports for listening. */ ListenTransConns = (XtransConnInfo *) malloc ( old_listen_count * sizeof (XtransConnInfo)); ListenTransFds = (int *) malloc (old_listen_count * sizeof (int)); ListenTransCount = 0; for (i = 0; i < old_listen_count; i++) { char portnum[10]; if (old_listen[i].portnum != ListenPort) continue; /* this should never happen */ else sprintf (portnum, "%d", old_listen[i].portnum); if ((ListenTransConns[ListenTransCount] = _FontTransReopenCOTSServer (old_listen[i].trans_id, old_listen[i].fd, portnum)) != NULL) { ListenTransFds[ListenTransCount] = old_listen[i].fd; FD_SET (old_listen[i].fd, &WellKnownConnections); NoticeF("reusing existing file descriptor %d\n", old_listen[i].fd); ListenTransCount++; } } } else { char port[20]; int partial; sprintf (port, "%d", ListenPort); if ((_FontTransMakeAllCOTSServerListeners (port, &partial, &ListenTransCount, &ListenTransConns) >= 0) && (ListenTransCount >= 1)) { ListenTransFds = (int *) malloc (ListenTransCount * sizeof (int)); for (i = 0; i < ListenTransCount; i++) { int fd = _FontTransGetConnectionNumber (ListenTransConns[i]); ListenTransFds[i] = fd; FD_SET (fd, &WellKnownConnections); } } } if (! XFD_ANYSET(&WellKnownConnections)) FatalError("cannot establish any listening sockets\n"); /* set up all the signal handlers */ signal(SIGPIPE, SIG_IGN); signal(SIGHUP, AutoResetServer); signal(SIGINT, GiveUp); signal(SIGTERM, GiveUp); signal(SIGUSR1, ServerReconfig); signal(SIGUSR2, ServerCacheFlush); signal(SIGCHLD, CleanupChild); XFD_COPYSET (&WellKnownConnections, &AllSockets); }
int WriteToClient(ClientPtr who, int count, const void *__buf) { OsCommPtr oc; ConnectionOutputPtr oco; int padBytes; const char *buf = __buf; #ifdef DEBUG_COMMUNICATION Bool multicount = FALSE; #endif if (!count || !who || who == serverClient || who->clientGone) return 0; oc = who->osPrivate; oco = oc->output; #ifdef DEBUG_COMMUNICATION { char info[128]; xError *err; xGenericReply *rep; xEvent *ev; if (!who->replyBytesRemaining) { switch (buf[0]) { case X_Reply: rep = (xGenericReply *) buf; if (rep->sequenceNumber == who->sequence) { snprintf(info, 127, "Xreply: type: 0x%x data: 0x%x " "len: %i seq#: 0x%x", rep->type, rep->data1, rep->length, rep->sequenceNumber); multicount = TRUE; } break; case X_Error: err = (xError *) buf; snprintf(info, 127, "Xerror: Code: 0x%x resID: 0x%x maj: 0x%x " "min: %x", err->errorCode, err->resourceID, err->minorCode, err->majorCode); break; default: if ((buf[0] & 0x7f) == KeymapNotify) snprintf(info, 127, "KeymapNotifyEvent: %i", buf[0]); else { ev = (xEvent *) buf; snprintf(info, 127, "XEvent: type: 0x%x detail: 0x%x " "seq#: 0x%x", ev->u.u.type, ev->u.u.detail, ev->u.u.sequenceNumber); } } ErrorF("REPLY: ClientIDX: %i %s\n", who->index, info); } else multicount = TRUE; } #endif if (!oco) { if ((oco = FreeOutputs)) { FreeOutputs = oco->next; } else if (!(oco = AllocateOutputBuffer())) { if (oc->trans_conn) { _XSERVTransDisconnect(oc->trans_conn); _XSERVTransClose(oc->trans_conn); oc->trans_conn = NULL; } MarkClientException(who); return -1; } oc->output = oco; } padBytes = padding_for_int32(count); if (ReplyCallback) { ReplyInfoRec replyinfo; replyinfo.client = who; replyinfo.replyData = buf; replyinfo.dataLenBytes = count + padBytes; replyinfo.padBytes = padBytes; if (who->replyBytesRemaining) { /* still sending data of an earlier reply */ who->replyBytesRemaining -= count + padBytes; replyinfo.startOfReply = FALSE; replyinfo.bytesRemaining = who->replyBytesRemaining; CallCallbacks((&ReplyCallback), (void *) &replyinfo); } else if (who->clientState == ClientStateRunning && buf[0] == X_Reply) { /* start of new reply */ CARD32 replylen; unsigned long bytesleft; replylen = ((const xGenericReply *) buf)->length; if (who->swapped) swapl(&replylen); bytesleft = (replylen * 4) + SIZEOF(xReply) - count - padBytes; replyinfo.startOfReply = TRUE; replyinfo.bytesRemaining = who->replyBytesRemaining = bytesleft; CallCallbacks((&ReplyCallback), (void *) &replyinfo); } } #ifdef DEBUG_COMMUNICATION else if (multicount) { if (who->replyBytesRemaining) { who->replyBytesRemaining -= (count + padBytes); } else { CARD32 replylen; replylen = ((xGenericReply *) buf)->length; who->replyBytesRemaining = (replylen * 4) + SIZEOF(xReply) - count - padBytes; } } #endif if (oco->count == 0 || oco->count + count + padBytes > oco->size) { FD_CLR(oc->fd, &OutputPending); if (!XFD_ANYSET(&OutputPending)) { CriticalOutputPending = FALSE; NewOutputPending = FALSE; } if (FlushCallback) CallCallbacks(&FlushCallback, NULL); return FlushClient(who, oc, buf, count); } NewOutputPending = TRUE; FD_SET(oc->fd, &OutputPending); memmove((char *) oco->buf + oco->count, buf, count); oco->count += count; if (padBytes) { memset(oco->buf + oco->count, '\0', padBytes); oco->count += padBytes; } return count; }
void CreateWellKnownSockets(void) { int i; int partial; FD_ZERO(&AllSockets); FD_ZERO(&AllClients); FD_ZERO(&LastSelectMask); FD_ZERO(&ClientsWithInput); #if !defined(WIN32) for (i = 0; i < MaxClients; i++) ConnectionTranslation[i] = 0; #else ClearConnectionTranslation(); #endif FD_ZERO(&WellKnownConnections); /* display is initialized to "0" by main(). It is then set to the display * number if specified on the command line, or to NULL when the -displayfd * option is used. */ if (display) { if (TryCreateSocket(atoi(display), &partial) && ListenTransCount >= 1) if (!PartialNetwork && partial) FatalError ("Failed to establish all listening sockets"); } else { /* -displayfd */ Bool found = 0; for (i = 0; i < 65535 - X_TCP_PORT; i++) { if (TryCreateSocket(i, &partial) && !partial) { found = 1; break; } else CloseWellKnownConnections(); } if (!found) FatalError("Failed to find a socket to listen on"); snprintf(dynamic_display, sizeof(dynamic_display), "%d", i); display = dynamic_display; } ListenTransFds = malloc(ListenTransCount * sizeof (int)); for (i = 0; i < ListenTransCount; i++) { int fd = _XSERVTransGetConnectionNumber(ListenTransConns[i]); ListenTransFds[i] = fd; FD_SET(fd, &WellKnownConnections); if (!_XSERVTransIsLocal(ListenTransConns[i])) DefineSelf (fd); } if (!XFD_ANYSET(&WellKnownConnections)) FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running"); #if !defined(WIN32) OsSignal(SIGPIPE, SIG_IGN); OsSignal(SIGHUP, AutoResetServer); #endif OsSignal(SIGINT, GiveUp); OsSignal(SIGTERM, GiveUp); XFD_COPYSET(&WellKnownConnections, &AllSockets); ResetHosts(display); InitParentProcess(); #ifdef XDMCP XdmcpInit(); #endif }
/* * creates the sockets for listening to clients * * only called when server first started */ void CreateSockets(int old_listen_count, OldListenRec *old_listen) { int i; struct sigaction act; FD_ZERO(&AllSockets); FD_ZERO(&AllClients); FD_ZERO(&LastSelectMask); FD_ZERO(&ClientsWithInput); FD_ZERO(&WellKnownConnections); for (i = 0; i < MAXSOCKS; i++) ConnectionTranslation[i] = 0; lastfdesc = sysconf(_SC_OPEN_MAX) - 1; if ((lastfdesc < 0) || (lastfdesc > MAXSOCKS)) { lastfdesc = MAXSOCKS; } if (old_listen_count > 0) { /* * The font server cloned itself. Re-use previously opened * transports for listening. */ ListenTransConns = (XtransConnInfo *) malloc ( old_listen_count * sizeof (XtransConnInfo)); ListenTransFds = (int *) malloc (old_listen_count * sizeof (int)); ListenTransCount = 0; for (i = 0; i < old_listen_count; i++) { char portnum[10]; if (old_listen[i].portnum != ListenPort) continue; /* this should never happen */ else sprintf (portnum, "%d", old_listen[i].portnum); if ((ListenTransConns[ListenTransCount] = _FontTransReopenCOTSServer (old_listen[i].trans_id, old_listen[i].fd, portnum)) != NULL) { ListenTransFds[ListenTransCount] = old_listen[i].fd; FD_SET (old_listen[i].fd, &WellKnownConnections); NoticeF("reusing existing file descriptor %d\n", old_listen[i].fd); ListenTransCount++; } } } else { char port[20]; int partial; sprintf (port, "%d", ListenPort); if ((_FontTransMakeAllCOTSServerListeners (port, &partial, &ListenTransCount, &ListenTransConns) >= 0) && (ListenTransCount >= 1)) { ListenTransFds = (int *) malloc (ListenTransCount * sizeof (int)); for (i = 0; i < ListenTransCount; i++) { int fd = _FontTransGetConnectionNumber (ListenTransConns[i]); ListenTransFds[i] = fd; FD_SET (fd, &WellKnownConnections); } } } if (! XFD_ANYSET(&WellKnownConnections)) FatalError("cannot establish any listening sockets\n"); /* set up all the signal handlers */ sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; #define HANDLE_SIGNAL(s, h) act.sa_handler = h; sigaction(s, &act, NULL) HANDLE_SIGNAL(SIGPIPE, SIG_IGN); HANDLE_SIGNAL(SIGHUP, AutoResetServer); HANDLE_SIGNAL(SIGINT, GiveUp); HANDLE_SIGNAL(SIGTERM, GiveUp); HANDLE_SIGNAL(SIGUSR1, ServerReconfig); HANDLE_SIGNAL(SIGUSR2, ServerCacheFlush); HANDLE_SIGNAL(SIGCHLD, CleanupChild); XFD_COPYSET (&WellKnownConnections, &AllSockets); }