now to know the public ip address, the GetPublicAddress protocol uses randomly selected STUN servers from the UserConfig file. If the server doesn't answer after two seconds, the protocol will reset and pick a random server again.
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/hilnius@13574 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
74c819fd8d
commit
93ec81f309
@ -18,14 +18,18 @@
|
||||
|
||||
#include "network/protocols/get_public_address.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/client_network_manager.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
#include "network/network_interface.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/random_generator.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int stunRand()
|
||||
{
|
||||
@ -92,16 +96,48 @@ void GetPublicAddress::asynchronousUpdate()
|
||||
bytes[19] = (uint8_t)(m_stun_tansaction_id[2]);
|
||||
bytes[20] = '\0';
|
||||
|
||||
Log::verbose("GetPublicAddress", "Querrying STUN server 132.177.123.6");
|
||||
unsigned int dst = (132<<24)+(177<<16)+(123<<8)+6;
|
||||
NetworkManager::getInstance()->setManualSocketsMode(true);
|
||||
NetworkManager::getInstance()->getHost()->sendRawPacket(bytes, 20, TransportAddress(dst, 3478));
|
||||
m_state = TEST_SENT;
|
||||
// time to pick a random stun server
|
||||
std::vector<char*> stun_servers = UserConfigParams::m_stun_servers;
|
||||
|
||||
RandomGenerator random_gen;
|
||||
int rand_result = random_gen.get(stun_servers.size());
|
||||
Log::verbose("GetPublicAddress", "Using STUN server %s", stun_servers[rand_result]);
|
||||
|
||||
// resolve the name into an IP address
|
||||
struct addrinfo hints, *res, *p;
|
||||
int status;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((status = getaddrinfo(stun_servers[rand_result], NULL, &hints, &res)) != 0) {
|
||||
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
|
||||
return;
|
||||
}
|
||||
for(p = res;p != NULL; p = p->ai_next)
|
||||
{
|
||||
struct sockaddr_in* interface = (struct sockaddr_in*)(p->ai_addr);
|
||||
|
||||
m_stun_server_ip = ntohl(interface->sin_addr.s_addr);
|
||||
NetworkManager::getInstance()->setManualSocketsMode(true);
|
||||
NetworkManager::getInstance()->getHost()->sendRawPacket(bytes, 20, TransportAddress(m_stun_server_ip, 3478));
|
||||
m_state = TEST_SENT;
|
||||
|
||||
freeaddrinfo(res); // free the linked list
|
||||
return;
|
||||
}
|
||||
freeaddrinfo(res); // free the linked list
|
||||
|
||||
}
|
||||
if (m_state == TEST_SENT)
|
||||
{
|
||||
unsigned int dst = (132<<24)+(177<<16)+(123<<8)+6;
|
||||
uint8_t* data = NetworkManager::getInstance()->getHost()->receiveRawPacket(TransportAddress(dst, 3478));
|
||||
uint8_t* data = NetworkManager::getInstance()->getHost()->receiveRawPacket(TransportAddress(m_stun_server_ip, 3478), 2000);
|
||||
if (!data)
|
||||
{
|
||||
m_state = NOTHING_DONE; // will send the test again to an other server
|
||||
return;
|
||||
}
|
||||
assert(data);
|
||||
|
||||
// check that the stun response is a response, contains the magic cookie and the transaction ID
|
||||
|
@ -44,6 +44,7 @@ class GetPublicAddress : public Protocol
|
||||
STATE m_state;
|
||||
uint32_t m_stun_tansaction_id[3];
|
||||
static const uint32_t m_stun_magic_cookie = 0x2112A442;
|
||||
uint32_t m_stun_server_ip;
|
||||
};
|
||||
|
||||
#endif // GET_PUBLIC_ADDRESS_HPP
|
||||
|
@ -204,7 +204,7 @@ uint8_t* STKHost::receiveRawPacket(TransportAddress* sender)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t* STKHost::receiveRawPacket(TransportAddress sender)
|
||||
uint8_t* STKHost::receiveRawPacket(TransportAddress sender, int max_tries)
|
||||
{
|
||||
uint8_t* buffer; // max size needed normally (only used for stun)
|
||||
buffer = (uint8_t*)(malloc(sizeof(uint8_t)*2048));
|
||||
@ -227,6 +227,11 @@ uint8_t* STKHost::receiveRawPacket(TransportAddress sender)
|
||||
i++;
|
||||
len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, &addr, &from_len);
|
||||
irr_driver->getDevice()->sleep(1); // wait 1 millisecond between two checks
|
||||
if (i >= max_tries && max_tries != -1)
|
||||
{
|
||||
Log::verbose("STKHost", "No answer from the server.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (addr.sa_family == AF_INET)
|
||||
{
|
||||
|
@ -120,10 +120,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.
|
||||
*/
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "modes/demo_world.hpp"
|
||||
#include "modes/overworld.hpp"
|
||||
#include "modes/world_with_rank.hpp"
|
||||
#include "network/network_world.hpp"
|
||||
#include "race/highscores.hpp"
|
||||
#include "states_screens/feature_unlocked.hpp"
|
||||
#include "states_screens/main_menu_screen.hpp"
|
||||
@ -96,6 +97,23 @@ void RaceResultGUI::enableAllButtons()
|
||||
enableGPProgress();
|
||||
}
|
||||
|
||||
// If we're in a network world, change the buttons text
|
||||
if (NetworkWorld::getInstance()->isRunning())
|
||||
{
|
||||
top->setVisible(false);
|
||||
middle->setText( _("Continue.") );
|
||||
middle->setVisible(true);
|
||||
middle->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
bottom->setText( _("Quit the server.") );
|
||||
bottom->setVisible(true);
|
||||
if (race_manager->getMajorMode()==RaceManager::MAJOR_MODE_GRAND_PRIX)
|
||||
{
|
||||
middle->setVisible(false); // you have to wait the server to start again
|
||||
bottom->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If something was unlocked
|
||||
// -------------------------
|
||||
int n = unlock_manager->getCurrentSlot()->getRecentlyCompletedChallenges().size();
|
||||
@ -215,6 +233,22 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// If we're playing online :
|
||||
if (NetworkWorld::getInstance()->isRunning())
|
||||
{
|
||||
StateManager::get()->popMenu();
|
||||
if (name == "middle") // Continue button (return to server lobby)
|
||||
{
|
||||
}
|
||||
if (name == "bottom") // Quit server (return to main menu)
|
||||
{
|
||||
race_manager->exitRace();
|
||||
race_manager->setAIKartOverride("");
|
||||
StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Next check for GP
|
||||
// -----------------
|
||||
if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_GRAND_PRIX)
|
||||
|
Loading…
x
Reference in New Issue
Block a user