/** 
 * @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");
}
示例#2
0
void ServerCore::Serve()
{
    fd_set sockets;
    struct timeval timeout;
    int max_desc;
    int readsocks;

    while(mRunning) {
        /* Build select list */
        FD_ZERO(&sockets);
        FD_SET(mListener, &sockets);
        max_desc = mListener;
        sem_wait(&mMutex);
        map<unsigned int, ClientConnection*>::iterator it = mClientMap.begin();
        while(it != mClientMap.end())
        {
            int fd = (*it).second->getFd();
            FD_SET(fd, &sockets);
            if (fd>max_desc) {
                max_desc = fd;
            }
            it++;
        }
        sem_post(&mMutex);

		timeout.tv_sec = 1;
		timeout.tv_usec = 0;
        readsocks = select(max_desc+1, &sockets, (fd_set*)0, (fd_set*)0,
                           &timeout);

		if (readsocks < 0) {
			printf("ERROR: select failed");
			break;
		}

        if(readsocks) {
            if(FD_ISSET(mListener, &sockets)) {
                /* New connection */
                int conn = accept(mListener, NULL, NULL);
                if (mClientMap.size()<MAX_CLIENTS) {
                    ClientConnection* client = new ClientConnection(conn);
                    mClientMap[mClientCount++] = client;
                } else {
                    close(conn);
                }
            }

            sem_wait(&mMutex);
            it = mClientMap.begin();
            while(it != mClientMap.end())
            {
                ClientConnection* client = (*it).second;
                if (FD_ISSET(client->getFd(), &sockets)) {
                    string data;
                    int status = client->Read(data);
                    if (status<0) {
                        /* Error , close */
                        map<unsigned int, ClientConnection*>::iterator it2 = it;
                        it2++;
                        delete client;
                        close(client->getFd());
                        mClientMap.erase(it);
                        it = it2;
                        continue;
                    }
                    if (status>0) {
                        if (mDispatch) {
                            /* Release the mutex so dispatched calls
                             * can write back to socket.
                             * This is safe, since this is the only thread
                             * that actually modifies the client connection map
                             */
                            sem_post(&mMutex);
                            mDispatch((*it).first,data);
                            sem_wait(&mMutex);
                        }
                    }
                }
                it++;
            }
            sem_post(&mMutex);
        } 
    }
}
/** @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++;
    }
}