cleaning way of stopping the listening thread (now uses a mutex locked/unlocked) Fixed some other bugs.
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/hilnius@13633 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
074ef2237d
commit
ff8fda6219
@ -161,7 +161,6 @@ void ConnectToServer::asynchronousUpdate()
|
||||
{
|
||||
// just send a broadcast packet, the client will know our ip address and will connect
|
||||
STKHost* host = NetworkManager::getInstance()->getHost();
|
||||
NetworkManager::getInstance()->setManualSocketsMode(true);
|
||||
TransportAddress sender;
|
||||
Log::info("ConnectToServer", "Waiting broadcast message.");
|
||||
const uint8_t* received_data = host->receiveRawPacket(&sender); // get the sender
|
||||
@ -173,9 +172,11 @@ void ConnectToServer::asynchronousUpdate()
|
||||
// just check if the ip is ours : if so, then just use localhost (127.0.0.1)
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
struct sockaddr_in *sa;
|
||||
getifaddrs (&ifap);
|
||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr->sa_family==AF_INET) {
|
||||
getifaddrs (&ifap); // get the info
|
||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family==AF_INET)
|
||||
{
|
||||
sa = (struct sockaddr_in *) ifa->ifa_addr;
|
||||
if (turnEndianness(sa->sin_addr.s_addr) == sender.ip) // this interface is ours
|
||||
sender.ip = 0x7f000001; // 127.0.0.1
|
||||
@ -220,7 +221,6 @@ void ConnectToServer::asynchronousUpdate()
|
||||
m_server_address = sender;
|
||||
m_state = CONNECTING;
|
||||
}
|
||||
NetworkManager::getInstance()->setManualSocketsMode(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -125,8 +125,9 @@ void GetPublicAddress::asynchronousUpdate()
|
||||
struct sockaddr_in* current_interface = (struct sockaddr_in*)(p->ai_addr);
|
||||
|
||||
m_stun_server_ip = ntohl(current_interface->sin_addr.s_addr);
|
||||
NetworkManager::getInstance()->setManualSocketsMode(true);
|
||||
NetworkManager::getInstance()->getHost()->sendRawPacket(bytes, 20, TransportAddress(m_stun_server_ip, 3478));
|
||||
m_transaction_host = new STKHost();
|
||||
m_transaction_host->setupClient(1,1,0,0);
|
||||
m_transaction_host->sendRawPacket(bytes, 20, TransportAddress(m_stun_server_ip, 3478));
|
||||
m_state = TEST_SENT;
|
||||
|
||||
freeaddrinfo(res); // free the linked list
|
||||
@ -137,7 +138,7 @@ void GetPublicAddress::asynchronousUpdate()
|
||||
}
|
||||
if (m_state == TEST_SENT)
|
||||
{
|
||||
uint8_t* data = NetworkManager::getInstance()->getHost()->receiveRawPacket(TransportAddress(m_stun_server_ip, 3478), 2000);
|
||||
uint8_t* data = m_transaction_host->receiveRawPacket(TransportAddress(m_stun_server_ip, 3478), 2000);
|
||||
if (!data)
|
||||
{
|
||||
m_state = NOTHING_DONE; // will send the test again to an other server
|
||||
@ -220,7 +221,6 @@ void GetPublicAddress::asynchronousUpdate()
|
||||
{
|
||||
Log::debug("GetPublicAddress", "The public address has been found : %i.%i.%i.%i:%i", address>>24&0xff, address>>16&0xff, address>>8&0xff, address&0xff, port);
|
||||
m_state = ADDRESS_KNOWN;
|
||||
NetworkManager::getInstance()->setManualSocketsMode(false);
|
||||
TransportAddress* addr = static_cast<TransportAddress*>(m_callback_object);
|
||||
addr->ip = address;
|
||||
addr->port = port;
|
||||
|
@ -45,6 +45,7 @@ class GetPublicAddress : public Protocol
|
||||
uint32_t m_stun_tansaction_id[3];
|
||||
static const uint32_t m_stun_magic_cookie = 0x2112A442;
|
||||
uint32_t m_stun_server_ip;
|
||||
STKHost* m_transaction_host;
|
||||
};
|
||||
|
||||
#endif // GET_PUBLIC_ADDRESS_HPP
|
||||
|
@ -37,8 +37,9 @@
|
||||
void* STKHost::receive_data(void* self)
|
||||
{
|
||||
ENetEvent event;
|
||||
ENetHost* host = (((STKHost*)(self))->m_host);
|
||||
while (1)
|
||||
STKHost* myself = (STKHost*)(self);
|
||||
ENetHost* host = myself->m_host;
|
||||
while (!myself->mustStopListening())
|
||||
{
|
||||
while (enet_host_service(host, &event, 20) != 0) {
|
||||
Event* evt = new Event(&event);
|
||||
@ -47,6 +48,9 @@ void* STKHost::receive_data(void* self)
|
||||
delete evt;
|
||||
}
|
||||
}
|
||||
myself->m_listening = false;
|
||||
delete myself->m_listening_thread;
|
||||
myself->m_listening_thread = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -56,18 +60,14 @@ STKHost::STKHost()
|
||||
{
|
||||
m_host = NULL;
|
||||
m_listening_thread = NULL;
|
||||
pthread_mutex_init(&m_exit_mutex, NULL);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
STKHost::~STKHost()
|
||||
{
|
||||
if (m_listening_thread)
|
||||
{
|
||||
pthread_cancel(*m_listening_thread);//, SIGKILL); with kill
|
||||
delete m_listening_thread;
|
||||
m_listening_thread = NULL;
|
||||
}
|
||||
stopListening();
|
||||
if (m_host)
|
||||
{
|
||||
enet_host_destroy(m_host);
|
||||
@ -84,6 +84,13 @@ void STKHost::setupServer(uint32_t address, uint16_t port, int peer_count,
|
||||
addr->host = address;
|
||||
addr->port = port;
|
||||
|
||||
#ifdef WIN32/*
|
||||
addr->host = 0;
|
||||
addr->host += ((unsigned int)(192)<<0); // 192.168.0.11
|
||||
addr->host += ((unsigned int)(168)<<8); // 192.168.0.11
|
||||
addr->host += ((unsigned int)(11)<<24); // 192.168.0.11*/
|
||||
#endif
|
||||
|
||||
m_host = enet_host_create(addr, peer_count, channel_limit,
|
||||
max_incoming_bandwidth, max_outgoing_bandwidth);
|
||||
if (m_host == NULL)
|
||||
@ -114,8 +121,10 @@ void STKHost::setupClient(int peer_count, int channel_limit,
|
||||
|
||||
void STKHost::startListening()
|
||||
{
|
||||
pthread_mutex_lock(&m_exit_mutex); // will let the update function start
|
||||
m_listening_thread = (pthread_t*)(malloc(sizeof(pthread_t)));
|
||||
pthread_create(m_listening_thread, NULL, &STKHost::receive_data, this);
|
||||
m_listening = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -124,8 +133,7 @@ void STKHost::stopListening()
|
||||
{
|
||||
if(m_listening_thread)
|
||||
{
|
||||
pthread_cancel(*m_listening_thread);
|
||||
m_listening_thread = NULL;
|
||||
pthread_mutex_unlock(&m_exit_mutex); // will stop the update function
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,12 +190,16 @@ uint8_t* STKHost::receiveRawPacket(TransportAddress* sender)
|
||||
|
||||
int i = 0;
|
||||
// wait to receive the message because enet sockets are non-blocking
|
||||
while(len < 0)
|
||||
while(len == -1) // nothing received
|
||||
{
|
||||
i++;
|
||||
len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, &addr, &from_len);
|
||||
Time::sleep(1); // wait 1 millisecond between two checks
|
||||
}
|
||||
if (len == SOCKET_ERROR)
|
||||
{
|
||||
Log::error("STKHost", "Problem with the socket. Please contact the dev team.");
|
||||
}
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) (&addr);
|
||||
// we received the data
|
||||
sender->ip = turnEndianness((uint32_t)(sin->sin_addr.s_addr));
|
||||
@ -211,32 +223,40 @@ uint8_t* STKHost::receiveRawPacket(TransportAddress sender, int max_tries)
|
||||
memset(buffer, 0, 2048);
|
||||
|
||||
socklen_t from_len;
|
||||
struct sockaddr addr;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
from_len = sizeof(addr);
|
||||
int len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, &addr, &from_len);
|
||||
int len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, (struct sockaddr*)(&addr), &from_len);
|
||||
|
||||
int i = 0;
|
||||
// wait to receive the message because enet sockets are non-blocking
|
||||
while(len < 0 || (
|
||||
(uint8_t)(addr.sa_data[2]) != (sender.ip>>24&0xff)
|
||||
&& (uint8_t)(addr.sa_data[3]) != (sender.ip>>16&0xff)
|
||||
&& (uint8_t)(addr.sa_data[4]) != (sender.ip>>8&0xff)
|
||||
&& (uint8_t)(addr.sa_data[5]) != (sender.ip&0xff)))
|
||||
while(len < 0 || addr.sin_addr.s_addr == sender.ip)
|
||||
{
|
||||
i++;
|
||||
len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, &addr, &from_len);
|
||||
if (len>=0)
|
||||
{
|
||||
Log::info("STKHost", "Message received but the ip address didn't match the expected one.");
|
||||
}
|
||||
len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, (struct sockaddr*)(&addr), &from_len);
|
||||
uint32_t addr1 = addr.sin_addr.s_addr;
|
||||
uint32_t addr2 = sender.ip;
|
||||
uint32_t addr3 = ntohl(addr1);
|
||||
uint32_t addr4 = ntohl(addr2);
|
||||
Time::sleep(1); // wait 1 millisecond between two checks
|
||||
if (i >= max_tries && max_tries != -1)
|
||||
{
|
||||
Log::verbose("STKHost", "No answer from the server.");
|
||||
Log::verbose("STKHost", "No answer from the server on %u.%u.%u.%u:%u", (m_host->address.host&0xff),
|
||||
(m_host->address.host>>8&0xff),
|
||||
(m_host->address.host>>16&0xff),
|
||||
(m_host->address.host>>24&0xff),
|
||||
(m_host->address.port));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (addr.sa_family == AF_INET)
|
||||
if (addr.sin_family == AF_INET)
|
||||
{
|
||||
char s[20];
|
||||
inet_ntop(AF_INET, &(((struct sockaddr_in *)&addr)->sin_addr), s, 20);
|
||||
inet_ntop(AF_INET, &(addr.sin_addr), s, 20);
|
||||
Log::info("STKHost", "IPv4 Address of the sender was %s", s);
|
||||
}
|
||||
return buffer;
|
||||
@ -281,3 +301,17 @@ bool STKHost::isConnectedTo(TransportAddress peer)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int STKHost::mustStopListening()
|
||||
{
|
||||
switch(pthread_mutex_trylock(&m_exit_mutex)) {
|
||||
case 0: /* if we got the lock, unlock and return 1 (true) */
|
||||
pthread_mutex_unlock(&m_exit_mutex);
|
||||
return 1;
|
||||
case EBUSY: /* return 0 (false) if the mutex was locked */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
@ -140,9 +140,16 @@ 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() { return m_listening; }
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user