/** * @brief pool select * @return void */ void SelPool::Select() { printf("Selecting in server and %d clients...\n", clients.size()); FD_ZERO(&read_set); FD_ZERO(&write_set); FD_SET(listenfd, &read_set); vector<ClientConnection*>::iterator it = clients.begin(); while ( it != clients.end() ) { ClientConnection *client = *it; int connFd = client->getFd(); if( client->isEmpty() && client->isReadable()) { printf("put %d to read_set\n", connFd); FD_SET(connFd, &read_set); } if( client->isWritable() ) /* state == Writing_Response */ { printf("put %d to write_set\n", connFd); FD_SET(connFd, &write_set); /* if it is CGI request, put its CGI_out pipe to read set */ if (client->getRequest()->isCGIRequest()) { int CGIout = client->getResponse()->getCGIout(); if (CGIout > maxfd) { maxfd = CGIout; } FD_SET(CGIout, &read_set); } } it++; } nready = select(maxfd + 1, &read_set, &write_set, NULL, NULL); //printf("Select Finished\n"); }
/** @brief check select pool and process client reqeusts * * @param pool select pool * @return void */ void SelPool::check_clients() { int connfd; vector<ClientConnection*>::iterator it = clients.begin(); while ( it != clients.end() ) { ClientConnection *client = *it; connfd = client->getFd(); printf("Handling %d\n", connfd); /* Client Connection State Machine */ switch ( client->getState() ) { case ClientConnection::Ready_ForRead: { printf("Client State: Ready_ForRead\n"); /* read ready client socket */ if (FD_ISSET(connfd, &read_set)) { readHandler(client); if (client->getState() == ClientConnection::Request_Parsed) { processHandler(client); /* if the client is closed after processing */ if (client->getState() == ClientConnection::Closed) { Socket::Close_Socket(connfd); FD_CLR(connfd, &read_set); delete client; clients.erase(it); continue; } writeHandler(client); } } break; } case ClientConnection::Request_Parsed: { printf("Client State: Request_Parsed\n"); break; } case ClientConnection::Writing_Response: { printf("Client State: Writing_Response\n"); if (FD_ISSET(connfd, &write_set)) { if (!client->getRequest()->isCGIRequest()) { processHandler(client); writeHandler(client); } else if (FD_ISSET(client->getResponse()->getCGIout(), &read_set)) { /* CGI request : if CGIout is also ready for reading */ pipeHandler(client); writeHandler(client); } } break; } case ClientConnection::Done_Response: { printf("Client State: Done_Response\n"); break; } default: { break; } } it++; } }