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:
hilnius 2013-09-05 20:19:44 +00:00
parent 074ef2237d
commit ff8fda6219
5 changed files with 73 additions and 31 deletions

View File

@ -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
{

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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;
};