예제 #1
0
파일: Server.cpp 프로젝트: dbcfd/C11Http
/**
 * Socket associated with client connection has indicated it has data ready
 * to read. We want to determine which client connection and receive the data
 * from it.
 */
void Server::handleServerConnection(int sckt)
{
    //determine connection
    ServerConnection* connection = mConnections->getServerConnection(sckt);
    if (0 != connection)
    {
        Callback* callback = getCallback();
        try
        {
            //receive data
            std::vector<char> result = connection->performReceive();

            if (0 != callback)
            {
                callback->receiveComplete(connection->getIdentifier(), &(result[0]),
                        result.size());
            }

        } catch (std::runtime_error)
        {
            if (0 != callback)
            {
                callback->disconnected(connection->getIdentifier());
            }
            //error retrieving data from client, connection is bad, need to remove it
            mConnections->removeServerConnection(sckt);
        }
    }
}
예제 #2
0
파일: Server.cpp 프로젝트: dbcfd/C11Http
void Server::waitForEvents() throw (std::runtime_error)
{
    //setup file descriptors
    fd_set masterRead;
    fd_set readFds;
    fd_set writeFds;
    FD_ZERO(&masterRead);
    FD_SET(mWakeupPipe[0], &masterRead);
    FD_SET(mConnectSocket->getSocket(), &masterRead);
    mConnections = new Connections(masterRead);
    int serverMax = std::max(mWakeupPipe[0], mConnectSocket->getSocket());

    while (!mHasBeenShutdown)
    {
        int numfds = 0;
        int fdmax = std::max(serverMax, mConnections->getMax());

        FD_ZERO(&readFds);
        FD_ZERO(&writeFds);

        //copy our master list of file descriptors
        readFds = masterRead;
        writeFds = mMasterWrite;

        /**
         * Select from specified file descriptors, will block
         */
        numfds = select(fdmax + 1, &readFds, &writeFds, NULL, 0);

        if (-1 == numfds)
        {
            std::stringstream sstr;
            sstr << "select error " << strerror(errno);
            throw(std::runtime_error(sstr.str()));
        }

        if (mHasBeenShutdown)
            break;

        /**
         * Check all the file descriptors to see which were hit
         */
        for (int i = 0; i <= fdmax; ++i)
        {
            if (FD_ISSET(i, &readFds)) //handle reads
            {
                /**
                 * If connectSocket is ready, that means a connection is formed, any other
                 * socket (per client connection) shows data is ready to be ready from a
                 * client
                 */
                if (i == mConnectSocket->getSocket())
                {
                    //handle new connection
                    try
                    {
                        ServerConnection* client = new ServerConnection(
                        		mConnectSocket->getSocket()); //performs accept, gets identifier
                        getCallback()->connected(client->getIdentifier());
                        mConnections->addServerConnection(client);
                    } catch (std::runtime_error& ex)
                    {
                        //TODO: log connection failure
                        //std::cout << "failure: " << ex.what() << std::endl;
                    }
                }
                else
                {
                    //creating a new connection to a client
                    handleServerConnection(i);
                }
            }

            /**
             * Self-pipe technique to wakeup and add additional file descriptors
             * to select set.
             */
            if (FD_ISSET(mWakeupPipe[0], &readFds)) //performing wakeup
            {
                char buffer[1];
                ::recv(mWakeupPipe[0], &mBuffer, sizeof(mBuffer), 0);
            }

            /**
             * See if we're ready to write to a client connection
             */
            if (FD_ISSET(i, &writeFds))
            {
                //ready for write
                ServerConnection* connection = mConnections->getServerConnection(
                        i);
                if (0 != connection)
                {
                    connection->sendQueuedMessage(getCallback());
                }
                //write complete, clear it from the select list
                FD_CLR(i, &mMasterWrite);
            }
        }
    }

}