/*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; }
/* * accepts new connections */ void MakeNewConnections(void) { fd_mask readyconnections; int curconn; int newconn; long connect_time; int i; ClientPtr client; OsCommPtr oc; fd_set tmask; XFD_ANDSET (&tmask, &LastSelectMask, &WellKnownConnections); readyconnections = tmask.fds_bits[0]; if (!readyconnections) return; connect_time = GetTimeInMillis(); /* kill off stragglers */ for (i = MINCLIENT; i < currentMaxClients; i++) { if ((client = clients[i]) != NullClient) { oc = (OsCommPtr) client->osPrivate; if ((oc && (oc->conn_time != 0) && (connect_time - oc->conn_time) >= TimeOutValue) || ((client->noClientException != FSSuccess) && (client->clientGone != CLIENT_GONE))) CloseDownClient(client); } } while (readyconnections) { XtransConnInfo trans_conn, new_trans_conn; int status; curconn = ffs(readyconnections) - 1; readyconnections &= ~(1 << curconn); if ((trans_conn = lookup_trans_conn (curconn)) == NULL) continue; if ((new_trans_conn = _FontTransAccept (trans_conn, &status)) == NULL) continue; newconn = _FontTransGetConnectionNumber (new_trans_conn); _FontTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); oc = (OsCommPtr) fsalloc(sizeof(OsCommRec)); if (!oc) { fsfree(oc); error_conn_max(new_trans_conn); _FontTransClose(new_trans_conn); continue; } FD_SET(newconn, &AllClients); FD_SET(newconn, &AllSockets); oc->fd = newconn; oc->trans_conn = new_trans_conn; oc->input = (ConnectionInputPtr) NULL; oc->output = (ConnectionOutputPtr) NULL; oc->conn_time = connect_time; if ((newconn < lastfdesc) && (client = NextAvailableClient((pointer) oc))) { ConnectionTranslation[newconn] = client->index; } else { error_conn_max(new_trans_conn); close_fd(oc); } } }