/*! \brief Called when the server accepts the connection.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0                   1        2            3       
 *       ---------------------------------------------------------
 *  Size |    1     |   1    | 1          |             |
 *  Data | player_id| hostid | authorised |playernames* |
 *       ---------------------------------------------------------
 */
void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
{
    // At least 3 bytes should remain now
    if(!checkDataSize(event, 3)) return;

    NetworkString &data = event->data();
    STKPeer* peer = event->getPeer();

    // Accepted
    // ========
    Log::info("ClientLobbyRoomProtocol",
              "The server accepted the connection.");

    // self profile
    irr::core::stringw name;
    if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN)
        name = PlayerManager::getCurrentOnlineUserName();
    else
        name = PlayerManager::getCurrentPlayer()->getName();
    uint8_t my_player_id = data.getUInt8();
    uint8_t my_host_id   = data.getUInt8();
    uint8_t authorised   = data.getUInt8();
    // Store this client's authorisation status in the peer information
    // for the server.
    event->getPeer()->setAuthorised(authorised!=0);
    STKHost::get()->setMyHostId(my_host_id);

    NetworkPlayerProfile* profile = 
        new NetworkPlayerProfile(name, my_player_id, my_host_id);
    STKHost::get()->getGameSetup()->setLocalMaster(my_player_id);
    m_setup->setNumLocalPlayers(1);
    // connection token
    uint32_t token = data.getToken();
    peer->setClientServerToken(token);

    // Add all players
    // ===============
    while (data.size() > 0)
    {
        uint8_t player_id = data.getUInt8();
        uint8_t host_id   = data.getUInt8();
        irr::core::stringw name;
        int bytes_read = data.decodeStringW(&name);
        
        NetworkPlayerProfile* profile2 =
            new NetworkPlayerProfile(name, player_id, host_id);
        m_setup->addPlayer(profile2);
        // Inform the network lobby of all players so that the GUI can
        // show all currently connected players.
        NetworkingLobby::getInstance()->addPlayer(profile2);
    }

    // Add self after other players so that player order is identical
    // on server and all clients.
    m_setup->addPlayer(profile);
    NetworkingLobby::getInstance()->addPlayer(profile);
    m_server = event->getPeer();
    m_state = CONNECTED;
}   // connectionAccepted
/*! \brief Called when a player asks to select a kart.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0          1                      2            
 *       ----------------------------------------------
 *  Size |    1     |           1         |     N     |
 *  Data |player id |  N (kart name size) | kart name |
 *       ----------------------------------------------
 */
void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
{
    if(m_state!=SELECTING)
    {
        Log::warn("Server", "Received kart selection while in state %d.",
                  m_state);
        return;
    }

    if (!checkDataSize(event, 1)) return;

    const NetworkString &data = event->data();
    STKPeer* peer = event->getPeer();

    uint8_t player_id = data.getUInt8();
    std::string kart_name;
    data.decodeString(&kart_name);
    // check if selection is possible
    if (!m_selection_enabled)
    {
        NetworkString *answer = getNetworkString(2);
        // selection still not started
        answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(2);
        peer->sendPacket(answer);
        delete answer;
        return;
    }
    // check if somebody picked that kart
    if (!m_setup->isKartAvailable(kart_name))
    {
        NetworkString *answer = getNetworkString(2);
        // kart is already taken
        answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(0);
        peer->sendPacket(answer);
        delete answer;
        return;
    }
    // check if this kart is authorized
    if (!m_setup->isKartAllowed(kart_name))
    {
        NetworkString *answer = getNetworkString(2);
        // kart is not authorized
        answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(1);
        peer->sendPacket(answer);
        delete answer;
        return;
    }

    // send a kart update to everyone
    NetworkString *answer = getNetworkString(3+kart_name.size());
    // This message must be handled synchronously on the client.
    answer->setSynchronous(true);
    // kart update (3), 1, race id
    answer->addUInt8(LE_KART_SELECTION_UPDATE).addUInt8(player_id)
          .encodeString(kart_name);
    sendMessageToPeersChangingToken(answer);
    delete answer;
    m_setup->setPlayerKart(player_id, kart_name);
}   // kartSelectionRequested
예제 #3
0
/*! \brief Called when the server accepts the connection.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0   1                   2   3            7   8           12
 *       ----------------------------------------------------------
 *  Size | 1 |         1         | 1 |      4     | 1 |     4     |
 *  Data | 1 | 0 <= race id < 16 | 4 | priv token | 4 | global id |
 *       ----------------------------------------------------------
 */
void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
{
    NetworkString &data = event->data();
    if (data.size() < 12 || data[0] != 1 || data[2] != 4 || data[7] != 4) // 12 bytes remains now
    {
        Log::error("ClientLobbyRoomProtocol", "A message notifying an accepted connection wasn't formated as expected.");
        return;
    }
    STKPeer* peer = event->getPeer();

    uint32_t global_id = data.gui32(8);
    if (global_id == PlayerManager::getCurrentOnlineId())
    {
        Log::info("ClientLobbyRoomProtocol", "The server accepted the connection.");

        // self profile
        NetworkPlayerProfile* profile = new NetworkPlayerProfile();
        profile->kart_name = "";
        profile->race_id = data.gui8(1);
        profile->user_profile = PlayerManager::getCurrentOnlineProfile();
        m_setup->addPlayer(profile);
        // connection token
        uint32_t token = data.gui32(3);
        peer->setClientServerToken(token);
        // add all players
        data.removeFront(12); // remove the 12 first bytes
        int remaining = data.size();
        if (remaining%7 != 0)
        {
            Log::error("ClientLobbyRoomProtocol", "ConnectionAccepted : Error in the server list");
        }
        remaining /= 7;
        for (int i = 0; i < remaining; i++)
        {
            if (data[0] != 1 || data[2] != 4)
                Log::error("ClientLobbyRoomProtocol", "Bad format in players list.");

            uint8_t race_id = data[1];
            uint32_t global_id = data.gui32(3);
            Online::OnlineProfile* new_user = new Online::OnlineProfile(global_id, "");

            NetworkPlayerProfile* profile2 = new NetworkPlayerProfile();
            profile2->race_id = race_id;
            profile2->user_profile = new_user;
            profile2->kart_name = "";
            m_setup->addPlayer(profile2);
            data.removeFront(7);
        }

        // add self
        m_server = event->getPeer();
        m_state = CONNECTED;
    }
    else
        Log::info("ClientLobbyRoomProtocol", "Failure during the connection acceptation process.");
}   // connectionAccepted
예제 #4
0
/** Sends data to all peers except the specified one.
 *  \param peer Peer which will not receive the message.
 *  \param data Data to sent.
 *  \param reliable If the data should be sent reliable or now.
 */
void STKHost::sendPacketExcept(STKPeer* peer, const NetworkString& data,
                               bool reliable)
{
    for (unsigned int i = 0; i < m_peers.size(); i++)
    {
        STKPeer* p = m_peers[i];
        if (!p->isSamePeer(peer))
        {
            p->sendPacket(data, reliable);
        }
    }
}   // sendPacketExcept
/*! \brief Called when a player asks to select a kart.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0   1            5                    6           N+6
 *       ---------------------------------------------------
 *  Size | 1 |      4     |          1         |     N     |
 *  Data | 4 | priv token | N (kart name size) | kart name |
 *       ---------------------------------------------------
 */
void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
{
    if(m_state!=SELECTING_KARTS)
    {
        Log::warn("Server", "Received kart selection while in state %d.",
                  m_state);
        return;
    }

    const NetworkString &data = event->data();
    STKPeer* peer = event->getPeer();
    if (!checkDataSizeAndToken(event, 6))
        return;

    std::string kart_name;
    data.decodeString(5, &kart_name);
    // check if selection is possible
    if (!m_selection_enabled)
    {
        NetworkString answer(3);
        // selection still not started
        answer.ai8(LE_KART_SELECTION_REFUSED).ai8(1).ai8(2);
        sendMessage(peer, answer);
        return;
    }
    // check if somebody picked that kart
    if (!m_setup->isKartAvailable(kart_name))
    {
        NetworkString answer(3);
        // kart is already taken
        answer.ai8(LE_KART_SELECTION_REFUSED).ai8(1).ai8(0);
        sendMessage(peer, answer);
        return;
    }
    // check if this kart is authorized
    if (!m_setup->isKartAllowed(kart_name))
    {
        NetworkString answer(3);
        // kart is not authorized
        answer.ai8(LE_KART_SELECTION_REFUSED).ai8(1).ai8(1);
        sendMessage(peer, answer);
        return;
    }
    // send a kart update to everyone
    NetworkString answer(3+1+kart_name.size());
    // kart update (3), 1, race id
    uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
    answer.ai8(LE_KART_SELECTION_UPDATE).ai8(1).ai8(player_id)
          .encodeString(kart_name);
    // This message must be handled synchronously on the client.
    sendSynchronousMessage(answer);
    m_setup->setPlayerKart(player_id, kart_name);
}   // kartSelectionRequested
/*! \brief Called when a player asks to select a kart.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0   1            5                    6           N+6
 *       ---------------------------------------------------
 *  Size | 1 |      4     |          1         |     N     |
 *  Data | 4 | priv token | N (kart name size) | kart name |
 *       ---------------------------------------------------
 */
void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
{
    NetworkString data = event->data();
    STKPeer* peer = *(event->peer);
    if (!checkDataSizeAndToken(event, 6))
        return;

    uint8_t kart_name_size = data.gui8(5);
    std::string kart_name = data.gs(6, kart_name_size);
    if (kart_name.size() != kart_name_size)
    {
        Log::error("ServerLobbyRoomProtocol", "Kart names sizes differ: told:"
                   "%d, real: %d.", kart_name_size, kart_name.size());
        return;
    }
    // check if selection is possible
    if (!m_selection_enabled)
    {
        NetworkString answer;
        answer.ai8(0x82).ai8(1).ai8(2); // selection still not started
        m_listener->sendMessage(this, peer, answer);
        return;
    }
    // check if somebody picked that kart
    if (!m_setup->isKartAvailable(kart_name))
    {
        NetworkString answer;
        answer.ai8(0x82).ai8(1).ai8(0); // kart is already taken
        m_listener->sendMessage(this, peer, answer);
        return;
    }
    // check if this kart is authorized
    if (!m_setup->isKartAllowed(kart_name))
    {
        NetworkString answer;
        answer.ai8(0x82).ai8(1).ai8(1); // kart is not authorized
        m_listener->sendMessage(this, peer, answer);
        return;
    }
    // send a kart update to everyone
    NetworkString answer;
    // kart update (3), 1, race id
    answer.ai8(0x03).ai8(1).ai8(peer->getPlayerProfile()->race_id);
    //  kart name size, kart name
    answer.ai8(kart_name.size()).as(kart_name);
    m_listener->sendMessage(this, answer);
    m_setup->setPlayerKart(peer->getPlayerProfile()->race_id, kart_name);
}
void ServerLobbyRoomProtocol::kartDisconnected(Event* event)
{
    STKPeer* peer = *(event->peer);
    if (peer->getPlayerProfile() != NULL) // others knew him
    {
        NetworkString msg;
        msg.ai8(0x02).ai8(1).ai8(peer->getPlayerProfile()->race_id);
        m_listener->sendMessage(this, msg);
        Log::info("ServerLobbyRoomProtocol", "Player disconnected : id %d",
                  peer->getPlayerProfile()->race_id);
        m_setup->removePlayer(peer->getPlayerProfile()->race_id);
        NetworkManager::getInstance()->removePeer(peer);
    }
    else
        Log::info("ServerLobbyRoomProtocol", "The DC peer wasn't registered.");
}
예제 #8
0
// ----------------------------------------------------------------------------
bool StartGameProtocol::notifyEventAsynchronous(Event* event)
{
    const NetworkString &data = event->data();
    if (data.size() < 5)
    {
        Log::error("StartGameProtocol", "Too short message.");
        return true;
    }
    uint32_t token = data.gui32();
    uint8_t ready = data.gui8(4);
    STKPeer* peer = event->getPeer();
    if (peer->getClientServerToken() != token)
    {
        Log::error("StartGameProtocol", "Bad token received.");
        return true;
    }
    if (NetworkConfig::get()->isServer() && ready) // on server, player is ready
    {
        Log::info("StartGameProtocol", "One of the players is ready.");
        m_player_states[peer->getPlayerProfile()] = READY;
        m_ready_count++;
        if (m_ready_count == m_game_setup->getPlayerCount())
        {
            // everybody ready, synchronize
            Protocol *p = ProtocolManager::getInstance()
                        ->getProtocol(PROTOCOL_SYNCHRONIZATION);
            SynchronizationProtocol* protocol = 
                                static_cast<SynchronizationProtocol*>(p);
            if (protocol)
            {
                protocol->startCountdown(5000); // 5 seconds countdown
                Log::info("StartGameProtocol",
                          "All players ready, starting countdown.");
                m_ready = true;
                return true;
            }
            else
                Log::error("StartGameProtocol",
                          "The Synchronization protocol hasn't been started.");
        }   // if m_ready_count == number of players
    }
    else // on the client, we shouldn't even receive messages.
    {
        Log::error("StartGameProtocol", "Received a message with bad format.");
    }
    return true;
}   // notifyEventAsynchronous
/*! \brief Called when a player votes for the number of races in a GP.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0   1            5   6             7
 *       ------------------------------------
 *  Size | 1 |      4     | 1 |      1      |
 *  Data | 4 | priv token | 1 | races count |
 *       ------------------------------------
 */
void ServerLobbyRoomProtocol::playerRaceCountVote(Event* event)
{
    NetworkString &data = event->data();
    STKPeer* peer = event->getPeer();
    if (!checkDataSizeAndToken(event, 7))
        return;
    if (!isByteCorrect(event, 5, 1))
        return;
    uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
    m_setup->getRaceConfig()->setPlayerRaceCountVote(player_id, data[6]);
    // Send the vote to everybody (including the sender)
    data.removeFront(5); // remove the token
    NetworkString other(2+data.size());
    other.ai8(1).ai8(player_id); // add the player id
    other += data; // add the data
    sendMessageToPeersChangingToken(LE_VOTE_RACE_COUNT, other);
}   // playerRaceCountVote
/*! \brief Called when a player votes for a minor race mode.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0   1            5   6                 7
 *       ----------------------------------------
 *  Size | 1 |      4     | 1 |        1        |
 *  Data | 4 | priv token | 1 | minor mode vote |
 *       ----------------------------------------
 */
void ServerLobbyRoomProtocol::playerMinorVote(Event* event)
{
    NetworkString data = event->data();
    STKPeer* peer = *(event->peer);
    if (!checkDataSizeAndToken(event, 7))
        return;
    if (!isByteCorrect(event, 5, 1))
        return;
    uint8_t player_id = peer->getPlayerProfile()->race_id;
    m_setup->getRaceConfig()->setPlayerMinorVote(player_id, data[6]);
    // Send the vote to everybody (including the sender)
    NetworkString other;
    other.ai8(1).ai8(player_id); // add the player id
    data.removeFront(5); // remove the token
    other += data; // add the data
    NetworkString prefix;
    prefix.ai8(0xc2); // prefix the token with the ype
    sendMessageToPeersChangingToken(prefix, other);
}
/*! \brief Called when a player votes for a track.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0   1            5   6            N+6 N+7                 N+8
 *       -----------------------------------------------------------
 *  Size | 1 |      4     | 1 |      N     | 1 |       1           |
 *  Data | 4 | priv token | N | track name | 1 | track number (gp) |
 *       -----------------------------------------------------------
 */
void ServerLobbyRoomProtocol::playerTrackVote(Event* event)
{
    NetworkString &data = event->data();
    STKPeer* peer = event->getPeer();
    if (!checkDataSizeAndToken(event, 8))
        return;
    std::string track_name;
    int N = data.decodeString(5, &track_name);
    if (!isByteCorrect(event, N+5, 1))
        return;
    uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
    m_setup->getRaceConfig()->setPlayerTrackVote(player_id, track_name, data[N+6]);
    // Send the vote to everybody (including the sender)
    data.removeFront(5); // remove the token
    NetworkString other(2+data.size());
    other.ai8(1).ai8(player_id); // add the player id
    other += data; // add the data
    sendMessageToPeersChangingToken(LE_VOTE_TRACK, other);
    if(m_setup->getRaceConfig()->getNumTrackVotes()==m_setup->getPlayerCount())
        startGame();
}   // playerTrackVote
void ServerLobbyRoomProtocol::kartDisconnected(Event* event)
{
    STKPeer* peer = event->getPeer();
    if (peer->getPlayerProfile() != NULL) // others knew him
    {
        NetworkString msg(3);
        msg.ai8(LE_PLAYER_DISCONNECTED).ai8(1)
           .ai8(peer->getPlayerProfile()->getGlobalPlayerId());
        sendMessage(msg);
        Log::info("ServerLobbyRoomProtocol", "Player disconnected : id %d",
                  peer->getPlayerProfile()->getGlobalPlayerId());
        m_setup->removePlayer(peer->getPlayerProfile());
        // Remove the profile from the peer (to avoid double free)
        peer->setPlayerProfile(NULL);
        STKHost::get()->removePeer(peer);
    }
    else
        Log::info("ServerLobbyRoomProtocol", "The DC peer wasn't registered.");
}   // kartDisconnected
/*! \brief Called when a player asks for a connection.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0   1                
 *       ---------------------
 *  Size | 1 |1|             |
 *  Data | 4 |n| player name |
 *       ---------------------
 */
void ServerLobbyRoomProtocol::connectionRequested(Event* event)
{
    STKPeer* peer = event->getPeer();
    const NetworkString &data = event->data();

    // can we add the player ?
    if (m_setup->getPlayerCount() >= NetworkConfig::get()->getMaxPlayers() ||
        m_state!=ACCEPTING_CLIENTS                                           )
    {
        NetworkString *message = getNetworkString(2);
        // Len, error code: 2 = busy, 0 = too many players
        message->addUInt8(LE_CONNECTION_REFUSED)
                .addUInt8(m_state!=ACCEPTING_CLIENTS ? 2 : 0);

        // send only to the peer that made the request
        peer->sendPacket(message);
        delete message;
        Log::verbose("ServerLobbyRoomProtocol", "Player refused");
        return;
    }

    // Connection accepted.
    // ====================
    std::string name_u8;
    int len = data.decodeString(&name_u8);
    core::stringw name = StringUtils::utf8ToWide(name_u8);
    std::string password;
    data.decodeString(&password);
    bool is_authorised = (password==NetworkConfig::get()->getPassword());

    // Get the unique global ID for this player.
    m_next_player_id.lock();
    m_next_player_id.getData()++;
    int new_player_id = m_next_player_id.getData();
    m_next_player_id.unlock();
    if(m_setup->getLocalMasterID()==0)
        m_setup->setLocalMaster(new_player_id);

    // The host id has already been incremented when the peer
    // was added, so it is the right id now.
    int new_host_id = STKHost::get()->getNextHostId();

    // Notify everybody that there is a new player
    // -------------------------------------------
    NetworkString *message = getNetworkString(3+1+name_u8.size());
    // size of id -- id -- size of local id -- local id;
    message->addUInt8(LE_NEW_PLAYER_CONNECTED).addUInt8(new_player_id)
            .addUInt8(new_host_id).encodeString(name_u8);
    STKHost::get()->sendPacketExcept(peer, message);
    delete message;

    // Now answer to the peer that just connected
    // ------------------------------------------
    RandomGenerator token_generator;
    // use 4 random numbers because rand_max is probably 2^15-1.
    uint32_t token = (uint32_t)((token_generator.get(RAND_MAX) & 0xff) << 24 |
                                (token_generator.get(RAND_MAX) & 0xff) << 16 |
                                (token_generator.get(RAND_MAX) & 0xff) <<  8 |
                                (token_generator.get(RAND_MAX) & 0xff));

    peer->setClientServerToken(token);
    peer->setAuthorised(is_authorised);
    peer->setHostId(new_host_id);

    const std::vector<NetworkPlayerProfile*> &players = m_setup->getPlayers();
    // send a message to the one that asked to connect
    // Estimate 10 as average name length
    NetworkString *message_ack = getNetworkString(4 + players.size() * (2+10));
    // connection success -- size of token -- token
    message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt8(new_player_id)
                .addUInt8(new_host_id).addUInt8(is_authorised);
    // Add all players so that this user knows (this new player is only added
    // to the list of players later, so the new player's info is not included)
    for (unsigned int i = 0; i < players.size(); i++)
    {
        message_ack->addUInt8(players[i]->getGlobalPlayerId())
                    .addUInt8(players[i]->getHostId())
                    .encodeString(players[i]->getName());
    }
    peer->sendPacket(message_ack);
    delete message_ack;

    NetworkPlayerProfile* profile = 
        new NetworkPlayerProfile(name, new_player_id, new_host_id);
    m_setup->addPlayer(profile);
    NetworkingLobby::getInstance()->addPlayer(profile);

    Log::verbose("ServerLobbyRoomProtocol", "New player.");

}   // connectionRequested
예제 #14
0
/** \brief Thread function checking if data is received.
 *  This function tries to get data from network low-level functions as
 *  often as possible. When something is received, it generates an
 *  event and passes it to the Network Manager.
 *  \param self : used to pass the ENet host to the function.
 */
void* STKHost::mainLoop(void* self)
{
    VS::setThreadName("STKHost");
    ENetEvent event;
    STKHost* myself = (STKHost*)(self);
    ENetHost* host = myself->m_network->getENetHost();

    if(NetworkConfig::get()->isServer() && 
        NetworkConfig::get()->isLAN()      )
    {
        TransportAddress address(0, 2757);
        ENetAddress eaddr = address.toEnetAddress();
        myself->m_lan_network = new Network(1, 1, 0, 0, &eaddr);
    }

    while (!myself->mustStopListening())
    {
        if(myself->m_lan_network)
        {
            myself->handleLANRequests();
        }   // if discovery host

        while (enet_host_service(host, &event, 20) != 0)
        {
            if (event.type == ENET_EVENT_TYPE_NONE)
                continue;

            // Create an STKEvent with the event data. This will also
            // create the peer if it doesn't exist already
            Event* stk_event = new Event(&event);
            if (stk_event->getType() == EVENT_TYPE_MESSAGE)
                Network::logPacket(stk_event->data(), true);

            Log::verbose("STKHost", "Event of type %d received",
                         (int)(stk_event->getType()));
            STKPeer* peer = stk_event->getPeer();
            if (stk_event->getType() == EVENT_TYPE_CONNECTED)
            {
                Log::info("STKHost", "A client has just connected. There are "
                          "now %lu peers.", myself->m_peers.size());
                Log::debug("STKHost", "Addresses are : %lx, %lx",
                           stk_event->getPeer(), peer);
            }   // EVENT_TYPE_CONNECTED
            else if (stk_event->getType() == EVENT_TYPE_MESSAGE)
            {
                TransportAddress stk_addr(peer->getAddress());
                Log::verbose("NetworkManager",
                             "Message, Sender : %s, message = \"%s\"",
                             stk_addr.toString(/*show port*/false).c_str(),
                             stk_event->data().std_string().c_str());

            }   // if message event

            // notify for the event now.
            ProtocolManager::getInstance()->propagateEvent(stk_event);
            
        }   // while enet_host_service
    }   // while !mustStopListening

    free(myself->m_listening_thread);
    myself->m_listening_thread = NULL;
    Log::info("STKHost", "Listening has been stopped");
    return NULL;
}   // mainLoop
/*! \brief Called when a player asks for a connection.
 *  \param event : Event providing the information.
 *
 *  Format of the data :
 *  Byte 0   1                  5
 *       ------------------------
 *  Size | 1 |          4       |
 *  Data | 4 | global player id |
 *       ------------------------
 */
void ServerLobbyRoomProtocol::connectionRequested(Event* event)
{
    STKPeer* peer = *(event->peer);
    NetworkString data = event->data();
    if (data.size() != 5 || data[0] != 4)
    {
        Log::warn("ServerLobbyRoomProtocol", "Receiving badly formated message. Size is %d and first byte %d", data.size(), data[0]);
        return;
    }
    uint32_t player_id = 0;
    player_id = data.getUInt32(1);
    // can we add the player ?
    if (m_setup->getPlayerCount() <
        ServerNetworkManager::getInstance()->getMaxPlayers()) //accept
    {
        // add the player to the game setup
        m_next_id = m_setup->getPlayerCount();
        // notify everybody that there is a new player
        NetworkString message;
        // new player (1) -- size of id -- id -- size of local id -- local id;
        message.ai8(1).ai8(4).ai32(player_id).ai8(1).ai8(m_next_id);
        m_listener->sendMessageExcept(this, peer, message);

        /// now answer to the peer that just connected
        RandomGenerator token_generator;
        // use 4 random numbers because rand_max is probably 2^15-1.
        uint32_t token = (uint32_t)(((token_generator.get(RAND_MAX)<<24) & 0xff) +
                                    ((token_generator.get(RAND_MAX)<<16) & 0xff) +
                                    ((token_generator.get(RAND_MAX)<<8)  & 0xff) +
                                    ((token_generator.get(RAND_MAX)      & 0xff)));

        // send a message to the one that asked to connect
        NetworkString message_ack;
        // connection success (129) -- size of token -- token
        message_ack.ai8(0x81).ai8(1).ai8(m_next_id).ai8(4).ai32(token).ai8(4).ai32(player_id);
        // add all players so that this user knows
        std::vector<NetworkPlayerProfile*> players = m_setup->getPlayers();
        for (unsigned int i = 0; i < players.size(); i++)
        {
            // do not duplicate the player into the message
            if (players[i]->race_id != m_next_id && players[i]->user_profile->getID() != player_id)
                message_ack.ai8(1).ai8(players[i]->race_id).ai8(4).ai32(players[i]->user_profile->getID());
        }
        m_listener->sendMessage(this, peer, message_ack);

        peer->setClientServerToken(token);

        NetworkPlayerProfile* profile = new NetworkPlayerProfile();
        profile->race_id = m_next_id;
        profile->kart_name = "";
        profile->user_profile = new Online::OnlineProfile(player_id, "");
        m_setup->addPlayer(profile);
        peer->setPlayerProfile(profile);
        Log::verbose("ServerLobbyRoomProtocol", "New player.");
    } // accept player
    else  // refuse the connection with code 0 (too much players)
    {
        NetworkString message;
        message.ai8(0x80);            // 128 means connection refused
        message.ai8(1);               // 1 bytes for the error code
        message.ai8(0);               // 0 = too much players
        // send only to the peer that made the request
        m_listener->sendMessage(this, peer, message);
        Log::verbose("ServerLobbyRoomProtocol", "Player refused");
    }
}