コード例 #1
0
/*
* Add new socket to the watcher.
*/
int tnet_transport_add_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_socket_type_t type, tsk_bool_t take_ownership, tsk_bool_t isClient, tnet_tls_socket_handle_t* tlsHandle)
{
    tnet_transport_t *transport = (tnet_transport_t*)handle;
    transport_context_t* context;
    int ret = -1;

    if (!transport) {
        TSK_DEBUG_ERROR("Invalid server handle.");
        return ret;
    }

    if (!(context = (transport_context_t*)transport->context)) {
        TSK_DEBUG_ERROR("Invalid context.");
        return -2;
    }

    if (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)) {
        transport->tls.enabled = tsk_true;
    }

    addSocket(fd, type, transport, take_ownership, isClient, tlsHandle);

    if (WSAEventSelect(fd, context->events[context->count - 1], FD_ALL_EVENTS) == SOCKET_ERROR) {
        removeSocket((int)(context->count - 1), context);
        TNET_PRINT_LAST_ERROR("WSAEventSelect have failed.");
        return -1;
    }

    /* Signal if transport is running */
    if (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started) {
        if (WSASetEvent(context->events[0])) {
            TSK_DEBUG_INFO("New socket added to the network transport.");
            return 0;
        }
        TSK_DEBUG_ERROR("Transport not started yet");
        return -1;
    }

    TSK_DEBUG_INFO("Adding socket delayed");
    return 0;
}
コード例 #2
0
int tnet_transport_unprepare(tnet_transport_t *transport)
{
    //int ret = -1;
    transport_context_t *context;

    if(!transport || !transport->context) {
        TSK_DEBUG_ERROR("Invalid parameter.");
        return -1;
    }
    else {
        context = transport->context;
    }

    if(!transport->prepared) {
        return 0;
    }

    transport->prepared = tsk_false;

    while(context->count) {
        removeSocket(0, context); // safe
    }

    /* reset both R and W sides */
    if (context->pipeW != -1) {
        if (close(context->pipeW)) {
            TSK_DEBUG_ERROR("Failed to close pipeW:%d", context->pipeW);
        }
        context->pipeW = -1;
    }
    context->pipeR = -1;

    // destroy master as it has been closed by removeSocket()
    TSK_OBJECT_SAFE_FREE(transport->master);

    return 0;
}
コード例 #3
0
/* 
* Add new socket to the watcher.
*/
int tnet_transport_add_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_socket_type_t type, tsk_bool_t take_ownership, tsk_bool_t isClient)
{
	tnet_transport_t *transport = (tnet_transport_t*)handle;
	transport_context_t* context;
	int ret = -1;

	if(!transport){
		TSK_DEBUG_ERROR("Invalid server handle.");
		return ret;
	}

	if(!(context = (transport_context_t*)transport->context)){
		TSK_DEBUG_ERROR("Invalid context.");
		return -2;
	}

	if(TNET_SOCKET_TYPE_IS_TLS(type)){
		transport->tls.have_tls = 1;
	}

	addSocket(fd, type, transport, take_ownership, isClient);
	if(WSAEventSelect(fd, context->events[context->count - 1], FD_ALL_EVENTS) == SOCKET_ERROR){
		removeSocket((context->count - 1), context);
		TNET_PRINT_LAST_ERROR("WSAEventSelect have failed.");
		return -1;
	}

	/* Signal */
	if(WSASetEvent(context->events[0])){
		TSK_DEBUG_INFO("New socket added to the network transport.");
		return 0;
	}

	// ...
	
	return -1;
}
コード例 #4
0
void SslServer::process(const PeerData &pd)
{
    QByteArray data = pd.data;

    if (data.isEmpty())
        return;

    quint8 command = getValue<quint8>(data.mid(0, 1));
    data.remove(0, 1);

    QSslSocket *socket = m_socket_hash[pd.descriptor];

    if (!socket)
        return;

    switch (command)
    {
    case ServerCommand::PeerTryConnect:
    {
        if (data.size() != 20)
        {
            removeSocket(socket);
            return;
        }

        QByteArray peer_id = data;

        peer_id = cleanString(QLatin1String(peer_id)).toLatin1().leftJustified(peer_id.length(), char(0), true);

        if (m_unavailable_list.contains(peer_id))
        {
            DEBUG_FUNCTION("IP:" << qPrintable(socket->peerAddress().toString()) << "User origin:" << qPrintable(m_id_hash.value(socket))
                           << "User target:" << qPrintable(peer_id) << "Attempt to connect to unavailable user!");
            writeWarning(socket, "You're trying to connect to a unavailable user!");
            return;
        }

        if (peer_id == m_id_hash[socket])
        {
            DEBUG_FUNCTION("IP:" << qPrintable(socket->peerAddress().toString()) << "User origin:" << qPrintable(m_id_hash.value(socket))
                           << "User target:" << qPrintable(peer_id) << "Attempt to connect to itself!");
            writeWarning(socket, "You're trying to connect to itself!");
            return;
        }

        if (!m_id_list.contains(peer_id))
        {
            DEBUG_FUNCTION("IP:" << qPrintable(socket->peerAddress().toString()) << "User origin:" << qPrintable(m_id_hash.value(socket))
                           << "User target:" << qPrintable(peer_id) << "Attempt to connect to non connected user!");
            writeWarning(socket, "You're trying to connect to a non connected user!");
            return;
        }

        QSslSocket *target_socket = m_id_hash.key(peer_id);

        if (m_connecting_connected_list.contains(target_socket))
        {
            DEBUG_FUNCTION("IP:" << qPrintable(socket->peerAddress().toString()) << "User origin:" << qPrintable(m_id_hash.value(socket))
                           << "User target:" << qPrintable(peer_id) << "Attempt to connect to already connected user!");
            writeWarning(socket, "User already connected!");
            return;
        }

        m_connecting_connected_list.append(socket);
        m_connecting_connected_list.append(target_socket);

        QByteArray data;
        data.append(getBytes<quint8>(ServerCommand::ConnectionRequested));
        data.append(getBytes<quint32>(socket->localAddress().toIPv4Address()));
        data.append(m_id_hash[socket]);

        m_accept_hash.insert(target_socket, socket);

        DEBUG_FUNCTION("IP:" << qPrintable(socket->peerAddress().toString()) << "User origin:" << qPrintable(m_id_hash.value(socket))
                       << "User target:" << qPrintable(peer_id) << "Trying to connect to peer!");

        target_socket->write(getBytes<qint32>(data.size()));
        target_socket->write(data);

        break;
    }
    case ServerCommand::ConnectionAnswer:
    {
        if (data.size() != 1)
        {
            removeSocket(socket);
            return;
        }

        QSslSocket *socket_starter = m_accept_hash[socket];

        bool accepted = getValue<bool>(data.mid(0, 1));

        if (!socket_starter)
        {
            m_connecting_connected_list.removeAll(socket_starter);
            m_connecting_connected_list.removeAll(socket);

            if (accepted)
            {
                DEBUG_FUNCTION("IP:" << qPrintable(socket->peerAddress().toString()) << "User origin:" << qPrintable(m_id_hash.value(socket))
                               << "User disconnected or canceled operation!");
                writeWarning(socket, "Can't connect to user because it's disconnected or canceled operation!");
            }

            return;
        }

        if (!accepted)
        {
            QSslSocket *socket1 = socket_starter;
            QSslSocket *socket2 = socket;

            m_accept_hash.remove(socket1);
            m_accept_hash.remove(socket2);

            m_connecting_connected_list.removeAll(socket1);
            m_connecting_connected_list.removeAll(socket2);

            DEBUG_FUNCTION("IP:" << qPrintable(socket->peerAddress().toString()) << "User origin:" << qPrintable(m_id_hash.value(socket))
                           << "User target:" << qPrintable(m_id_hash.value(socket_starter)) << "User refused connection!");
            writeWarning(socket_starter, "User refused connection!");

            return;
        }

        QSslSocket *socket1 = socket;
        QSslSocket *socket2 = socket_starter;

        m_connected_1.insert(socket1, socket2);
        m_connected_2.insert(socket2, socket1);

        QByteArray data1;
        QByteArray data2;

        data1.append(getBytes<quint8>(ServerCommand::ConnectedToPeer));
        data2.append(getBytes<quint8>(ServerCommand::ConnectedToPeer));

        QByteArray password = OpenSslLib::RANDbytes(32);

        data1.append(m_id_hash[socket1]);
        data1.append(password);

        data2.append(m_id_hash[socket2]);
        data2.append(password);

        socket1->write(getBytes<qint32>(data2.size()));
        socket1->write(data2);

        socket2->write(getBytes<qint32>(data1.size()));
        socket2->write(data1);

        DEBUG_FUNCTION("IP:" << qPrintable(socket->peerAddress().toString()) << "User origin:" << qPrintable(m_id_hash.value(socket_starter))
                       << "User target:" << qPrintable(m_id_hash.value(socket)) << "Connected!");

        break;
    }
    case ServerCommand::DisconnectedFromPeer:
    {
        QSslSocket *target_socket = m_connected_1.value(socket);

        if (!target_socket)
            target_socket = m_connected_2.value(socket);

        DEBUG_FUNCTION("IP:" << qPrintable(socket->peerAddress().toString()) << "User origin:" << qPrintable(m_id_hash.value(socket))
                       << "User target:" << qPrintable(m_id_hash.value(target_socket)) << "Disconnected from peer!");

        disconnectedFromPeer(socket);

        break;
    }
    case ServerCommand::P2PData:
    {
        QSslSocket *target_socket = m_connected_1.value(socket);

        if (!target_socket)
            target_socket = m_connected_2.value(socket);

        if (!target_socket)
            break;

        data.prepend(getBytes<quint8>(ServerCommand::P2PData));

        target_socket->write(getBytes<qint32>(data.size()));
        target_socket->write(data);

        m_alive_hash[socket].restart();

        m_alive_hash[target_socket].restart();

        break;
    }
    case ServerCommand::Alive:
    {
        m_alive_hash[socket].restart();

        break;
    }
    case ServerCommand::XML:
    {
        processCommandXML(socket, data);

        break;
    }
    default:
    {
        removeSocket(socket);
        return;
    }
    }
}
コード例 #5
0
ファイル: Server.cpp プロジェクト: SignZ/DrawAttack
void Server::run() {
	if (m_wordList.size() == 0)
		return;

	cpp3ds::Clock pingClock;

	if (m_listener.listen(m_port) == cpp3ds::Socket::Done) {
		m_selector.add(m_listener);
		std::cout << "Started DrawAttack server on port " << m_port << "..." << std::endl;
		m_running = true;
		while (m_running) {
			// Make the selector wait for data on any socket
			if (m_selector.wait(cpp3ds::milliseconds(1000))) {
				if (m_selector.isReady(m_listener)) {
					cpp3ds::TcpSocket* socket = new cpp3ds::TcpSocket;
					if (m_listener.accept(*socket) == cpp3ds::Socket::Done)
					{
						std::cout << "client connected" << std::endl;
						// Add the new client to the clients list
						sendPlayerData(socket);
						socket->send(m_drawDataPacket);
						m_pingResponses[socket] = true;
						m_sockets.emplace_back(socket);
						m_selector.add(*socket);
					} else {
						delete socket;
					}
				}
				else
				{
					for (auto& socket : m_sockets) {
						if (m_selector.isReady(*socket)) {
							processSocket(socket);
						}
					}
				}
			}

			// Ping clients and check for previous response
			if (pingClock.getElapsedTime() >= cpp3ds::seconds(PING_TIMEOUT)) {
				cpp3ds::Packet packet;
				packet << NetworkEvent::Ping;
				for (auto i = m_sockets.begin(); i != m_sockets.end();) {
					if (m_pingResponses[*i]) {
						(*i)->send(packet);
						m_pingResponses[*i] = false;
						i++;
					} else {
						// Timed out socket
						std::cout << "A socket timed out." << std::endl;
						removeSocket(*i);
					}
				}
				pingClock.restart();
			}

			if (m_mode == Play) {
				if (m_roundClock.getElapsedTime() >= cpp3ds::seconds(ROUND_DURATION)) {
					// Round time ended, nobody won
					cpp3ds::Packet packet;
					packet << NetworkEvent::RoundWord << m_currentWord << NetworkEvent::RoundFail;
					sendToAllSockets(packet);
					m_roundClock.restart();
					m_mode = Wait;
				}
				if (m_roundTimeoutClock.getElapsedTime() >= cpp3ds::seconds(ROUND_TIMEOUT)) {
					// Drawer hasn't been active, so end round
					cpp3ds::Packet packet;
					packet << NetworkEvent::RoundWord << m_currentWord << NetworkEvent::RoundTimeout;
					sendToAllSockets(packet);
					m_roundClock.restart();
					m_mode = Wait;
				}
			} else if (m_mode == Wait) {
				if (m_players.size() >= MIN_PLAYERS) {
					if (m_roundClock.getElapsedTime() >= cpp3ds::seconds(ROUND_INTERMISSION)) {
						Player drawer = getNextDrawer();
						startRound(drawer, getNextWord(), ROUND_DURATION);
					}
				}
			}
		}
	} else {
		cpp3ds::err() << "Failed to listen on port " << m_port << std::endl;
	}
}
コード例 #6
0
ファイル: Server.cpp プロジェクト: SignZ/DrawAttack
void Server::processSocket(cpp3ds::TcpSocket* socket)
{
	cpp3ds::Packet packet;
	cpp3ds::Socket::Status status = socket->receive(packet);
	if (status == cpp3ds::Socket::Done)
	{
		cpp3ds::Packet packetSend;
		NetworkEvent event;

		while (NetworkEvent::packetToEvent(packet, event))
		{
			if (!validateEvent(socket, event))
				continue;

			switch(event.type) {
				case NetworkEvent::Version:
					if (event.server.message.compare(SERVER_VERSION) != 0) {
						packet.clear();
						std::string message = _("Incompatible client version %s (needs %s)", event.server.message.c_str(), SERVER_VERSION);
						packet << NetworkEvent::ServerShutdown << message;
						socket->send(packet);
						removeSocket(socket);
					}
					break;
				case NetworkEvent::PlayerConnected: {
					std::cout << event.player.name << " connected." << std::endl;
					bool collision = false;
					for (auto& player : m_players) {
						if (event.player.name.compare(player.second.getName()) == 0) {
							collision = true;
							break;
						}
					}
					if (collision) {
						cpp3ds::Packet packet;
						packet << NetworkEvent::PlayerNameCollision << event.player.name;
						socket->send(packet);
						break;
					}
					Player player(event.player.name);
					m_players.emplace(socket, player);
					NetworkEvent::eventToPacket(event, packetSend);
					sendToAllSockets(packetSend);
					packetSend.clear();
					if (m_players.size() < MIN_PLAYERS) {
						sendWaitForPlayers(socket, MIN_PLAYERS);
					}
					break;
				}
				case NetworkEvent::Text: {
					NetworkEvent::eventToPacket(event, packetSend);
					if (m_mode != Play)
						break;
					std::string word = event.text.value.toAnsiString();
					std::transform(word.begin(), word.end(), word.begin(), ::tolower);
					if (word.compare(m_currentWord) == 0) {
						std::cout << event.text.name << " won!" << std::endl;
						packetSend << NetworkEvent::RoundWord << word << NetworkEvent::RoundWin << event.text.name;
						for (auto& player : m_players) {
							if (player.second.getName().compare(event.text.name) == 0)
								player.second.incrementScore();
							if (player.first == m_currentDrawer)
								player.second.incrementScore();
						}
						m_roundClock.restart();
						m_mode = Wait;
					}
					break;
				}
				case NetworkEvent::DrawMove:
				case NetworkEvent::DrawEndline:
					m_drawDataPacket << event.type << event.draw.x << event.draw.y;
					NetworkEvent::eventToPacket(event, packetSend);
					m_roundTimeoutClock.restart();
					break;
				case NetworkEvent::DrawClear:
					clearDrawData();
					NetworkEvent::eventToPacket(event, packetSend);
					m_roundTimeoutClock.restart();
					break;
				case NetworkEvent::DrawUndo: {
					m_drawDataPacket << event.type;
					NetworkEvent::eventToPacket(event, packetSend);
					m_roundTimeoutClock.restart();
					break;
				}
				case NetworkEvent::RoundPass:
					packetSend << NetworkEvent::RoundWord << m_currentWord;
					NetworkEvent::eventToPacket(event, packetSend);
					m_roundClock.restart();
					m_mode = Wait;
					break;
				case NetworkEvent::Ping:
					m_pingResponses[socket] = true;
					break;
				default:
					break;
			}
		}
		if (!packetSend.endOfPacket())
			sendToAllSockets(packetSend);

	} else if (status == cpp3ds::Socket::Disconnected || status == cpp3ds::Socket::Error) {
		removeSocket(socket);
	}
}
コード例 #7
0
ファイル: CommServer.cpp プロジェクト: anthonypesce/cyphesis
/// \brief Main program loop called repeatedly.
///
/// Call the server idle function to do its processing. If the server is
/// is currently busy, poll all the sockets as quickly as possible.
/// If the server is idle, use select() to sleep on the sockets for
/// a short period of time. If any sockets get broken or disconnected,
/// they are noted and closed down at the end of the process.
void CommServer::poll(bool busy)
{
    // This is the main code loop.
    // Classic select code for checking incoming data on sockets.

    // It would be useful to let idle know if we are currently dealing with
    // traffic
    // bool busy = idle();

#ifdef HAVE_EPOLL_CREATE
    static const int max_events = 16;

    static struct epoll_event events[max_events];

    int rval = ::epoll_wait(m_epollFd, events, max_events, (busy ? 0 : 100));

    if (rval <  0) {
        if (errno != EINTR) {
            log(CYLOG_ERROR, String::compose("epoll_wait: %1", strerror(errno)));
        }
        return;
    }

    m_congested = (rval != 0) || (m_congested && busy);

    if (rval == max_events) {
        // If we see this alot, we should increase the maximum
        log(NOTICE, "epoll_wait returned the maximum number of events.");
    }

    for (int i = 0; i < rval; ++i) {
        struct epoll_event & event = events[i];
        CommSocket * cs = static_cast<CommSocket *>(event.data.ptr);

        if (event.events & EPOLLERR) {
            // FIXME This is triggered by an outgoing connect fail, and by
            // process/src/bint. What to do?
            // log(WARNING, "Socket error returned by epoll_wait()");
        }
        if (event.events & EPOLLIN) {
            if (cs->eof()) {
                removeSocket(cs);
            } else {
                if (cs->read() != 0) {
                    // Remove it?
                    // FIXME It could be bad to do this, as dispatch()
                    // has not been called.
                    removeSocket(cs);
                } else {
                    cs->dispatch();
                }
            }
        } else if (event.events & EPOLLHUP) {
            removeSocket(cs);
        }
    }
#else // HAVE_EPOLL_CREATE

    fd_set sock_fds;
    SOCKET_TYPE highest = 0;
    struct timeval tv;

    tv.tv_sec = 0;
    tv.tv_usec = (busy ? 0 : 100000);

    FD_ZERO(&sock_fds);

    bool pendingConnections = false;
    CommSocketSet::const_iterator Iend = m_sockets.end();
    for (CommSocketSet::const_iterator I = m_sockets.begin(); I != Iend; ++I) {
       if (!(*I)->isOpen()) {
           pendingConnections = true;
           continue;
       }
       SOCKET_TYPE socket_fd = (*I)->getFd();
       FD_SET(socket_fd, &sock_fds);
       if (socket_fd > highest) {
           highest = socket_fd;
       }
    }
    highest++;
    int rval = ::select(highest, &sock_fds, NULL, NULL, &tv);

    if (rval < 0) {
        if (errno != EINTR) {
            log(CYLOG_ERROR, "Error caused by select() in main loop");
            logSysError(CYLOG_ERROR);
        }
        return;
    }

    if (rval == 0 && !pendingConnections) {
        return;
    }
    
    // We assume Iend is still valid. m_sockets must not have been modified
    // between Iend's initialisation and here.
    CommSocketSet obsoleteConnections;
    for (CommSocketSet::const_iterator I = m_sockets.begin(); I != Iend; ++I) {
       CommSocket * socket = *I;
       if (!socket->isOpen()) {
           obsoleteConnections.insert(socket);
           continue;
       }
       if (FD_ISSET(socket->getFd(), &sock_fds)) {
           if (!socket->eof()) {
               if (socket->read() != 0) {
                   debug(std::cout << "Removing socket due to failure"
                                   << std::endl << std::flush;);
                   obsoleteConnections.insert(socket);
               }
               socket->dispatch();
           } else {
コード例 #8
0
void __CFSocketCallBack(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) {
    // Extract the context
    tnet_transport_t *transport = (tnet_transport_t *) info;
	transport_context_t *context = transport->context;
    
    // Extract the native socket
    int fd = CFSocketGetNative(s);
    transport_socket_t *sock = (transport_socket_t *) getSocket(context, fd);

    /* lock context */
    tsk_safeobj_lock(context);
    
    switch (callbackType) {
        case kCFSocketReadCallBack:
        {
            int ret;
            tsk_size_t len = 0;
            void* buffer = 0;
            tnet_transport_event_t* e;
            
            if (tnet_ioctlt(sock->fd, FIONREAD, &len) < 0) {
                TNET_PRINT_LAST_ERROR("IOCTLT FAILED.");
                break;
            }
            
            if (!len) {
                TSK_DEBUG_WARN("IOCTLT returned zero.");
                TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, sock->fd);
                removeSocket(sock, context);
                break;
            }
            
            if (!(buffer = tsk_calloc(len, sizeof(uint8_t)))) {
                TSK_DEBUG_ERROR("TSK_CALLOC FAILED.");
                break;
            }
            
            if ((ret = tnet_sockfd_recv(sock->fd, buffer, len, 0)) < 0) {
                TSK_FREE(buffer);
                removeSocket(sock, context);
                TNET_PRINT_LAST_ERROR("recv have failed.");
                break;
            }
            else if ((len != (tsk_size_t)ret) && len) { // useless test ?
                len = (tsk_size_t)ret;
                // buffer = tsk_realloc(buffer, len);
            }
            
            TSK_DEBUG_INFO("__CFSocketCallBack -> %u bytes read", len);
            
            e = tnet_transport_event_create(event_data, transport->callback_data, sock->fd);
            e->data = buffer;
            e->size = len;
            
            TSK_RUNNABLE_ENQUEUE_OBJECT(TSK_RUNNABLE(transport), e);
            
            break;
        }
        case kCFSocketAcceptCallBack:
        case kCFSocketConnectCallBack:
        case kCFSocketDataCallBack:
        case kCFSocketWriteCallBack:
        default:
        {
            // Not Implemented
            assert(42 == 0);
            break;
        }
    }
    
    /* unlock context */
    tsk_safeobj_unlock(context);
}
コード例 #9
0
void __CFReadStreamClientCallBack(CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) {
    // Extract the context
    tnet_transport_t *transport = (tnet_transport_t *) clientCallBackInfo;
	transport_context_t *context = transport->context;
    
    /* lock context */
    tsk_safeobj_lock(context);
    
    // Extract the native socket
    CFDataRef data = CFReadStreamCopyProperty(stream, kCFStreamPropertySocketNativeHandle);
    CFSocketNativeHandle fd;
    CFDataGetBytes(data, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8*) &fd);
    CFRelease(data);
    transport_socket_t *sock = (transport_socket_t *) getSocket(context, fd);
    
    switch(eventType) {
        case kCFStreamEventOpenCompleted:
        {
            TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> kCFStreamEventOpenCompleted");
            break;
        }
        case kCFStreamEventHasBytesAvailable:
        {
            tsk_size_t len = 0;
            void *buffer = 0;
            tnet_transport_event_t* e;
            
            // Allocate a standard buffer
            len = TNET_BUFFER_SIZE;
            if (!(buffer = tsk_calloc(len, sizeof(uint8_t)))) {
                TSK_DEBUG_ERROR("TSK_CALLOC FAILED.");
                break;
            }
            
            // Process to read data
            CFIndex index = CFReadStreamRead(stream, buffer, TNET_BUFFER_SIZE);
            len = index;
            
            TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> %u bytes read", len);
            
            e = tnet_transport_event_create(event_data, transport->callback_data, sock->fd);
            e->data = buffer;
            e->size = len;
            
            TSK_RUNNABLE_ENQUEUE_OBJECT(TSK_RUNNABLE(transport), e);
            
            break;
        }
        case kCFStreamEventEndEncountered:
        case kCFStreamEventErrorOccurred:
        {
            // Get the error code
            CFErrorRef error = CFReadStreamCopyError(stream);
            CFIndex index = CFErrorGetCode(error);
            CFRelease(error);
                        
            TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> Error %lu", index);
            
            TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, sock->fd);
            removeSocket(sock, context);
            break;
        }
        default:
        {
            // Not Implemented
            assert(42 == 0);
            break;
        }
    }
    
    /* unlock context */
    tsk_safeobj_unlock(context);
}
コード例 #10
0
/*=== Main thread */
void *tnet_transport_mainthread(void *param)
{
    tnet_transport_t *transport = param;
    transport_context_t *context = transport->context;
    int ret, status;
    tsk_size_t i;
    tsk_bool_t is_stream;
    tnet_fd_t fd;

    struct sockaddr_storage remote_addr = {0};
    transport_socket_xt* active_socket;

    /* check whether the transport is already prepared */
    if(!transport->prepared) {
        TSK_DEBUG_ERROR("Transport must be prepared before strating.");
        goto bail;
    }

    is_stream = TNET_SOCKET_TYPE_IS_STREAM(transport->master->type);

    TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d} using master fd {%d} with type {%d} with max_fds {%lu}...",
                   transport->description,
                   transport->master->ip,
                   transport->master->port,
                   transport->master->fd,
                   transport->master->type,
                   sizeof(context->ufds)/sizeof(context->ufds[0]));

    while(TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started) {
        context->polling = tsk_true;
        ret = tnet_poll(context->ufds, context->count, -1);
        context->polling = tsk_false;
        if(ret < 0) {
            TNET_PRINT_LAST_ERROR("poll() have failed.");
            goto bail;
        }

        if(!TSK_RUNNABLE(transport)->running && !TSK_RUNNABLE(transport)->started) {
            TSK_DEBUG_INFO("Stopping [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type);
            goto bail;
        }

        /* lock context */
        tsk_safeobj_lock(context);

        /* == == */
        for(i=0; i<context->count; i++) {
            if(!context->ufds[i].revents) {
                continue;
            }

            // TSK_DEBUG_INFO("REVENTS(i=%d) = %d", i, context->ufds[i].revents);

            if(context->ufds[i].fd == context->pipeR) {
                TSK_DEBUG_INFO("PipeR event = %d", context->ufds[i].revents);
                if(context->ufds[i].revents & TNET_POLLIN) {
                    static char __buffer[1024];
                    if(read(context->pipeR, __buffer, sizeof(__buffer)) < 0) {
                        TNET_PRINT_LAST_ERROR("Failed to read from the Pipe");
                    }
                }
                else if(context->ufds[i].revents & TNET_POLLHUP) {
                    TNET_PRINT_LAST_ERROR("Pipe Error");
                    goto bail;
                }
                context->ufds[i].revents = 0;
                continue;
            }

            /* Get active event and socket */
            active_socket = context->sockets[i];

            /*================== TNET_POLLHUP ==================*/
            if(context->ufds[i].revents & (TNET_POLLHUP)) {
                if(context->ufds[i].revents & TNET_POLLOUT) {
                    TSK_DEBUG_INFO("POLLOUT and POLLHUP are exclusive");
                }
                else {
                    fd = active_socket->fd;
                    TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLHUP(%d)", transport->description, fd);

                    tnet_transport_remove_socket(transport, &active_socket->fd);
                    TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd);
                    continue;
                }
            }

            /*================== TNET_POLLERR ==================*/
            if(context->ufds[i].revents & (TNET_POLLERR)) {
                fd = active_socket->fd;
                TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLERR(%d)", transport->description, fd);

                tnet_transport_remove_socket(transport, &active_socket->fd);
                TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd);
                continue;
            }

            /*================== TNET_POLLNVAL ==================*/
            if(context->ufds[i].revents & (TNET_POLLNVAL)) {
                fd = active_socket->fd;
                TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLNVAL(%d)", transport->description, fd);

                tnet_transport_remove_socket(transport, &active_socket->fd);
                TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd);
                continue;
            }

            /*================== POLLIN ==================*/
            if(context->ufds[i].revents & TNET_POLLIN) {
                tsk_size_t len = 0;
                void* buffer = tsk_null;
                tnet_transport_event_t* e;

                // TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLIN(%d)", transport->description, active_socket->fd);

                /* check whether the socket is paused or not */
                if(active_socket->paused) {
                    TSK_DEBUG_INFO("Socket is paused");
                    goto TNET_POLLIN_DONE;
                }

                /* Retrieve the amount of pending data.
                 * IMPORTANT: If you are using Symbian please update your SDK to the latest build (August 2009) to have 'FIONREAD'.
                 * This apply whatever you are using the 3rd or 5th edition.
                 * Download link: http://wiki.forum.nokia.com/index.php/Open_C/C%2B%2B_Release_History
                 */
                ret = tnet_ioctlt(active_socket->fd, FIONREAD, &len);
                if((ret < 0 || !len) && is_stream) {
                    /* It's probably an incoming connection --> try to accept() it */
                    int listening = 0, remove_socket = 0;
                    socklen_t socklen = sizeof(listening);

                    TSK_DEBUG_INFO("ioctlt(%d), len=%u returned zero or failed", active_socket->fd, (unsigned)len);

                    // check if socket is listening
                    if(getsockopt(active_socket->fd, SOL_SOCKET, SO_ACCEPTCONN, &listening, &socklen) != 0) {
#if defined(BSD) /* old FreeBSD versions (and OSX up to Lion) do not support SO_ACCEPTCONN */
                        listening = 1;
#else
                        TNET_PRINT_LAST_ERROR("getsockopt(SO_ACCEPTCONN, %d) failed\n", active_socket->fd);
                        /* not socket accepted -> no socket to remove */
                        goto TNET_POLLIN_DONE;
#endif
                    }
                    if (listening) {
                        if((fd = accept(active_socket->fd, tsk_null, tsk_null)) != TNET_INVALID_SOCKET) {
                            TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_ACCEPT(fd=%d)", transport->description, fd);
                            addSocket(fd, transport->master->type, transport, tsk_true, tsk_false, tsk_null);
                            TSK_RUNNABLE_ENQUEUE(transport, event_accepted, transport->callback_data, fd);
                            if(active_socket->tlshandle) {
                                transport_socket_xt* tls_socket;
                                if((tls_socket = getSocket(context, fd))) {
                                    if(tnet_tls_socket_accept(tls_socket->tlshandle) != 0) {
                                        TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd);
                                        tnet_transport_remove_socket(transport, &fd);
                                        TNET_PRINT_LAST_ERROR("SSL_accept() failed");
                                        continue;
                                    }
                                }
                            }
                        }
                        else {
                            TNET_PRINT_LAST_ERROR("accept(%d) failed", active_socket->fd);
                            remove_socket = 1;
                        }
                    }
                    else {
                        TSK_DEBUG_INFO("Closing socket with fd = %d because ioctlt() returned zero or failed", active_socket->fd);
                        remove_socket = 1;
                    }

                    if(remove_socket) {
                        fd = active_socket->fd;
                        tnet_transport_remove_socket(transport, &active_socket->fd);
                        TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd);
                        continue;
                    }
                    goto TNET_POLLIN_DONE;
                }

                if(len <= 0) {
#if defined(__ANDROID__) || defined(ANDROID)
                    // workaround for indoona OSX which sends bodiless UDP packets
                    // vand Android requires to call recv() even if len is equal to zero
                    if(len == 0 && ret == 0) {
                        static char __fake_buff[1];
                        ret = recv(active_socket->fd, __fake_buff, len, 0);
                    }
#endif
                    goto TNET_POLLIN_DONE;
                }

                if (!(buffer = tsk_calloc(len, sizeof(uint8_t)))) {
                    TSK_DEBUG_ERROR("TSK_CALLOC FAILED");
                    goto TNET_POLLIN_DONE;
                }

                // Retrieve the remote address
                if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) {
                    ret = tnet_getpeername(active_socket->fd, &remote_addr);
                }

                // Receive the waiting data
                if (active_socket->tlshandle) {
                    int isEncrypted;
                    tsk_size_t tlslen = len;
                    if ((ret = tnet_tls_socket_recv(active_socket->tlshandle, &buffer, &tlslen, &isEncrypted)) == 0) {
                        if (isEncrypted) {
                            TSK_FREE(buffer);
                            goto TNET_POLLIN_DONE;
                        }
                        if (ret == 0) {
                            len = ret = tlslen;
                        }
                    }
                }
                else {
                    if (is_stream) {
                        ret = tnet_sockfd_recv(active_socket->fd, buffer, len, 0);
                    }
                    else {
                        ret = tnet_sockfd_recvfrom(active_socket->fd, buffer, len, 0, (struct sockaddr*)&remote_addr);
                    }
                }

                if(ret < 0) {
                    TSK_FREE(buffer);
                    status = tnet_geterrno();
                    // do not remove the socket for i/o pending errors
                    if (status == TNET_ERROR_WOULDBLOCK || status == TNET_ERROR_INPROGRESS || status == TNET_ERROR_EAGAIN) {
                        TSK_DEBUG_WARN("recv returned error code:%d", status);
                    }
                    else {
                        TNET_PRINT_LAST_ERROR("recv/recvfrom have failed");
                        removeSocket(i, context);
                    }
                    goto TNET_POLLIN_DONE;
                }

                if((len != (tsk_size_t)ret) && len) {
                    len = (tsk_size_t)ret;
                    // buffer = tsk_realloc(buffer, len);
                }

                if(len > 0) {
                    transport->bytes_in += len;
                    e = tnet_transport_event_create(event_data, transport->callback_data, active_socket->fd);
                    e->data = buffer, buffer = tsk_null;
                    e->size = len;
                    e->remote_addr = remote_addr;

                    TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e);
                }
                TSK_FREE(buffer);

TNET_POLLIN_DONE:
                /*context->ufds[i].revents &= ~TNET_POLLIN*/
                ;
            }


            /*================== TNET_POLLOUT ==================*/
            if(context->ufds[i].revents & TNET_POLLOUT) {
                TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLOUT", transport->description);
                if(!active_socket->connected) {
                    active_socket->connected = tsk_true;
                    TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, active_socket->fd);
                }
                //else{
                context->ufds[i].events &= ~TNET_POLLOUT;
                //}
            }


            /*================== TNET_POLLPRI ==================*/
            if(context->ufds[i].revents & TNET_POLLPRI) {
                TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLPRI", transport->description);
            }

            context->ufds[i].revents = 0;
        }/* for */

done:
        /* unlock context */
        tsk_safeobj_unlock(context);

    } /* while */

bail:

    TSK_DEBUG_INFO("Stopped [%s] server with IP {%s} on port {%d}", transport->description, transport->master->ip, transport->master->port);
    return 0;
}
コード例 #11
0
/*=== Main thread */
void* TSK_STDCALL tnet_transport_mainthread(void *param)
{
    tnet_transport_t *transport = (tnet_transport_t*)param;
    transport_context_t *context = (transport_context_t*)transport->context;
    DWORD evt;
    WSANETWORKEVENTS networkEvents;
    DWORD flags = 0;
    int ret;

    struct sockaddr_storage remote_addr = { 0 };
    WSAEVENT active_event;
    transport_socket_xt* active_socket;
    int index;

    TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type);

    while (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started) {
        /* Wait for multiple events */
        if ((evt = WSAWaitForMultipleEvents((DWORD)context->count, context->events, FALSE, WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) {
            TNET_PRINT_LAST_ERROR("WSAWaitForMultipleEvents have failed.");
            goto bail;
        }

        if (!TSK_RUNNABLE(transport)->running && !TSK_RUNNABLE(transport)->started) {
            goto bail;
        }

        /* lock context */
        tsk_safeobj_lock(context);

        /* Get active event and socket */
        index = (evt - WSA_WAIT_EVENT_0);
        active_event = context->events[index];
        if (!(active_socket = context->sockets[index])) {
            goto done;
        }

        /* Get the network events flags */
        if (WSAEnumNetworkEvents(active_socket->fd, active_event, &networkEvents) == SOCKET_ERROR) {
            TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd);
            TNET_PRINT_LAST_ERROR("WSAEnumNetworkEvents have failed.");

            tsk_safeobj_unlock(context);
            goto bail;
        }

        /*================== FD_ACCEPT ==================*/
        if (networkEvents.lNetworkEvents & FD_ACCEPT) {
            tnet_fd_t fd;

            TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_ACCEPT", transport->description);

            if (networkEvents.iErrorCode[FD_ACCEPT_BIT]) {
                TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd);
                TNET_PRINT_LAST_ERROR("ACCEPT FAILED.");
                goto done;
            }

            /* Accept the connection */
            if ((fd = (tnet_fd_t)WSAAccept(active_socket->fd, NULL, NULL, AcceptCondFunc, (DWORD_PTR)context)) != INVALID_SOCKET) {
                /* Add the new fd to the server context */
                addSocket(fd, transport->master->type, transport, tsk_true, tsk_false, tsk_null);
                if (active_socket->tlshandle) {
                    transport_socket_xt* tls_socket;
                    if ((tls_socket = getSocket(context, fd))) {
                        if (tnet_tls_socket_accept(tls_socket->tlshandle)) {
                            tnet_transport_remove_socket(transport, &fd);
                            TNET_PRINT_LAST_ERROR("SSL_accept() failed");
                            goto done;
                        }
                    }
                }
                if (WSAEventSelect(fd, context->events[context->count - 1], FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR) {
                    tnet_transport_remove_socket(transport, &fd);
                    TNET_PRINT_LAST_ERROR("WSAEventSelect() have failed.");
                    goto done;
                }
                TSK_RUNNABLE_ENQUEUE(transport, event_accepted, transport->callback_data, fd);
            }
            else {
                TNET_PRINT_LAST_ERROR("ACCEPT FAILED.");
                goto done;
            }




        }

        /*================== FD_CONNECT ==================*/
        if (networkEvents.lNetworkEvents & FD_CONNECT) {
            TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_CONNECT", transport->description);

            if (networkEvents.iErrorCode[FD_CONNECT_BIT]) {
                tnet_fd_t fd = active_socket->fd;
                TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd);
                tnet_transport_remove_socket(transport, &fd);
                TNET_PRINT_LAST_ERROR("CONNECT FAILED.");
                goto done;
            }
            else {
                TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, active_socket->fd);
                active_socket->connected = 1;
            }
        }


        /*================== FD_READ ==================*/
        if (networkEvents.lNetworkEvents & FD_READ) {
            DWORD readCount = 0;
            WSABUF wsaBuffer;

            /* TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_READ", transport->description); */

            /* check whether the socket is paused or not */
            if (active_socket->paused) {
                TSK_DEBUG_INFO("Socket is paused");
                goto FD_READ_DONE;
            }

            if (networkEvents.iErrorCode[FD_READ_BIT]) {
                TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd);
                TNET_PRINT_LAST_ERROR("READ FAILED.");
                goto done;
            }

            /* Retrieve the amount of pending data */
            if (tnet_ioctlt(active_socket->fd, FIONREAD, &(wsaBuffer.len)) < 0) {
                TNET_PRINT_LAST_ERROR("IOCTLT FAILED.");
                goto done;
            }

            if (!wsaBuffer.len) {
                goto done;
            }

            /* Alloc data */
            if (!(wsaBuffer.buf = tsk_calloc(wsaBuffer.len, sizeof(uint8_t)))) {
                goto done;
            }

            /* Retrieve the remote address */
            if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) {
                ret = tnet_getpeername(active_socket->fd, &remote_addr);
            }

            /* Receive the waiting data. */
            if (active_socket->tlshandle) {
                int isEncrypted;
                tsk_size_t len = wsaBuffer.len;
                if (!(ret = tnet_tls_socket_recv(active_socket->tlshandle, &wsaBuffer.buf, &len, &isEncrypted))) {
                    if (isEncrypted) {
                        TSK_FREE(wsaBuffer.buf);
                        goto done;
                    }
                    wsaBuffer.len = (ULONG)len;
                }
            }
            else {
                if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) {
                    ret = WSARecv(active_socket->fd, &wsaBuffer, 1, &readCount, &flags, 0, 0);
                }
                else {
                    int len = sizeof(remote_addr);
                    ret = WSARecvFrom(active_socket->fd, &wsaBuffer, 1, &readCount, &flags,
                                      (struct sockaddr*)&remote_addr, &len, 0, 0);
                }
                if (readCount < wsaBuffer.len) {
                    wsaBuffer.len = readCount;
                    /* wsaBuffer.buf = tsk_realloc(wsaBuffer.buf, readCount); */
                }
            }

            if (ret) {
                ret = WSAGetLastError();
                if (ret == WSAEWOULDBLOCK) {
                    // Doesn't (always) mean congestion but... another thread is also poll()ing the FD. For example, when TURN session has a reference to the fd.
                    TSK_DEBUG_WARN("WSAEWOULDBLOCK error for READ SSESSION");
                }
                else if (ret == WSAECONNRESET && TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)) {
                    /* For DGRAM ==> The sent packet gernerated "ICMP Destination/Port unreachable" result. */
                    TSK_FREE(wsaBuffer.buf);
                    goto done; // ignore and retry.
                }
                else {
                    TSK_FREE(wsaBuffer.buf);

                    removeSocket(index, context);
                    TNET_PRINT_LAST_ERROR("WSARecv have failed.");
                    goto done;
                }
            }
            else {
                tnet_transport_event_t* e = tnet_transport_event_create(event_data, transport->callback_data, active_socket->fd);
                transport->bytes_in += wsaBuffer.len;
                e->data = wsaBuffer.buf;
                e->size = wsaBuffer.len;
                e->remote_addr = remote_addr;

                TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e);
            }
FD_READ_DONE:
            ;
        }




        /*================== FD_WRITE ==================*/
        if (networkEvents.lNetworkEvents & FD_WRITE) {
            TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_WRITE", transport->description);

            if (networkEvents.iErrorCode[FD_WRITE_BIT]) {
                TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd);
                TNET_PRINT_LAST_ERROR("WRITE FAILED.");
                goto done;
            }
        }



        /*================== FD_CLOSE ==================*/
        if (networkEvents.lNetworkEvents & FD_CLOSE) {
            TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_CLOSE", transport->description);

            TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, active_socket->fd);
            removeSocket(index, context);
        }

        /*	http://msdn.microsoft.com/en-us/library/ms741690(VS.85).aspx

        	The proper way to reset the state of an event object used with the WSAEventSelect function
        	is to pass the handle of the event object to the WSAEnumNetworkEvents function in the hEventObject parameter.
        	This will reset the event object and adjust the status of active FD events on the socket in an atomic fashion.
        	*/
        /* WSAResetEvent(active_event); <== DO NOT USE (see above) */

done:
        /* unlock context */
        tsk_safeobj_unlock(context);
    } /* while(transport->running) */


bail:

    TSK_DEBUG_INFO("Stopped [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type);
    return tsk_null;
}
コード例 #12
0
ファイル: TMCSnesorServer.cpp プロジェクト: Shalelol/tmc
void worker(boost::shared_ptr<boost::asio::ip::tcp::socket> socket)
{	try
	{
        for(;;) 
        {
            		
			char data_in[100];
			boost::system::error_code error;
			size_t length = (*socket).read_some(boost::asio::buffer(data_in), error);
			std::string connections;
			if (error == boost::asio::error::eof)
			{
				break; // Connection closed by user
			}
			else if (error)
			{
				throw boost::system::system_error(error); // Give some error message (DONALD: need to handle this error back to SCADA)
			}
				
			std::string sdata_in(data_in);
			
			std::string message = "unknown\n";
			
			if (sdata_in == "temperature")
			{
				// TemperatureSensor temperature;
				std::string data = temperature.getData(i2c_fd) + "\n";
				message = data;
			}
			
			if(sdata_in == "ambience")
			{
				// AmbienceSensor ambience;
				std::string data = ambience.getData(a2d) + "\n";
				message = data;
			}
			
			if(sdata_in == "sound")
			{
				// SoundSensor	sound;
				std::string data = sound.getData(a2d) + "\n";
				message = data;
			}
			
			if(sdata_in == "humidity")
			{
				// HumiditySensor humidity;
				std::string data = humidity.getData() + "\n";
				message = data;
				//message = _humidityData;
				//HumiditySensor humidity;
				//_humidityData = humidity.getData() + "\n";
				
			}
			
			if(sdata_in == "dust")
			{
				
				//DustSensor dust;
				std::string data = dust.getData() + "\n";
				message = data;
				
			}
	
            boost::asio::write(*socket, boost::asio::buffer(message));
            
        }
		
		removeSocket(socket);
	} 
	catch(std::exception& e)
	{
		//std::cerr << "Exception: " << e.what() << std::endl;
		removeSocket(socket);
	}
}
コード例 #13
0
void ClientSocketMultiplexer::waitForData() {
	set<AbstractMultiplexedClientSocket *>::iterator i;
	map<int, AbstractMultiplexedClientSocket *>::iterator mi;
	AbstractMultiplexedClientSocket *s;
	struct pollfd *fds=NULL;
	int nfds,r=0;

	multiplexerState = MULTIPLEXER_WAITING;
	while (r>=0) {
		updateSockets();

		free(fds);
		if (!(fds = (struct pollfd *)calloc(sockets.size()+1,sizeof(struct pollfd)))) {
			perror("malloc()");
			break;
		}
		fds[0].fd = controlSockets[0];
		POLL_READ(fds[0]);
		nfds=1;

		for (mi=sockets.begin();mi!=sockets.end();++mi) {
			fds[nfds].fd = (*mi).first;
			s = (*mi).second;
			if (s->hasDataToSend()) POLL_WRITE(fds[nfds]);
			POLL_READ(fds[nfds]);
			nfds++;
		}

		r = poll(fds,nfds,-1);
		if (r>0) {
			set<AbstractMultiplexedClientSocket *> readSet,writeSet;
			char c=0;

			for (int j=1;j<nfds;j++) {
				if (READY_TO_WRITE(fds[j])) writeSet.insert(sockets[fds[j].fd]);
				if (READY_TO_READ(fds[j])) readSet.insert(sockets[fds[j].fd]);
			}

			for (i=readSet.begin();i!=readSet.end();++i) {
				(*i)->receiveData((void *)buffer,BUFSIZ);
				if ((*i)->getSocketStatus() != SOCKET_OPENED) {
					writeSet.erase((*i));
					removeSocket((*i));
				}
			}
			for (i=writeSet.begin();i!=writeSet.end();++i) {
				(*i)->transmitBuffer();
				if ((*i)->getSocketStatus() != SOCKET_OPENED) removeSocket((*i));
			}

			readSet.clear();
			writeSet.clear();

			if (READY_TO_READ(fds[0])) {
				while ((recv(controlSockets[0],&c,1,0) == 1) && !c);
				if (c) break;
			}
		} else {
			perror("poll()");
			r = 0;
		}
	}
	free(fds);
	multiplexerState = MULTIPLEXER_IDLE;
}