bool KartUpdateProtocol::notifyEventAsynchronous(Event* event)
{
    if (event->type != EVENT_TYPE_MESSAGE)
        return true;
    NetworkString ns = event->data();
    if (ns.size() < 36)
    {
        Log::info("KartUpdateProtocol", "Message too short.");
        return true;
    }
    ns.removeFront(4);
    while(ns.size() >= 16)
    {
        uint32_t kart_id = ns.getUInt32(0);

        float a,b,c;
        a = ns.getFloat(4);
        b = ns.getFloat(8);
        c = ns.getFloat(12);
        float d,e,f,g;
        d = ns.getFloat(16);
        e = ns.getFloat(20);
        f = ns.getFloat(24);
        g = ns.getFloat(28);
        pthread_mutex_trylock(&m_positions_updates_mutex);
        m_next_positions.push_back(Vec3(a,b,c));
        m_next_quaternions.push_back(btQuaternion(d,e,f,g));
        m_karts_ids.push_back(kart_id);
        pthread_mutex_unlock(&m_positions_updates_mutex);
        ns.removeFront(32);
    }
    return true;
}
/** Sends a packet to this host.
 *  \param data The data to send.
 *  \param reliable If the data is sent reliable or not.
 */
void STKPeer::sendPacket(NetworkString const& data, bool reliable)
{
    TransportAddress a(m_enet_peer->address);
    Log::verbose("STKPeer", "sending packet of size %d to %s",
                 data.size(), a.toString().c_str());
         
    ENetPacket* packet = enet_packet_create(data.getBytes(), data.size() + 1,
                                    (reliable ? ENET_PACKET_FLAG_RELIABLE
                                              : ENET_PACKET_FLAG_UNSEQUENCED));
    enet_peer_send(m_enet_peer, 0, packet);
}   // sendPacket
/** \brief Broadcasts a packet to all peers.
 *  \param data : Data to send.
 */
void Network::broadcastPacket(const NetworkString& data, bool reliable)
{
    ENetPacket* packet = enet_packet_create(data.getBytes(), data.size() + 1,
                                      reliable ? ENET_PACKET_FLAG_RELIABLE
                                               : ENET_PACKET_FLAG_UNSEQUENCED);
    enet_host_broadcast(m_host, 0, packet);
}   // broadcastPacket
/** Saves a state on the client. Used to save an initial state at t=0 for each
 *  client in case that we receive an event from another client (which will
 *  trigger a rewind) before a state from the server.
 */
void RewindManager::saveLocalState()
{
    int ticks = World::getWorld()->getTimeTicks();

    saveState(/*local_state*/true);
    NetworkString *state = GameProtocol::lock()->getState();

    // Copy the data to a new string, making the buffer in
    // GameProtocol availble for again.
    BareNetworkString *bns =
        new BareNetworkString(state->getCurrentData(),
                              state->size()           );
    m_rewind_queue.addLocalState(bns, /*confirmed*/true, ticks);
}   // saveLocalState
/** \brief Log packets into a file
 *  \param ns : The data in the packet
 *  \param incoming : True if the packet comes from a peer.
 *  False if it's sent to a peer.
 */
void Network::logPacket(const NetworkString &ns, bool incoming)
{
    if (m_log_file.getData() == NULL) // read only access, no need to lock
        return;

    const char *arrow = incoming ? "<--" : "-->";

    m_log_file.lock();
    fprintf(m_log_file.getData(), "[%d\t]  %s  ",
            (int)(StkTime::getRealTime()), arrow);

    for (int i = 0; i < ns.size(); i++)
    {
        fprintf(m_log_file.getData(), "%d.", ns[i]);
    }
    fprintf(m_log_file.getData(), "\n");
    m_log_file.unlock();
}   // logPacket
Пример #6
0
/** This function is called on a client when it receives a kartFinishedRace
 *  event from the server. It updates the game with this information.
 *  \param ns The message from the server.
 */
void GameEventsProtocol::kartFinishedRace(const NetworkString &ns)
{
    if (ns.size() < 5)
    {
        Log::warn("GameEventsProtocol", "kartFinisheRace: Too short message.");
        return;
    }

    uint8_t kart_id = ns.getUInt8();
    float time      = ns.getFloat();
    if (race_manager->modeHasLaps())
    {
        World::getWorld()->getKart(kart_id)
            ->setPosition(m_last_finished_position++);
    }
    World::getWorld()->getKart(kart_id)->finishedRace(time,
                                                      /*from_server*/true);
}   // kartFinishedRace
Пример #7
0
void STKPeer::sendPacket(NetworkString const& data, bool reliable)
{
    TransportAddress a(m_peer->address);
    Log::verbose("STKPeer", "sending packet of size %d to %s",
                 a.toString().c_str());

    ENetPacket* packet = enet_packet_create(data.getBytes(), data.size() + 1,
                                            (reliable ? ENET_PACKET_FLAG_RELIABLE : ENET_PACKET_FLAG_UNSEQUENCED));
    /* to debug the packet output
    printf("STKPeer: ");
    for (unsigned int i = 0; i < data.size(); i++)
    {
        printf("%d ", (uint8_t)(data[i]));
    }
    printf("\n");
    */
    enet_peer_send(m_peer, 0, packet);
}
Пример #8
0
bool StartGameProtocol::notifyEventAsynchronous(Event* event)
{
    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->peer));
    if (peer->getClientServerToken() != token)
    {
        Log::error("StartGameProtocol", "Bad token received.");
        return true;
    }
    if (m_listener->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
            SynchronizationProtocol* protocol = static_cast<SynchronizationProtocol*>(m_listener->getProtocol(PROTOCOL_SYNCHRONIZATION));
            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.");
        }
    }
    else // on the client, we shouldn't even receive messages.
    {
        Log::error("StartGameProtocol", "Received a message with bad format.");
    }
    return true;
}
Пример #9
0
// ----------------------------------------------------------------------------
void STKHost::handleLANRequests()
{
    const int LEN=2048;
    char buffer[LEN];

    TransportAddress sender;
    int len = m_lan_network->receiveRawPacket(buffer, LEN, &sender, 1);
    if(len<=0) return;

    if (std::string(buffer, len) == "stk-server")
    {
        Log::verbose("STKHost", "Received LAN server query");
        std::string name = 
            StringUtils::wideToUtf8(NetworkConfig::get()->getServerName());
        // Avoid buffer overflows
        if (name.size() > 255)
            name = name.substr(0, 255);

        // Send the answer, consisting of server name, max players, 
        // current players, and the client's ip address and port
        // number (which solves the problem which network interface
        // might be the right one if there is more than one).
        NetworkString s;
        s.encodeString(name);
        s.addUInt8(NetworkConfig::get()->getMaxPlayers());
        s.addUInt8(0);   // FIXME: current number of connected players
        s.addUInt32(sender.getIP());
        s.addUInt16(sender.getPort());
        m_lan_network->sendRawPacket(s.getBytes(), s.size(), sender);
    }   // if message is server-requested
    else if (std::string(buffer, len) == "connection-request")
    {
        Protocol *c = new ConnectToPeer(sender);
        c->requestStart();
    }
    else
        Log::info("STKHost", "Received unknown command '%s'",
                  std::string(buffer, len).c_str());

}   // handleLANRequests
bool ServerLobbyRoomProtocol::notifyEventAsynchronous(Event* event)
{
    assert(m_setup); // assert that the setup exists
    if (event->type == EVENT_TYPE_MESSAGE)
    {
        NetworkString data = event->data();
        assert(data.size()); // message not empty
        uint8_t message_type;
        message_type = data[0];
        event->removeFront(1);
        Log::info("ServerLobbyRoomProtocol", "Message received with type %d.", message_type);
        if (message_type == 0x01) // player requesting connection
            connectionRequested(event);
        else if (message_type == 0x02) // player requesting kart selection
            kartSelectionRequested(event);
        else if (message_type == 0xc0) // vote for major mode
            playerMajorVote(event);
        else if (message_type == 0xc1) // vote for race count
            playerRaceCountVote(event);
        else if (message_type == 0xc2) // vote for minor mode
            playerMinorVote(event);
        else if (message_type == 0xc3) // vote for track
            playerTrackVote(event);
        else if (message_type == 0xc4) // vote for reversed mode
            playerReversedVote(event);
        else if (message_type == 0xc5) // vote for laps
            playerLapsVote(event);
    } // if (event->type == EVENT_TYPE_MESSAGE)
    else if (event->type == EVENT_TYPE_CONNECTED)
    {
    } // if (event->type == EVENT_TYPE_CONNECTED)
    else if (event->type == EVENT_TYPE_DISCONNECTED)
    {
        kartDisconnected(event);
    } // if (event->type == EVENT_TYPE_DISCONNECTED)
    return true;
}
Пример #11
0
bool SynchronizationProtocol::notifyEventAsynchronous(Event* event)
{
    if (event->type != EVENT_TYPE_MESSAGE)
        return true;
    NetworkString data = event->data();
    if (data.size() < 10)
    {
        Log::warn("SynchronizationProtocol", "Received a message too short.");
        return true;
    }
    uint8_t talk_id = data.gui8();
    uint32_t token = data.gui32(1);
    uint32_t request = data.gui8(5);
    uint32_t sequence = data.gui32(6);

    std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
    assert(peers.size() > 0);

    if (m_listener->isServer())
    {
        if (talk_id > peers.size())
        {
            Log::warn("SynchronizationProtocol", "The ID isn't known.");
            return true;
        }
    }

    uint8_t peer_id = 0;
    for (unsigned int i = 0; i < peers.size(); i++)
    {
        if (peers[i]->isSamePeer(*event->peer))
        {
            peer_id = i;
        }
    }
    if (peers[peer_id]->getClientServerToken() != token)
    {
        Log::warn("SynchronizationProtocol", "Bad token from peer %d", talk_id);
        return true;
    }

    if (request)
    {
        NetworkString response;
        response.ai8(data.gui8(talk_id)).ai32(token).ai8(0).ai32(sequence);
        m_listener->sendMessage(this, peers[peer_id], response, false);
        Log::verbose("SynchronizationProtocol", "Answering sequence %u", sequence);
        if (data.size() == 14 && !m_listener->isServer()) // countdown time in the message
        {
            uint32_t time_to_start = data.gui32(10);
            Log::debug("SynchronizationProtocol", "Request to start game in %d.", time_to_start);
            if (!m_countdown_activated)
                startCountdown(time_to_start);
            else
                m_countdown = (double)(time_to_start/1000.0);
        }
        else
            Log::verbose("SynchronizationProtocol", "No countdown for now.");
    }
    else // response
    {
        if (sequence >= m_pings[peer_id].size())
        {
            Log::warn("SynchronizationProtocol", "The sequence# %u isn't known.", sequence);
            return true;
        }
        double current_time = StkTime::getRealTime();
        m_total_diff[peer_id] += current_time - m_pings[peer_id][sequence];
        Log::verbose("SynchronizationProtocol", "InstantPing is %u",
            (unsigned int)((current_time - m_pings[peer_id][sequence])*1000));
        m_successed_pings[peer_id]++;
        m_average_ping[peer_id] = (int)((m_total_diff[peer_id]/m_successed_pings[peer_id])*1000.0);

        Log::debug("SynchronizationProtocol", "Ping is %u", m_average_ping[peer_id]);
    }
    return true;
}
/*! \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");
    }
}