Limit the concurrent connection attempts in Windows XP. Its's only a hack.

Problem:
RetroShare connects to all ssl's at once. In Windows XP there is a build-in connection limit of concurrent incomplete connections.

Quote:
"The TCP/IP stack in Windows XP with Service Pack 2 (SP2) installed limits the number of concurrent, incomplete outbound TCP connection attempts. When the limit is reached, subsequent connection attempts are put in a queue and resolved at a fixed rate so that there are only a limited number of connections in the incomplete state."

This results in a high usage of the nonepaged pool and when it runs over the limit it results in the following error in the system log:
German:  "TCP/IP hat das Sicherheitslimit erreicht, das für die Anzahl gleichzeitiger TCP-Verbindungsversuche festgelegt wurde."
English: "TCP/IP has reached the security limit imposed on the number of concurrent (incomplete) TCP connect attempts."

After a longer runtime of RetroShare and a very high usage of the nonepaged pool all connections of all running programs are lost and no new connections can be made. At the end it can cause a blue screen.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3631 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
thunder2 2010-10-07 11:17:42 +00:00
parent c134b5f605
commit f4bbd3e933
6 changed files with 188 additions and 4 deletions

View file

@ -32,6 +32,15 @@
const int pqipersongrpzone = 354;
#ifdef WINDOWS_SYS
///////////////////////////////////////////////////////////
// hack for too many connections
#include "retroshare/rsinit.h"
static std::list<std::string> waitingIds;
#define MAX_CONNECT_COUNT 5
///////////////////////////////////////////////////////////
#endif
/****
*#define PGRP_DEBUG 1
****/
@ -296,6 +305,73 @@ void pqipersongrp::statusChange(const std::list<pqipeer> &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<std::string> peers;
mConnMgr->getFriendList(peers);
/* count connection attempts */
std::list<std::string>::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;