diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 08829b505..fcd98b733 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -59,6 +59,8 @@ #include "karts/max_speed.hpp" #include "karts/skidding.hpp" #include "modes/linear_world.hpp" +#include "network/network_world.hpp" +#include "network/network_manager.hpp" #include "physics/btKart.hpp" #include "physics/btKartRaycast.hpp" #include "physics/btUprightConstraint.hpp" @@ -77,6 +79,12 @@ # pragma warning(disable:4355) #endif +#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__) +# define isnan _isnan +#else +# include +#endif + /** The kart constructor. * \param ident The identifier for the kart model to use. * \param position The position (or rank) for this kart (between 1 and @@ -794,29 +802,32 @@ void Kart::finishedRace(float time) // in modes that support it, start end animation setController(new EndController(this, m_controller->getPlayer(), m_controller)); - GameSlot *slot = unlock_manager->getCurrentSlot(); - const Challenge *challenge = slot->getCurrentChallenge(); - // In case of a GP challenge don't make the end animation depend - // on if the challenge is fulfilled - if(challenge && !challenge->getData()->isGrandPrix()) + if (m_controller->isPlayerController()) // if player is on this computer { - if(challenge->getData()->isChallengeFulfilled()) - m_kart_model->setAnimation(KartModel::AF_WIN_START); + GameSlot *slot = unlock_manager->getCurrentSlot(); + const Challenge *challenge = slot->getCurrentChallenge(); + // In case of a GP challenge don't make the end animation depend + // on if the challenge is fulfilled + if(challenge && !challenge->getData()->isGrandPrix()) + { + if(challenge->getData()->isChallengeFulfilled()) + m_kart_model->setAnimation(KartModel::AF_WIN_START); + else + m_kart_model->setAnimation(KartModel::AF_LOSE_START); + + } + else if(m_race_position<=0.5f*race_manager->getNumberOfKarts() || + m_race_position==1) + m_kart_model->setAnimation(KartModel::AF_WIN_START); else m_kart_model->setAnimation(KartModel::AF_LOSE_START); - } - else if(m_race_position<=0.5f*race_manager->getNumberOfKarts() || - m_race_position==1) - m_kart_model->setAnimation(KartModel::AF_WIN_START); - else - m_kart_model->setAnimation(KartModel::AF_LOSE_START); - - RaceGUIBase* m = World::getWorld()->getRaceGUI(); - if(m) - { - m->addMessage((getPosition() == 1 ? _("You won the race!") : _("You finished the race!")) , - this, 2.0f); + RaceGUIBase* m = World::getWorld()->getRaceGUI(); + if(m) + { + m->addMessage((getPosition() == 1 ? _("You won the race!") : _("You finished the race!")) , + this, 2.0f); + } } } else if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER) @@ -1236,7 +1247,9 @@ void Kart::update(float dt) } // if there is material // Check if any item was hit. - ItemManager::get()->checkItemHit(this); + // check it if we're not in a network world, or if we're on the server (when network mode is on) + if (!NetworkWorld::getInstance()->isRunning() || NetworkManager::getInstance()->isServer()) + ItemManager::get()->checkItemHit(this); static video::SColor pink(255, 255, 133, 253); static video::SColor green(255, 61, 87, 23); @@ -1282,7 +1295,7 @@ void Kart::update(float dt) // take the same time again to reach the bottom float t = 2.0f * v/force; - // Jump if either the jump is estimated to be long enough, or + // Jump if either the jump is estimated to be long enough, or // the texture has the jump property set. if(t>getKartProperties()->getJumpAnimationTime() || last_m->isJumpTexture() ) diff --git a/src/network/protocols/server_lobby_room_protocol.cpp b/src/network/protocols/server_lobby_room_protocol.cpp index eeb5991e6..38d4d99fd 100644 --- a/src/network/protocols/server_lobby_room_protocol.cpp +++ b/src/network/protocols/server_lobby_room_protocol.cpp @@ -19,6 +19,7 @@ #include "network/protocols/server_lobby_room_protocol.hpp" #include "network/server_network_manager.hpp" +#include "network/network_world.hpp" #include "network/protocols/get_public_address.hpp" #include "network/protocols/show_public_address.hpp" #include "network/protocols/connect_to_peer.hpp" @@ -28,10 +29,12 @@ #include "online/current_user.hpp" #include "online/http_manager.hpp" #include "config/user_config.hpp" +#include "modes/world.hpp" #include "utils/log.hpp" #include "utils/time.hpp" #include "utils/random_generator.hpp" + ServerLobbyRoomProtocol::ServerLobbyRoomProtocol() : LobbyRoomProtocol(NULL) { } @@ -47,29 +50,45 @@ ServerLobbyRoomProtocol::~ServerLobbyRoomProtocol() void ServerLobbyRoomProtocol::setup() { m_setup = NetworkManager::getInstance()->setupNewGame(); // create a new setup + m_setup->getRaceConfig()->setPlayerCount(16); //FIXME : this has to be moved to when logging into the server m_next_id = 0; m_state = NONE; m_public_address.ip = 0; m_public_address.port = 0; m_selection_enabled = false; + m_in_race = false; Log::info("ServerLobbyRoomProtocol", "Starting the protocol."); } //----------------------------------------------------------------------------- -void ServerLobbyRoomProtocol::notifyEvent(Event* event) +bool ServerLobbyRoomProtocol::notifyEventAsynchronous(Event* event) { assert(m_setup); // assert that the setup exists if (event->type == EVENT_TYPE_MESSAGE) { - assert(event->data.size()); // message not empty + NetworkString data = event->data(); + assert(data.size()); // message not empty uint8_t message_type; - message_type = event->data.getAndRemoveUInt8(); + 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); - if (message_type == 0x02) // player requesting kart selection + 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) { @@ -78,6 +97,7 @@ void ServerLobbyRoomProtocol::notifyEvent(Event* event) { kartDisconnected(event); } // if (event->type == EVENT_TYPE_DISCONNECTED) + return true; } //----------------------------------------------------------------------------- @@ -108,56 +128,9 @@ void ServerLobbyRoomProtocol::update() break; case WORKING: { - // first poll every 5 seconds - static double last_poll_time = 0; - if (StkTime::getRealTime() > last_poll_time+10.0) - { - last_poll_time = StkTime::getRealTime(); - TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); - Online::XMLRequest* request = new Online::XMLRequest(); - request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); - request->setParameter("id",Online::CurrentUser::get()->getID()); - request->setParameter("token",Online::CurrentUser::get()->getToken()); - request->setParameter("address",addr.ip); - request->setParameter("port",addr.port); - request->setParameter("action","poll-connection-requests"); - - Online::HTTPManager::get()->synchronousRequest(request); - assert(request->isDone()); - - const XMLNode * result = request->getResult(); - std::string rec_success; - if(result->get("success", &rec_success)) - { - if(rec_success == "yes") - { - const XMLNode * users_xml = result->getNode("users"); - uint32_t id = 0; - for (unsigned int i = 0; i < users_xml->getNumNodes(); i++) - { - users_xml->getNode(i)->get("id", &id); - Log::debug("ServerLobbyRoomProtocol", "User with id %d wants to connect.", id); - m_incoming_peers_ids.push_back(id); - } - } - else - { - Log::error("ServerLobbyRoomProtocol", "Error while reading the list."); - } - } - else - { - Log::error("ServerLobbyRoomProtocol", "Cannot retrieve the list."); - } - delete request; - } - - // now - for (unsigned int i = 0; i < m_incoming_peers_ids.size(); i++) - { - m_listener->requestStart(new ConnectToPeer(m_incoming_peers_ids[i])); - } - m_incoming_peers_ids.clear(); + checkIncomingConnectionRequests(); + if (m_in_race && World::getWorld() && NetworkWorld::getInstance()->isRunning()) + checkRaceFinished(); break; } @@ -182,6 +155,7 @@ void ServerLobbyRoomProtocol::startGame() m_listener->sendMessage(this, peers[i], ns, true); // reliably } m_listener->requestStart(new StartGameProtocol(m_setup)); + m_in_race = true; } //----------------------------------------------------------------------------- @@ -200,6 +174,139 @@ void ServerLobbyRoomProtocol::startSelection() //----------------------------------------------------------------------------- +void ServerLobbyRoomProtocol::checkIncomingConnectionRequests() +{ + // first poll every 5 seconds + static double last_poll_time = 0; + if (StkTime::getRealTime() > last_poll_time+10.0) + { + last_poll_time = StkTime::getRealTime(); + TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); + Online::XMLRequest* request = new Online::XMLRequest(); + request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); + request->setParameter("id",Online::CurrentUser::get()->getProfile()->getID()); + request->setParameter("token",Online::CurrentUser::get()->getToken()); + request->setParameter("address",addr.ip); + request->setParameter("port",addr.port); + request->setParameter("action","poll-connection-requests"); + + Online::HTTPManager::get()->synchronousRequest(request); + assert(request->isDone()); + + const XMLNode * result = request->getResult(); + std::string rec_success; + if(result->get("success", &rec_success)) + { + if(rec_success == "yes") + { + const XMLNode * users_xml = result->getNode("users"); + uint32_t id = 0; + for (unsigned int i = 0; i < users_xml->getNumNodes(); i++) + { + users_xml->getNode(i)->get("id", &id); + Log::debug("ServerLobbyRoomProtocol", "User with id %d wants to connect.", id); + m_incoming_peers_ids.push_back(id); + } + } + else + { + Log::error("ServerLobbyRoomProtocol", "Error while reading the list."); + } + } + else + { + Log::error("ServerLobbyRoomProtocol", "Cannot retrieve the list."); + } + delete request; + } + + // now + for (unsigned int i = 0; i < m_incoming_peers_ids.size(); i++) + { + m_listener->requestStart(new ConnectToPeer(m_incoming_peers_ids[i])); + } + m_incoming_peers_ids.clear(); +} + +//----------------------------------------------------------------------------- + +void ServerLobbyRoomProtocol::checkRaceFinished() +{ + assert(NetworkWorld::getInstance()->isRunning()); + assert(World::getWorld()); + // if race is over, give the final score to everybody + if (NetworkWorld::getInstance()->isRaceOver()) + { + // calculate karts ranks : + int num_players = race_manager->getNumberOfKarts(); + std::vector karts_results; + std::vector karts_times; + for (int j = 0; j < num_players; j++) + { + float kart_time = race_manager->getKartRaceTime(j); + for (unsigned int i = 0; i < karts_times.size(); i++) + { + if (kart_time < karts_times[i]) + { + karts_times.insert(karts_times.begin()+i, kart_time); + karts_results.insert(karts_results.begin()+i, j); + break; + } + } + } + + std::vector peers = NetworkManager::getInstance()->getPeers(); + + NetworkString queue; + for (unsigned int i = 0; i < karts_results.size(); i++) + { + queue.ai8(1).ai8(karts_results[i]); // kart pos = i+1 + Log::info("ServerLobbyRoomProtocol", "Kart %d finished #%d", karts_results[i], i+1); + } + for (unsigned int i = 0; i < peers.size(); i++) + { + NetworkString ns; + ns.ai8(0x06).ai8(4).ai32(peers[i]->getClientServerToken()); + NetworkString total = ns + queue; + m_listener->sendMessage(this, peers[i], total, true); + } + Log::info("ServerLobbyRoomProtocol", "End of game message sent"); + m_in_race = false; + + // stop race protocols + Protocol* protocol = NULL; + protocol = m_listener->getProtocol(PROTOCOL_CONTROLLER_EVENTS); + if (protocol) + m_listener->requestTerminate(protocol); + else + Log::error("ClientLobbyRoomProtocol", "No controller events protocol registered."); + + protocol = m_listener->getProtocol(PROTOCOL_KART_UPDATE); + if (protocol) + m_listener->requestTerminate(protocol); + else + Log::error("ClientLobbyRoomProtocol", "No kart update protocol registered."); + + protocol = m_listener->getProtocol(PROTOCOL_GAME_EVENTS); + if (protocol) + m_listener->requestTerminate(protocol); + else + Log::error("ClientLobbyRoomProtocol", "No game events protocol registered."); + + // notify the network world that it is stopped + NetworkWorld::getInstance()->stop(); + // exit the race now + race_manager->exitRace(); + race_manager->setAIKartOverride(""); + } + else + { + //Log::info("ServerLobbyRoomProtocol", "Phase is %d", World::getWorld()->getPhase()); + } +} + +//----------------------------------------------------------------------------- + void ServerLobbyRoomProtocol::kartDisconnected(Event* event) { STKPeer* peer = *(event->peer); @@ -209,7 +316,7 @@ void ServerLobbyRoomProtocol::kartDisconnected(Event* event) 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); + peer->getPlayerProfile()->race_id); m_setup->removePlayer(peer->getPlayerProfile()->race_id); NetworkManager::getInstance()->removePeer(peer); } @@ -232,19 +339,20 @@ void ServerLobbyRoomProtocol::kartDisconnected(Event* event) void ServerLobbyRoomProtocol::connectionRequested(Event* event) { STKPeer* peer = *(event->peer); - if (event->data.size() != 5 || event->data[0] != 4) + NetworkString data = event->data(); + if (data.size() != 5 || data[0] != 4) { - Log::warn("ServerLobbyRoomProtocol", "The server is sending a badly formated message. Size is %d and first byte %d", event->data.size(), event->data[0]); + 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 = event->data.getUInt32(1); + player_id = data.getUInt32(1); // can we add the player ? - if (m_setup->getPlayerCount() < 16) // accept player + if (m_setup->getPlayerCount() < + ServerNetworkManager::getInstance()->getMaxPlayers()) //accept { // add the player to the game setup - while(m_setup->getProfile(m_next_id)!=NULL) - m_next_id++; + 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; @@ -267,7 +375,7 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event) std::vector players = m_setup->getPlayers(); for (unsigned int i = 0; i < players.size(); i++) { - // do not make a duplicate of the player + // 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()); } @@ -309,27 +417,17 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event) */ void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event) { - if (event->data.size() < 6 || event->data[0] != 4) - { - Log::warn("ServerLobbyRoomProtocol", "The server is sending a badly " - "formated message. Size is %d and first byte %d", - event->data.size(), event->data[0]); - return; - } + NetworkString data = event->data(); STKPeer* peer = *(event->peer); - uint32_t token = event->data.gui32(1); - if (token != peer->getClientServerToken()) - { - Log::warn("ServerLobbyRoomProtocol", "Peer sending bad token. Request " - "aborted."); + if (!checkDataSizeAndToken(event, 6)) return; - } - uint8_t kart_name_size = event->data.gui8(5); - std::string kart_name = event->data.gs(6, kart_name_size); + + 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()); + "%d, real: %d.", kart_name_size, kart_name.size()); return; } // check if selection is possible @@ -367,3 +465,195 @@ void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event) } //----------------------------------------------------------------------------- + +/*! \brief Called when a player votes for a major 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 | major mode vote | + * ---------------------------------------- + */ +void ServerLobbyRoomProtocol::playerMajorVote(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()->setPlayerMajorVote(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(0xc0); // prefix the token with the ype + sendMessageToPeersChangingToken(prefix, other); +} +//----------------------------------------------------------------------------- + +/*! \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->peer); + if (!checkDataSizeAndToken(event, 7)) + return; + if (!isByteCorrect(event, 5, 1)) + return; + uint8_t player_id = peer->getPlayerProfile()->race_id; + m_setup->getRaceConfig()->setPlayerRaceCountVote(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(0xc1); // prefix the token with the type + sendMessageToPeersChangingToken(prefix, other); +} +//----------------------------------------------------------------------------- + +/*! \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->peer); + if (!checkDataSizeAndToken(event, 8)) + return; + int N = data[5]; + std::string track_name = data.gs(5, N); + if (!isByteCorrect(event, N+6, 1)) + return; + uint8_t player_id = peer->getPlayerProfile()->race_id; + m_setup->getRaceConfig()->setPlayerTrackVote(player_id, track_name, data[N+7]); + // 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(0xc3); // prefix the token with the ype + sendMessageToPeersChangingToken(prefix, other); +} +//----------------------------------------------------------------------------- + +/*! \brief Called when a player votes for the reverse mode of a race + * \param event : Event providing the information. + * + * Format of the data : + * Byte 0 1 5 6 7 8 9 + * --------------------------------------------------------- + * Size | 1 | 4 | 1 | 1 | 1 | 1 | + * Data | 4 | priv token | 1 | reversed | 1 | track number (gp) | + * --------------------------------------------------------- + */ +void ServerLobbyRoomProtocol::playerReversedVote(Event* event) +{ + NetworkString data = event->data(); + STKPeer* peer = *(event->peer); + if (!checkDataSizeAndToken(event, 9)) + return; + if (!isByteCorrect(event, 5, 1)) + return; + if (!isByteCorrect(event, 7, 1)) + return; + uint8_t player_id = peer->getPlayerProfile()->race_id; + m_setup->getRaceConfig()->setPlayerReversedVote(player_id, data[6]!=0, data[8]); + // 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(0xc4); // prefix the token with the ype + sendMessageToPeersChangingToken(prefix, other); +} +//----------------------------------------------------------------------------- + +/*! \brief Called when a player votes for a major race mode. + * \param event : Event providing the information. + * + * Format of the data : + * Byte 0 1 5 6 7 8 9 + * ----------------------------------------------------- + * Size | 1 | 4 | 1 | 1 | 1 | 1 | + * Data | 4 | priv token | 1 | laps | 1 | track number (gp) | + * ----------------------------------------------------- + */ +void ServerLobbyRoomProtocol::playerLapsVote(Event* event) +{ + NetworkString data = event->data(); + STKPeer* peer = *(event->peer); + if (!checkDataSizeAndToken(event, 9)) + return; + if (!isByteCorrect(event, 5, 1)) + return; + if (!isByteCorrect(event, 7, 1)) + return; + uint8_t player_id = peer->getPlayerProfile()->race_id; + m_setup->getRaceConfig()->setPlayerLapsVote(player_id, data[6], data[8]); + // 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(0xc5); // prefix the token with the ype + sendMessageToPeersChangingToken(prefix, other); +} +//----------------------------------------------------------------------------- diff --git a/src/network/stk_host.hpp b/src/network/stk_host.hpp index 16b6dd43f..a9951000c 100644 --- a/src/network/stk_host.hpp +++ b/src/network/stk_host.hpp @@ -23,8 +23,12 @@ #define STK_HOST_HPP #include "network/types.hpp" + #include "network/network_string.hpp" +// enet.h includes win32.h, which without lean_and_mean includes +// winspool.h, which defines MAX_PRIORITY as a macro, which then +// results in http_manager.hpp not being compilable. #define WIN32_LEAN_AND_MEAN #include @@ -59,6 +63,13 @@ class STKHost STKHost(); /*! \brief Destructor */ virtual ~STKHost(); + + /*! \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. + */ + static void logPacket(const NetworkString ns, bool incoming); /*! \brief Thread function checking if data is received. * This function tries to get data from network low-level functions as @@ -113,6 +124,7 @@ class STKHost * \return A string containing the data of the received packet. */ uint8_t* receiveRawPacket(); + uint8_t* receiveRawPacket(TransportAddress* sender); /*! \brief Receives a packet directly from the network interface and * filter its address. * Receive a packet whithout ENet processing it. Checks that the @@ -120,10 +132,13 @@ class STKHost * parameter. Does not check the port right now. * \param sender : Transport address of the original sender of the * wanted packet. + * \param max_tries : Number of times we try to read data from the + * socket. This is aproximately the time we wait in milliseconds. + * -1 means eternal tries. * \return A string containing the data of the received packet * matching the sender's ip address. */ - uint8_t* receiveRawPacket(TransportAddress sender); + uint8_t* receiveRawPacket(TransportAddress sender, int max_tries = -1); /*! \brief Broadcasts a packet to all peers. * \param data : Data to send. */ @@ -137,9 +152,21 @@ class STKHost * \return True if the peer is known and connected, false elseway. */ bool isConnectedTo(TransportAddress peer_address); + + /*! \brief Returns true when the thread should stop listening. */ + int mustStopListening(); + /*! \brief Returns true when the thread has stopped listening. */ + bool hasStoppedListening() const { return m_listening; } + + uint32_t getAddress() const { return m_host->address.host; } + uint16_t getPort() const; protected: ENetHost* m_host; //!< ENet host interfacing sockets. pthread_t* m_listening_thread; //!< Thread listening network events. + pthread_mutex_t m_exit_mutex; //!< Mutex to kill properly the thread + bool m_listening; + static FILE* m_log_file; //!< Where to log packets + static pthread_mutex_t m_log_mutex; //!< To write in the log only once at a time }; diff --git a/src/utils/time.hpp b/src/utils/time.hpp index b801270d3..8c796756b 100644 --- a/src/utils/time.hpp +++ b/src/utils/time.hpp @@ -21,12 +21,14 @@ #include #ifdef WIN32 +# define WIN32_LEAN_AND_MEAN # define _WINSOCKAPI_ # include # include #else # include # include +# include #endif #include @@ -81,7 +83,14 @@ public: }; // getTimeSinceEpoch // ------------------------------------------------------------------------ - /** + /** Returns a time based on an arbitrary 'epoch' (e.g. could be start + * time of the application, 1.1.1970, ...). + * The value is a double precision floating point value in seconds. + */ + static double getRealTime(long startAt=0); + + // ------------------------------------------------------------------------ + /** * \brief Compare two different times. * \return A signed integral indicating the relation between the time. */ @@ -98,7 +107,19 @@ public: }; // compareTime // ------------------------------------------------------------------------ - /** + /** Sleeps for the specified amount of time. + * \param msec Number of milliseconds to sleep. + */ + static void sleep(int msec) + { +#ifdef WIN32 + Sleep(msec); +#else + usleep(msec*1000); +#endif + } // sleep + // ------------------------------------------------------------------------ + /** * \brief Add a interval to a time. */ static TimeType addInterval(TimeType time, int year, int month, int day) {