/* This is the server process request loop. The server process loop * becomes a listener thread when rxi_ServerProc returns, and stays * listener thread until rxi_ListenerProc returns. */ void * rx_ServerProc(void * unused) { osi_socket sock; int threadID; struct rx_call *newcall = NULL; fd_set *rfds; if (!(rfds = IOMGR_AllocFDSet())) { osi_Panic("rxi_ListenerProc: no fd_sets!\n"); } rxi_MorePackets(rx_maxReceiveWindow + 2); /* alloc more packets */ rxi_dataQuota += rx_initSendWindow; /* Reserve some pkts for hard times */ /* threadID is used for making decisions in GetCall. Get it by bumping * number of threads handling incoming calls */ threadID = rxi_availProcs++; while (1) { sock = OSI_NULLSOCKET; rxi_ServerProc(threadID, newcall, &sock); /* assert(sock != OSI_NULLSOCKET); */ newcall = NULL; rxi_ListenerProc(rfds, &threadID, &newcall); /* assert(threadID != -1); */ /* assert(newcall != NULL); */ } /* not reached */ return NULL; }
/* This is the listener process request loop. The listener process loop * becomes a server thread when rxi_ListenerProc returns, and stays * server thread until rxi_ServerProc returns. */ static void * rx_ListenerProc(void *dummy) { int threadID; osi_socket sock; struct rx_call *newcall; fd_set *rfds; if (!(rfds = IOMGR_AllocFDSet())) { osi_Panic("rx_ListenerProc: no fd_sets!\n"); } while (1) { newcall = NULL; threadID = -1; rxi_ListenerProc(rfds, &threadID, &newcall); /* assert(threadID != -1); */ /* assert(newcall != NULL); */ sock = OSI_NULLSOCKET; rxi_ServerProc(threadID, newcall, &sock); /* assert(sock != OSI_NULLSOCKET); */ } /* not reached */ return NULL; }
/* * Simulate a blocking sendmsg on the non-blocking socket. * It's non blocking because it was set that way for recvmsg. */ int rxi_Sendmsg(osi_socket socket, struct msghdr *msg_p, int flags) { fd_set *sfds = (fd_set *) 0; while (sendmsg(socket, msg_p, flags) == -1) { int err; rx_stats.sendSelects++; if (!sfds) { if (!(sfds = IOMGR_AllocFDSet())) { (osi_Msg "rx failed to alloc fd_set: "); perror("rx_sendmsg"); return -1; } FD_SET(socket, sfds); } #if defined(HAVE_LINUX_ERRQUEUE_H) && defined(ADAPT_PMTU) while((rxi_HandleSocketError(socket)) > 0) ; #endif #ifdef AFS_NT40_ENV if (WSAGetLastError()) #elif defined(AFS_LINUX22_ENV) /* linux unfortunately returns ECONNREFUSED if the target port * is no longer in use */ /* and EAGAIN if a UDP checksum is incorrect */ if (errno != EWOULDBLOCK && errno != ENOBUFS && errno != ECONNREFUSED && errno != EAGAIN) #else if (errno != EWOULDBLOCK && errno != ENOBUFS) #endif { (osi_Msg "rx failed to send packet: "); perror("rx_sendmsg"); #ifndef AFS_NT40_ENV if (errno > 0) return -errno; #else if (WSAGetLastError() > 0) return -WSAGetLastError(); #endif return -1; } while ((err = select(socket + 1, 0, sfds, 0, 0)) != 1) { if (err >= 0 || errno != EINTR) osi_Panic("rxi_sendmsg: select error %d.%d", err, errno); } } if (sfds) IOMGR_FreeFDSet(sfds); return 0; }
void handleWrite(clientHandle_t * ch, selcmd_t * sc) { int i; fd_set *rfds, *wfds, *efds; char *buf; int code; int scode; char c; int nbytes; rfds = IOMGR_AllocFDSet(); wfds = IOMGR_AllocFDSet(); efds = IOMGR_AllocFDSet(); assert(rfds && wfds && efds); if (sc->sc_delay > 0) { IOMGR_Sleep(sc->sc_delay); } Log("(handleWrite 0x%x) waking after %d second sleep.\n", ch->ch_pid, sc->sc_delay); if (sc->sc_flags & SC_WAIT_OOB) sendOOB(ch->ch_fd); buf = (char *)malloc(sc->sc_info); assert(buf); i = 0; while (1) { FD_ZERO(rfds); FD_SET(ch->ch_fd, rfds); FD_ZERO(efds); FD_SET(ch->ch_fd, efds); FD_ZERO(wfds); scode = IOMGR_Select(ch->ch_fd + 1, rfds, wfds, efds, (struct timeval *)0); assert(scode > 0); if (FD_ISSET(ch->ch_fd, rfds)) { assert(i < sc->sc_info); code = read(ch->ch_fd, &buf[i], 1); i++; write_I++; if (code != 1) { Log("code =%d\n", code); assert(code == 1); } /* Test for valid fds */ assertNullFDSet(ch->ch_fd, rfds); assertNullFDSet(-1, wfds); assertNullFDSet(-1, efds); if (c == END_DATA || i >= sc->sc_info) { break; } } } Log("Read %d bytes of data.\n", sc->sc_info); nbytes = write(ch->ch_fd, buf, sc->sc_info); assert(nbytes == sc->sc_info); Log("Wrote data back to client.\n"); IOMGR_FreeFDSet(rfds); IOMGR_FreeFDSet(wfds); IOMGR_FreeFDSet(efds); }
main(int ac, char **av) { int i; int on = 1; short port = -1; /* host order. */ int setFD = 0; struct sockaddr_in saddr; int acceptFD; clientHandle_t *clientHandle; int code; int addr_len; PROCESS pid; fd_set *rfds, *wfds, *efds; int sockFD; program = av[0]; if (ac < 2) Usage(); /* lwp_debug = 1; */ signal(SIGIO, sigIO); for (i = 1; i < ac; i++) { if (!strcmp("-fd", av[i])) { if (++i >= ac) { printf("Missing number for -fd option.\n"); Usage(); } setFD = atoi(av[i]); if (setFD <= 2) { printf("%d: file descriptor must be at least 3.\n", setFD); Usage(); } } else { if (port == -1) { port = atoi(av[i]); if (port <= 0) { printf("%s: port must be at least 1\n", av[i]); Usage(); } } else { printf("%s: Unknown argument.\n", av[i]); } } } if (port == -1) { printf("Missing port.\n"); Usage(); } if (!setFD) { setFD = 31; printf("Using default socket of %d.\n", setFD); } OpenFDs(setFD); IOMGR_Initialize(); /* Setup server processes */ for (i = 0; i < MAX_THREADS; i++) { if (LWP_CreateProcess (handleRequest, 32768, LWP_NORMAL_PRIORITY, (char *)&clientHandles[i], "HandleRequestThread", &pid) < 0) { printf("%s: Failed to start all LWP's\n", program); exit(1); } clientHandles[i].ch_pid = pid; } sockFD = socket(AF_INET, SOCK_STREAM, 0); if (sockFD < 0) { perror("socket"); exit(1); } Log("Using socket at file descriptor %d.\n", sockFD); if (setsockopt(sockFD, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) { perror("setsockopt: "); exit(1); } memset((void *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = ntohs(port); saddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sockFD, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind: "); exit(1); } rfds = IOMGR_AllocFDSet(); wfds = IOMGR_AllocFDSet(); efds = IOMGR_AllocFDSet(); if (!rfds || !wfds || !efds) { printf("main: Could not alloc fd_set's.\n"); exit(1); } listen(sockFD, 100); while (1) { FD_ZERO(rfds); FD_ZERO(wfds); FD_ZERO(efds); FD_SET(sockFD, rfds); FD_SET(sockFD, efds); Log("Main - going to select.\n"); code = IOMGR_Select(sockFD + 1, rfds, wfds, efds, (struct timeval *)0); switch (code) { case 0: /* Timer, can't happen here. */ case -1: case -2: Log("Oops! select returns %d!\n", code); abort(); default: if (FD_ISSET(sockFD, efds)) { recvOOB(sockFD); assertNullFDSet(sockFD, rfds); assertNullFDSet(-1, wfds); assertNullFDSet(sockFD, efds); } if (FD_ISSET(sockFD, rfds)) { while (nThreads > MAX_THREADS) { IOMGR_Sleep(1); } clientHandle = getClientHandle(); addr_len = sizeof(clientHandle->ch_addr); clientHandle->ch_fd = accept(sockFD, (struct sockaddr *) &clientHandle->ch_addr, &addr_len); if (clientHandle->ch_fd < 0) { perror("accept: "); exit(1); } Log("Main - signalling LWP 0x%x\n", &clientHandle->ch_state); LWP_NoYieldSignal(&clientHandle->ch_state); assertNullFDSet(sockFD, rfds); assertNullFDSet(-1, wfds); assertNullFDSet(-1, efds); break; } Die(1, "(main) No data to read.\n"); } } }
void sendTest(int sockFD, int delay, int reqOOB, int size) { char *buf, *bufTest; fd_set *rfds, *wfds, *efds; int i, j; int nbytes, code; selcmd_t selCmd; time_t stime, etime; buf = (char *)malloc(size); assert(buf); bufTest = (char *)malloc(size); assert(bufTest); for (j = i = 0; i < size; i++, j++) { if (j == END_DATA) j++; if (j > 255) j = 0; buf[i] = (char)j; } selCmd.sc_cmd = SC_WRITE; selCmd.sc_info = size; selCmd.sc_delay = delay; selCmd.sc_flags = SC_WAIT_ONLY; nbytes = write(sockFD, (char *)&selCmd, sizeof(selCmd)); assert(nbytes == sizeof(selCmd)); Log("Starting to write %d bytes.\n", size); if (!delay) { nbytes = write(sockFD, buf, size); assert(nbytes == size); } else { rfds = IOMGR_AllocFDSet(); wfds = IOMGR_AllocFDSet(); efds = IOMGR_AllocFDSet(); if (!rfds || !wfds || !efds) { printf("%s: Could not allocate all fd_sets.\n", program); exit(1); } for (writeIndex = i = 0; i < size; writeIndex++, i++) { FD_ZERO(rfds); FD_ZERO(wfds); FD_ZERO(efds); FD_SET(sockFD, wfds); FD_SET(sockFD, efds); (void)time(&stime); code = IOMGR_Select(sockFD + 1, rfds, wfds, efds, (struct timeval *)NULL); assert(code > 0); if (FD_ISSET(sockFD, wfds)) { (void)time(&etime); if (etime - stime > 1) { Log("Waited %d seconds to write at offset %d.\n", etime - stime, i); } stime = etime; nbytes = write(sockFD, &buf[i], 1); (void)time(&etime); if (etime - stime > 1) { Log("Waited %d seconds IN write.\n", etime - stime); } assert(nbytes == 1); FD_CLR(sockFD, wfds); } assertNullFDSet(0, rfds); assertNullFDSet(0, wfds); assertNullFDSet(0, efds); } } Log("Wrote %d bytes.\n", size); i = 0; while (i < size) { nbytes = read(sockFD, &bufTest[i], size); i += nbytes; } Log("Read %d bytes.\n", size); assert(memcmp(buf, bufTest, size) == 0); Log("Compared %d bytes.\n", size); }