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 handleRequest(char *arg) { clientHandle_t *ch = (clientHandle_t *) arg; selcmd_t sc; struct stat sbuf; int code = 0; int c_errno = 0; while (1) { Log("(handleRequest) going to sleep on 0x%x\n", &ch->ch_state); LWP_WaitProcess(&ch->ch_state); assert(ch->ch_state == CH_INUSE); FD_ZERO(&(ch->ch_read)); FD_ZERO(&(ch->ch_write)); FD_ZERO(&(ch->ch_except)); FD_SET(ch->ch_fd, &(ch->ch_read)); FD_SET(ch->ch_fd, &(ch->ch_except)); code = IOMGR_Select(ch->ch_fd + 1, &(ch->ch_read), &(ch->ch_write), &(ch->ch_except), (struct timeval *)NULL); if (FD_ISSET(ch->ch_fd, &(ch->ch_except))) { Log("Received expception. Read fd_set shows %d\n", FD_ISSET(ch->ch_fd, &(ch->ch_read))); assertNullFDSet(ch->ch_fd, &(ch->ch_read)); assertNullFDSet(-1, &(ch->ch_write)); assertNullFDSet(ch->ch_fd, &(ch->ch_except)); goto done; } assert(code > 0); if (read(ch->ch_fd, (char *)&sc, sizeof(sc)) != sizeof(sc)) { Die(1, "(handleRequest) read command"); } Log("(handleRequest)cmd=%d\n", sc.sc_cmd); fflush(stdout); switch (sc.sc_cmd) { case SC_PROBE: Log("Probed from client at %s\n", inet_ntoa(ch->ch_addr.sin_addr)); break; #ifdef notdef case SC_OOB: nThreads--; ch->ch_fd = 0; ch->ch_state = CH_FREE; return; #endif case SC_WRITE: handleWrite(ch, &sc); break; case SC_END: Log("Ending ungracefully in server.\n"); exit(1); default: Log("%d: bad command to handleRequest.\n", sc.sc_cmd); break; } done: /* We're done now, so we can be re-used. */ nThreads--; close(ch->ch_fd); ch->ch_fd = 0; ch->ch_state = CH_FREE; } }
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); }