diff --git a/libretroshare/src/pqi/p3connmgr.cc b/libretroshare/src/pqi/p3connmgr.cc index d10858a3a..6f52dd006 100644 --- a/libretroshare/src/pqi/p3connmgr.cc +++ b/libretroshare/src/pqi/p3connmgr.cc @@ -1453,6 +1453,19 @@ void p3ConnectMgr::tickMonitors() (*mit)->statusChange(actionList); } } + +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections + + /* notify all monitors */ + std::list::iterator mit; + for(mit = clients.begin(); mit != clients.end(); mit++) { + (*mit)->statusChanged(); + } + +/////////////////////////////////////////////////////////// +#endif } diff --git a/libretroshare/src/pqi/pqimonitor.h b/libretroshare/src/pqi/pqimonitor.h index 548188b73..f82244f89 100644 --- a/libretroshare/src/pqi/pqimonitor.h +++ b/libretroshare/src/pqi/pqimonitor.h @@ -112,6 +112,14 @@ virtual ~pqiMonitor() { return; } *@param plist contains list of states and actions of the client's peers */ virtual void statusChange(const std::list &plist) = 0; + +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections +virtual void statusChanged() {}; +/////////////////////////////////////////////////////////// +#endif + //virtual void ownStatusChange(pqipeer &) { return; } // SIGNAL reset or similar. //virtual void peerStatus(std::string id, uint32_t mode) = 0; diff --git a/libretroshare/src/pqi/pqipersongrp.cc b/libretroshare/src/pqi/pqipersongrp.cc index 079ea17d8..3af1f72c9 100644 --- a/libretroshare/src/pqi/pqipersongrp.cc +++ b/libretroshare/src/pqi/pqipersongrp.cc @@ -32,6 +32,15 @@ const int pqipersongrpzone = 354; +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections +#include "retroshare/rsinit.h" +static std::list waitingIds; +#define MAX_CONNECT_COUNT 5 +/////////////////////////////////////////////////////////// +#endif + /**** *#define PGRP_DEBUG 1 ****/ @@ -296,6 +305,73 @@ void pqipersongrp::statusChange(const std::list &plist) } } +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections +void pqipersongrp::statusChanged() +{ +#warning "Windows connection limited hacked together - please fix" + + if (RsInit::isWindowsXP() == false) { + /* the problem only exist in Windows XP */ + waitingIds.clear(); + return; + } + + /* check for active connections and start waiting id's */ + long connect_count = 0; + + { + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + /* get address from p3connmgr */ + if (!mConnMgr) { + return; + } + + /* check for active connections and start waiting id's */ + std::list peers; + mConnMgr->getFriendList(peers); + + /* count connection attempts */ + std::list::iterator peer; + for (peer = peers.begin(); peer != peers.end(); peer++) { + peerConnectState state; + if (mConnMgr->getFriendNetStatus(*peer, state) == false) { + continue; + } + + if (state.inConnAttempt) { + connect_count++; + if (connect_count >= MAX_CONNECT_COUNT) { +#ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::connectPeer() Too many connections due to windows limitations. There are " << waitingIds.size() << " waiting connections." << std::endl; +#endif + return; + } + } + } + + } /* UNLOCKED */ + +#ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::connectPeer() There are " << connect_count << " connection attempts and " << waitingIds.size() << " waiting connections. Can start " << (MAX_CONNECT_COUNT - connect_count) << " connection attempts." << std::endl; +#endif + + /* there is no need for a mutex for waitingIds */ + + /* start some waiting id's */ + for (int i = connect_count; i < MAX_CONNECT_COUNT; i++) { + if (waitingIds.empty()) { + break; + } + std::string waitingId = waitingIds.front(); + waitingIds.pop_front(); + connectPeer(waitingId, true); + } +} +/////////////////////////////////////////////////////////// +#endif int pqipersongrp::addPeer(std::string id) @@ -393,7 +469,14 @@ int pqipersongrp::tagHeartbeatRecvd(std::string id) -int pqipersongrp::connectPeer(std::string id) +int pqipersongrp::connectPeer(std::string id +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections + , bool bConnect /*= false*/ +/////////////////////////////////////////////////////////// +#endif + ) { /* get status from p3connectMgr */ #ifdef PGRP_DEBUG @@ -423,6 +506,33 @@ int pqipersongrp::connectPeer(std::string id) if (!mConnMgr) return 0; +#ifdef WINDOWS_SYS + /////////////////////////////////////////////////////////// + // hack for too many connections + + if (RsInit::isWindowsXP()) { + /* the problem only exist in Windows XP */ + if (bConnect == false) { + /* check for id is waiting */ + if (std::find(waitingIds.begin(), waitingIds.end(), id) != waitingIds.end()) { + /* id is waiting for a connection */ + return 0; + } + + /* add id to waiting */ + waitingIds.push_back(id); + + /* wait for call to connectPeer with empty id */ + return 0; + } + + /* remove id from waiting */ + waitingIds.remove(id); + } + + /////////////////////////////////////////////////////////// +#endif + struct sockaddr_in addr; uint32_t delay; uint32_t period; diff --git a/libretroshare/src/pqi/pqipersongrp.h b/libretroshare/src/pqi/pqipersongrp.h index 32c6dfd38..7243d46bd 100644 --- a/libretroshare/src/pqi/pqipersongrp.h +++ b/libretroshare/src/pqi/pqipersongrp.h @@ -64,10 +64,24 @@ int load_config(); /*************** pqiMonitor callback ***********************/ virtual void statusChange(const std::list &plist); +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections +virtual void statusChanged(); +/////////////////////////////////////////////////////////// +#endif + /******************* Peer Control **************************/ virtual int addPeer(std::string id); /* can be overloaded for testing */ int removePeer(std::string id); -int connectPeer(std::string id); +int connectPeer(std::string id +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections + , bool bConnect = false +/////////////////////////////////////////////////////////// +#endif + ); /* Work-around to dodgy pointer stuff */ int tagHeartbeatRecvd(std::string id); diff --git a/libretroshare/src/retroshare/rsinit.h b/libretroshare/src/retroshare/rsinit.h index cee38ca9c..fdd0b2dbb 100644 --- a/libretroshare/src/retroshare/rsinit.h +++ b/libretroshare/src/retroshare/rsinit.h @@ -67,7 +67,7 @@ class RsInit */ static char dirSeperator(); static bool isPortable(); - + static bool isWindowsXP(); /*! * Account Details (Combined GPG+SSL Setup) diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 32e09df73..98dd59277 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -76,6 +76,7 @@ class RsInitConfig static std::string homePath; #ifdef WINDOWS_SYS static bool portable; + static bool isWindowsXP; #endif static std::list accountIds; @@ -169,6 +170,7 @@ std::string RsInitConfig::basedir; std::string RsInitConfig::homePath; #ifdef WINDOWS_SYS bool RsInitConfig::portable = false; +bool RsInitConfig::isWindowsXP = false; #endif /* Listening Port */ @@ -252,10 +254,38 @@ void RsInit::InitRsConfig() #ifdef WINDOWS_SYS // test for portable version - if (GetFileAttributes (L"gpg.exe") != (DWORD) -1 && GetFileAttributes (L"gpgme-w32spawn.exe") != (DWORD) -1) { + if (GetFileAttributes (L"gpg.exe") != (DWORD) -1 && GetFileAttributes (L"gpgme-w32spawn.exe") != (DWORD) -1) { // use portable version RsInitConfig::portable = true; } + + // test for Windows XP + OSVERSIONINFOEX osvi; + memset(&osvi, 0, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + if (GetVersionEx((OSVERSIONINFO*) &osvi)) { + if (osvi.dwMajorVersion == 5) { + if (osvi.dwMinorVersion == 1) { + /* Windows XP */ + RsInitConfig::isWindowsXP = true; + } else if (osvi.dwMinorVersion == 2) { + SYSTEM_INFO si; + memset(&si, 0, sizeof(si)); + GetSystemInfo(&si); + if (osvi.wProductType == VER_NT_WORKSTATION && si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) { + /* Windows XP Professional x64 Edition */ + RsInitConfig::isWindowsXP = true; + } + } + } + } + + if (RsInitConfig::isWindowsXP) { + std::cerr << "Running Windows XP" << std::endl; + } else { + std::cerr << "Not running Windows XP" << std::endl; + } #endif /* Setup the Debugging */ @@ -1988,6 +2018,15 @@ bool RsInit::isPortable() #endif } +bool RsInit::isWindowsXP() +{ +#ifdef WINDOWS_SYS + return RsInitConfig::isWindowsXP; +#else + return false; +#endif +} + std::string RsInit::RsConfigDirectory() { return RsInitConfig::basedir;