mirror of
https://github.com/glest/glest-source.git
synced 2025-08-13 03:44:00 +02:00
Ported LAN auto-connect feature to win32
This commit is contained in:
@@ -23,6 +23,14 @@ using std::string;
|
|||||||
const char* WSAGetLastErrorMessage(const char* pcMessagePrefix,int nErrorID = 0);
|
const char* WSAGetLastErrorMessage(const char* pcMessagePrefix,int nErrorID = 0);
|
||||||
|
|
||||||
namespace Shared{ namespace Platform{
|
namespace Shared{ namespace Platform{
|
||||||
|
//
|
||||||
|
// This interface describes the methods a callback object must implement
|
||||||
|
// when signalled with detected servers
|
||||||
|
//
|
||||||
|
class DiscoveredServersInterface {
|
||||||
|
public:
|
||||||
|
virtual void DiscoveredServers(std::vector<string> serverList) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// class IP
|
// class IP
|
||||||
@@ -81,6 +89,7 @@ public:
|
|||||||
int peek(void *data, int dataSize);
|
int peek(void *data, int dataSize);
|
||||||
|
|
||||||
void setBlock(bool block);
|
void setBlock(bool block);
|
||||||
|
static void setBlock(bool block, SOCKET socket);
|
||||||
bool isReadable();
|
bool isReadable();
|
||||||
bool isWritable(bool waitOnDelayedResponse);
|
bool isWritable(bool waitOnDelayedResponse);
|
||||||
bool isConnected();
|
bool isConnected();
|
||||||
@@ -93,14 +102,48 @@ protected:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BroadCastClientSocketThread : public Thread
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Mutex mutexRunning;
|
||||||
|
Mutex mutexQuit;
|
||||||
|
|
||||||
|
bool quit;
|
||||||
|
bool running;
|
||||||
|
|
||||||
|
DiscoveredServersInterface *discoveredServersCB;
|
||||||
|
|
||||||
|
void setRunningStatus(bool value);
|
||||||
|
void setQuitStatus(bool value);
|
||||||
|
|
||||||
|
public:
|
||||||
|
BroadCastClientSocketThread(DiscoveredServersInterface *cb);
|
||||||
|
virtual void execute();
|
||||||
|
void signalQuit();
|
||||||
|
bool getQuitStatus();
|
||||||
|
bool getRunningStatus();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// class ClientSocket
|
// class ClientSocket
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
class ClientSocket: public Socket{
|
class ClientSocket: public Socket{
|
||||||
public:
|
public:
|
||||||
|
ClientSocket();
|
||||||
|
virtual ~ClientSocket();
|
||||||
|
|
||||||
void connect(const Ip &ip, int port);
|
void connect(const Ip &ip, int port);
|
||||||
static std::vector<string> discoverServers();
|
static std::vector<string> discoverServers();
|
||||||
|
static void discoverServers(DiscoveredServersInterface *cb);
|
||||||
|
|
||||||
|
static void stopBroadCastClientThread();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
static BroadCastClientSocketThread *broadCastClientThread;
|
||||||
|
static void startBroadCastClientThread(DiscoveredServersInterface *cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
class BroadCastSocketThread : public Thread
|
class BroadCastSocketThread : public Thread
|
||||||
|
@@ -156,6 +156,7 @@ const char* WSAGetLastErrorMessage(const char* pcMessagePrefix,
|
|||||||
namespace Shared{ namespace Platform{
|
namespace Shared{ namespace Platform{
|
||||||
|
|
||||||
int Socket::broadcast_portno = 61357;
|
int Socket::broadcast_portno = 61357;
|
||||||
|
BroadCastClientSocketThread *ClientSocket::broadCastClientThread = NULL;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// class Ip
|
// class Ip
|
||||||
@@ -543,9 +544,12 @@ int Socket::peek(void *data, int dataSize){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Socket::setBlock(bool block){
|
void Socket::setBlock(bool block){
|
||||||
u_long iMode= !
|
setBlock(block,this->sock);
|
||||||
block;
|
}
|
||||||
int err= ioctlsocket(sock, FIONBIO, &iMode);
|
|
||||||
|
void Socket::setBlock(bool block, SOCKET socket){
|
||||||
|
u_long iMode= !block;
|
||||||
|
int err= ioctlsocket(socket, FIONBIO, &iMode);
|
||||||
if(err==SOCKET_ERROR)
|
if(err==SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
throwException("Error setting I/O mode for socket");
|
throwException("Error setting I/O mode for socket");
|
||||||
@@ -690,6 +694,63 @@ void Socket::throwException(const string &str){
|
|||||||
// =====================================================
|
// =====================================================
|
||||||
// class ClientSocket
|
// class ClientSocket
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
ClientSocket::ClientSocket() : Socket() {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
//broadCastClientThread = NULL;
|
||||||
|
stopBroadCastClientThread();
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientSocket::~ClientSocket() {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
stopBroadCastClientThread();
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientSocket::stopBroadCastClientThread() {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
if(broadCastClientThread != NULL) {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
broadCastClientThread->signalQuit();
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= 5; ) {
|
||||||
|
if(broadCastClientThread->getRunningStatus() == false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sleep(100);
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
}
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
delete broadCastClientThread;
|
||||||
|
broadCastClientThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientSocket::startBroadCastClientThread(DiscoveredServersInterface *cb) {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
ClientSocket::stopBroadCastClientThread();
|
||||||
|
|
||||||
|
broadCastClientThread = new BroadCastClientSocketThread(cb);
|
||||||
|
broadCastClientThread->start();
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientSocket::discoverServers(DiscoveredServersInterface *cb) {
|
||||||
|
ClientSocket::startBroadCastClientThread(cb);
|
||||||
|
}
|
||||||
|
|
||||||
void ClientSocket::connect(const Ip &ip, int port)
|
void ClientSocket::connect(const Ip &ip, int port)
|
||||||
{
|
{
|
||||||
@@ -786,16 +847,83 @@ void ClientSocket::connect(const Ip &ip, int port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
// Function : discovery_response_thread
|
// Function : discovery response thread
|
||||||
// in : none
|
// Description: Runs in its own thread to listen for broadcasts from
|
||||||
// return : none
|
|
||||||
// Description: To be forked in its own thread to listen and respond to broadcasts from
|
|
||||||
// other servers
|
// other servers
|
||||||
//
|
//
|
||||||
std::vector<string> ClientSocket::discoverServers() {
|
BroadCastClientSocketThread::BroadCastClientSocketThread(DiscoveredServersInterface *cb) {
|
||||||
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
setQuitStatus(false);
|
||||||
|
setRunningStatus(false);
|
||||||
|
discoveredServersCB = cb;
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadCastClientSocketThread::signalQuit() {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
setQuitStatus(true);
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadCastClientSocketThread::setQuitStatus(bool value) {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
mutexQuit.p();
|
||||||
|
quit = value;
|
||||||
|
mutexQuit.v();
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BroadCastClientSocketThread::getQuitStatus() {
|
||||||
|
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
bool retval = false;
|
||||||
|
mutexQuit.p();
|
||||||
|
retval = quit;
|
||||||
|
mutexQuit.v();
|
||||||
|
|
||||||
|
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BroadCastClientSocketThread::getRunningStatus() {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
bool retval = false;
|
||||||
|
mutexRunning.p();
|
||||||
|
retval = running;
|
||||||
|
mutexRunning.v();
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] running = %d\n",__FILE__,__FUNCTION__,__LINE__,retval);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadCastClientSocketThread::setRunningStatus(bool value) {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] value = %d\n",__FILE__,__FUNCTION__,__LINE__,value);
|
||||||
|
|
||||||
|
mutexRunning.p();
|
||||||
|
running = value;
|
||||||
|
mutexRunning.v();
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] running = %d\n",__FILE__,__FUNCTION__,__LINE__,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
// Function : broadcast thread
|
||||||
|
// Description: Runs in its own thread to send out a broadcast to the local network
|
||||||
|
// the current broadcast message is <myhostname:my.ip.address.dotted>
|
||||||
|
//
|
||||||
|
void BroadCastClientSocketThread::execute() {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
std::vector<string> foundServers;
|
std::vector<string> foundServers;
|
||||||
|
|
||||||
short port; // The port for the broadcast.
|
short port; // The port for the broadcast.
|
||||||
@@ -812,7 +940,7 @@ std::vector<string> ClientSocket::discoverServers() {
|
|||||||
// Prepare to receive the broadcast.
|
// Prepare to receive the broadcast.
|
||||||
bcfd = socket(AF_INET, SOCK_DGRAM, 0);
|
bcfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if( bcfd <= 0 ) {
|
if( bcfd <= 0 ) {
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"socket failed: %d\n", WSAGetLastError());
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"socket failed: %d\n", errno);
|
||||||
//exit(-1);
|
//exit(-1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -823,37 +951,69 @@ std::vector<string> ClientSocket::discoverServers() {
|
|||||||
bcaddr.sin_port = port;
|
bcaddr.sin_port = port;
|
||||||
|
|
||||||
int val = 1;
|
int val = 1;
|
||||||
setsockopt(bcfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
|
setsockopt(bcfd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
|
||||||
|
|
||||||
if(bind( bcfd, (struct sockaddr *)&bcaddr, sizeof(bcaddr) ) < 0 ) {
|
if(bind( bcfd, (struct sockaddr *)&bcaddr, sizeof(bcaddr) ) < 0 ) {
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"bind failed: %d\n", WSAGetLastError());
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"bind failed: %d\n", errno);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
// Keep getting packets forever.
|
|
||||||
for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= 3; )
|
|
||||||
{
|
|
||||||
alen = sizeof(struct sockaddr);
|
|
||||||
if( (nb = recvfrom(bcfd, buff, 10024, 0, (struct sockaddr *) &bcSender, &alen)) <= 0 )
|
|
||||||
{
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"recvfrom failed: %d\n", WSAGetLastError());
|
|
||||||
//exit(-1);
|
|
||||||
}
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"broadcast message received: [%s] from: [%s]\n", buff,inet_ntoa(bcSender.sin_addr) );
|
|
||||||
|
|
||||||
vector<string> tokens;
|
Socket::setBlock(false, bcfd);
|
||||||
Tokenize(buff,tokens,":");
|
|
||||||
for(int idx = 1; idx < tokens.size(); idx++) {
|
setRunningStatus(true);
|
||||||
foundServers.push_back(tokens[idx]);
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is running\n");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Keep getting packets forever.
|
||||||
|
for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= 5; )
|
||||||
|
{
|
||||||
|
alen = sizeof(struct sockaddr);
|
||||||
|
if( (nb = recvfrom(bcfd, buff, 10024, 0, (struct sockaddr *) &bcSender, &alen)) <= 0 )
|
||||||
|
{
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"recvfrom failed: %d\n", errno);
|
||||||
|
//exit(-1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"broadcast message received: [%s] from: [%s]\n", buff,inet_ntoa(bcSender.sin_addr) );
|
||||||
|
|
||||||
|
vector<string> tokens;
|
||||||
|
Tokenize(buff,tokens,":");
|
||||||
|
for(int idx = 1; idx < tokens.size(); idx++) {
|
||||||
|
foundServers.push_back(tokens[idx]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(getQuitStatus() == true) {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sleep( 100 ); // send out broadcast every 1 seconds
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
catch(const exception &ex) {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
|
||||||
|
setRunningStatus(false);
|
||||||
|
}
|
||||||
|
catch(...) {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
setRunningStatus(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
setRunningStatus(false);
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is exiting\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
return foundServers;
|
// Here we callback into the implementer class
|
||||||
|
if(discoveredServersCB != NULL) {
|
||||||
|
discoveredServersCB->DiscoveredServers(foundServers);
|
||||||
|
}
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
Reference in New Issue
Block a user