mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
9e5e07d3f0
* Disabled lots of debugging. * Disabled LOCAL test mode in udpstunner, rsinit * Enabled BadPeer checking in bitdht. * Restored normal timeout periods for connection attempts. * Restored normal connection levels for dht status. git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-dhtmods@4779 b45a01b8-16f6-495d-af2f-9b41ad6348cc
2436 lines
61 KiB
C++
2436 lines
61 KiB
C++
|
|
#include "dht/p3bitdht.h"
|
|
|
|
#include <stdio.h>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
|
|
#include "bitdht/bdiface.h"
|
|
#include "bitdht/bdstddht.h"
|
|
#include "bitdht/bdmanager.h"
|
|
|
|
//#include "udp/udplayer.h"
|
|
|
|
#include "util/rsnet.h"
|
|
#include "tcponudp/tou.h"
|
|
#include "tcponudp/udpstunner.h"
|
|
#include "tcponudp/udprelay.h"
|
|
|
|
#include "pqi/p3netmgr.h"
|
|
#include "pqi/pqimonitor.h"
|
|
|
|
#define PEERNET_CONNECT_TIMEOUT 180 // Should be BIGGER than Higher level (but okay if not!)
|
|
|
|
#define MIN_DETERMINISTIC_SWITCH_PERIOD 60
|
|
|
|
/***
|
|
*
|
|
* #define DEBUG_BITDHT_COMMON 1 // These are the things that are called regularly (annoying for debugging specifics)
|
|
* #define DEBUG_PEERNET 1
|
|
*
|
|
**/
|
|
|
|
|
|
/******************************************************************************************
|
|
************************************* Dht Callback ***************************************
|
|
******************************************************************************************/
|
|
|
|
/**** dht NodeCallback ****
|
|
*
|
|
*
|
|
* In the old version, we used this to callback mConnCb->peerStatus()
|
|
* We might want to drop this, and concentrate on the connection stuff.
|
|
*
|
|
* -> if an new dht peer, then pass to Stunners.
|
|
* -> do we care if we know them? not really!
|
|
*/
|
|
|
|
int p3BitDht::InfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info)
|
|
{
|
|
/* translate info */
|
|
std::string rsid;
|
|
struct sockaddr_in addr = id->addr;
|
|
int outtype = PNASS_TYPE_BADPEER;
|
|
int outreason = PNASS_REASON_UNKNOWN;
|
|
int outage = 0;
|
|
|
|
#ifdef DEBUG_BITDHT_COMMON
|
|
std::cerr << "p3BitDht::InfoCallback() likely BAD_PEER: ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(id->id), RSDHT_PEERTYPE_ANY);
|
|
|
|
if (dpd)
|
|
{
|
|
rsid = dpd->mRsId;
|
|
}
|
|
}
|
|
|
|
if (mPeerSharer)
|
|
{
|
|
mPeerSharer->updatePeer(rsid, addr, outtype, outreason, outage);
|
|
}
|
|
|
|
/* call to the Stunners to drop the address as well */
|
|
/* IDEALLY these addresses should all be filtered at UdpLayer level instead! */
|
|
if (mDhtStunner)
|
|
{
|
|
mDhtStunner->dropStunPeer(addr);
|
|
}
|
|
if (mProxyStunner)
|
|
{
|
|
mProxyStunner->dropStunPeer(addr);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
/**** dht NodeCallback ****
|
|
*
|
|
*
|
|
* In the old version, we used this to callback mConnCb->peerStatus()
|
|
* We might want to drop this, and concentrate on the connection stuff.
|
|
*
|
|
* -> if an new dht peer, then pass to Stunners.
|
|
* -> do we care if we know them? not really!
|
|
*/
|
|
|
|
int p3BitDht::NodeCallback(const bdId *id, uint32_t peerflags)
|
|
{
|
|
// No need for Mutex, and Stunners are self protected.
|
|
|
|
// These are the flags that will be returned by p3BitDht & RS peers with the new DHT.
|
|
// if (peerflags & BITDHT_PEER_STATUS_DHT_ENGINE_VERSION) // Change to this later...
|
|
if ((peerflags & BITDHT_PEER_STATUS_DHT_ENGINE) &&
|
|
(peerflags & BITDHT_PEER_STATUS_DHT_APPL))
|
|
{
|
|
|
|
/* pass off to the Stunners
|
|
* but only if they need them.
|
|
* ideally don't pass to both peers... (XXX do later)
|
|
*/
|
|
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
if (id->id == mOwnDhtId)
|
|
{
|
|
#ifdef DEBUG_BITDHT_COMMON
|
|
std::cerr << "p3BitDht::NodeCallback() Skipping own id";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
if ((mProxyStunner) && (mProxyStunner->needStunPeers()))
|
|
{
|
|
#ifdef DEBUG_BITDHT_COMMON
|
|
std::cerr << "p3BitDht::NodeCallback() Passing BitDHT Peer to DhtStunner: ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mProxyStunner->addStunPeer(id->addr, "");
|
|
}
|
|
/* else */ // removed else until we have lots of peers.
|
|
|
|
if ((mDhtStunner) && (mDhtStunner->needStunPeers()))
|
|
{
|
|
#ifdef DEBUG_BITDHT_COMMON
|
|
std::cerr << "p3BitDht::NodeCallback() Passing BitDHT Peer to DhtStunner: ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mDhtStunner->addStunPeer(id->addr, "");
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/**** dht PeerCallback ****
|
|
*
|
|
*
|
|
* In the old version, we used this to callback mConnCb->peerConnectRequest()
|
|
* we need to continue doing this, to maintain compatibility.
|
|
*
|
|
* -> update Dht Status, and trigger connect if ONLINE or UNREACHABLE
|
|
*/
|
|
|
|
|
|
int p3BitDht::PeerCallback(const bdId *id, uint32_t status)
|
|
{
|
|
//std::ostringstream str;
|
|
//bdStdPrintNodeId(str, &(id->id));
|
|
//std::string strId = str.str();
|
|
|
|
//std::cerr << "p3BitDht::dhtPeerCallback()";
|
|
//std::cerr << std::endl;
|
|
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(id->id), RSDHT_PEERTYPE_FRIEND);
|
|
|
|
if (!dpd)
|
|
{
|
|
/* ERROR */
|
|
std::cerr << "p3BitDht::PeerCallback() ERROR Unknown Peer: ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << " status: " << status;
|
|
std::cerr << std::endl;
|
|
|
|
return 0;
|
|
}
|
|
|
|
sockaddr_clear(&(dpd->mDhtId.addr));
|
|
|
|
switch(status)
|
|
{
|
|
default:
|
|
dpd->mDhtState = RSDHT_PEERDHT_NOT_ACTIVE;
|
|
break;
|
|
|
|
case BITDHT_MGR_QUERY_FAILURE:
|
|
dpd->mDhtState = RSDHT_PEERDHT_FAILURE;
|
|
break;
|
|
|
|
case BITDHT_MGR_QUERY_PEER_OFFLINE:
|
|
dpd->mDhtState = RSDHT_PEERDHT_OFFLINE;
|
|
break;
|
|
|
|
case BITDHT_MGR_QUERY_PEER_UNREACHABLE:
|
|
dpd->mDhtState = RSDHT_PEERDHT_UNREACHABLE;
|
|
dpd->mDhtId = *id; // set the IP:Port of the unreachable peer.
|
|
UnreachablePeerCallback_locked(id, status, dpd);
|
|
|
|
break;
|
|
|
|
case BITDHT_MGR_QUERY_PEER_ONLINE:
|
|
dpd->mDhtState = RSDHT_PEERDHT_ONLINE;
|
|
dpd->mDhtId = *id; // set the IP:Port of the Online peer.
|
|
OnlinePeerCallback_locked(id, status, dpd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
time_t now = time(NULL);
|
|
dpd->mDhtUpdateTS = now;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
int p3BitDht::OnlinePeerCallback_locked(const bdId *id, uint32_t /*status*/, DhtPeerDetails *dpd)
|
|
{
|
|
/* remove unused parameter warnings */
|
|
(void) id;
|
|
|
|
if ((dpd->mPeerConnectState != RSDHT_PEERCONN_DISCONNECTED) ||
|
|
(dpd->mPeerReqState == RSDHT_PEERREQ_RUNNING))
|
|
{
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::OnlinePeerCallback_locked() WARNING Ignoring Callback: connection already underway: ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
|
|
bool connectOk = true;
|
|
bool doTCPCallback = false;
|
|
|
|
/* work out network state */
|
|
uint32_t connectFlags = dpd->mConnectLogic.connectCb(CSB_CONNECT_DIRECT,
|
|
mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode());
|
|
// bool useProxyPort = (connectFlags & CSB_ACTION_PROXY_PORT);
|
|
|
|
switch(connectFlags & CSB_ACTION_MASK_MODE)
|
|
{
|
|
default:
|
|
case CSB_ACTION_WAIT:
|
|
{
|
|
connectOk = false;
|
|
}
|
|
break;
|
|
case CSB_ACTION_TCP_CONN:
|
|
{
|
|
connectOk = false;
|
|
doTCPCallback = true;
|
|
}
|
|
break;
|
|
case CSB_ACTION_DIRECT_CONN:
|
|
{
|
|
|
|
connectOk = true;
|
|
}
|
|
break;
|
|
case CSB_ACTION_PROXY_CONN:
|
|
{
|
|
/* ERROR */
|
|
std::cerr << "dhtPeerCallback: ERROR ConnectLogic returned PROXY";
|
|
std::cerr << std::endl;
|
|
connectOk = false;
|
|
}
|
|
break;
|
|
case CSB_ACTION_RELAY_CONN:
|
|
{
|
|
/* ERROR */
|
|
std::cerr << "dhtPeerCallback: ERROR ConnectLogic returned RELAY";
|
|
std::cerr << std::endl;
|
|
connectOk = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (connectOk)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtPeerCallback. Peer Online, triggering Direct Connection for: ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* Push Back PeerAction */
|
|
PeerAction ca;
|
|
ca.mType = PEERNET_ACTION_TYPE_CONNECT;
|
|
ca.mMode = BITDHT_CONNECT_MODE_DIRECT;
|
|
ca.mDestId = *id;
|
|
ca.mAnswer = BITDHT_CONNECT_ERROR_NONE;
|
|
|
|
mActions.push_back(ca);
|
|
}
|
|
|
|
/* might need to make this an ACTION - leave for now */
|
|
if (doTCPCallback)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtPeerCallback. Peer Online, triggering TCP Connection for: ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* Push Back PeerAction */
|
|
PeerAction ca;
|
|
ca.mType = PEERNET_ACTION_TYPE_TCPATTEMPT;
|
|
ca.mMode = BITDHT_CONNECT_MODE_DIRECT;
|
|
ca.mDestId = *id;
|
|
ca.mAnswer = BITDHT_CONNECT_ERROR_NONE;
|
|
|
|
mActions.push_back(ca);
|
|
//ConnectCalloutTCPAttempt(dpd->mRsId, id->addr);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
int p3BitDht::UnreachablePeerCallback_locked(const bdId *id, uint32_t /*status*/, DhtPeerDetails *dpd)
|
|
{
|
|
|
|
if ((dpd->mPeerConnectState != RSDHT_PEERCONN_DISCONNECTED) ||
|
|
(dpd->mPeerReqState == RSDHT_PEERREQ_RUNNING))
|
|
{
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::UnreachablePeerCallback_locked() WARNING Ignoring Callback: connection already underway: ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtPeerCallback. Peer Unreachable, triggering Proxy | Relay Connection for: ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
bool proxyOk = false;
|
|
bool connectOk = true;
|
|
|
|
/* work out network state */
|
|
uint32_t connectFlags = dpd->mConnectLogic.connectCb(CSB_CONNECT_UNREACHABLE,
|
|
mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode());
|
|
bool useProxyPort = (connectFlags & CSB_ACTION_PROXY_PORT);
|
|
|
|
switch(connectFlags & CSB_ACTION_MASK_MODE)
|
|
{
|
|
default:
|
|
case CSB_ACTION_WAIT:
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtPeerCallback. Request to Wait ... so no Connection Attempt for ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
connectOk = false;
|
|
}
|
|
break;
|
|
case CSB_ACTION_DIRECT_CONN:
|
|
{
|
|
/* ERROR */
|
|
std::cerr << "dhtPeerCallback: ERROR ConnectLogic returned DIRECT";
|
|
std::cerr << std::endl;
|
|
|
|
connectOk = false;
|
|
}
|
|
break;
|
|
case CSB_ACTION_PROXY_CONN:
|
|
{
|
|
proxyOk = true;
|
|
connectOk = true;
|
|
}
|
|
break;
|
|
case CSB_ACTION_RELAY_CONN:
|
|
{
|
|
proxyOk = false;
|
|
connectOk = true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (connectOk)
|
|
{
|
|
/* Push Back PeerAction */
|
|
PeerAction ca;
|
|
ca.mType = PEERNET_ACTION_TYPE_CONNECT;
|
|
ca.mDestId = *id;
|
|
|
|
dpd->mConnectLogic.storeProxyPortChoice(connectFlags, useProxyPort);
|
|
|
|
if (proxyOk)
|
|
{
|
|
ca.mMode = BITDHT_CONNECT_MODE_PROXY;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtPeerCallback. Trying Proxy Connection.";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtPeerCallback. Trying Relay Connection.";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
ca.mMode = BITDHT_CONNECT_MODE_RELAY;
|
|
}
|
|
|
|
ca.mAnswer = BITDHT_CONNECT_ERROR_NONE;
|
|
mActions.push_back(ca);
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtPeerCallback. Cancelled Connection Attempt for ";
|
|
bdStdPrintId(std::cerr, id);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
int p3BitDht::ValueCallback(const bdNodeId */*id*/, std::string /*key*/, uint32_t /*status*/)
|
|
{
|
|
std::cerr << "p3BitDht::ValueCallback() ERROR Does nothing!";
|
|
std::cerr << std::endl;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId,
|
|
uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
#endif
|
|
std::cerr << "p3BitDht::ConnectCallback()";
|
|
std::cerr << std::endl;
|
|
std::cerr << "srcId: ";
|
|
bdStdPrintId(std::cerr, srcId);
|
|
std::cerr << std::endl;
|
|
std::cerr << "proxyId: ";
|
|
bdStdPrintId(std::cerr, proxyId);
|
|
std::cerr << std::endl;
|
|
std::cerr << "destId: ";
|
|
bdStdPrintId(std::cerr, destId);
|
|
std::cerr << std::endl;
|
|
|
|
std::cerr << " mode: " << mode;
|
|
std::cerr << " param: " << param;
|
|
std::cerr << " point: " << point;
|
|
std::cerr << " cbtype: " << cbtype;
|
|
std::cerr << std::endl;
|
|
|
|
|
|
/* we handle MID and START/END points differently... this is biggest difference.
|
|
* so handle first.
|
|
*/
|
|
|
|
bdId peerId;
|
|
time_t now = time(NULL);
|
|
|
|
switch(point)
|
|
{
|
|
default:
|
|
case BD_PROXY_CONNECTION_UNKNOWN_POINT:
|
|
{
|
|
std::cerr << "p3BitDht::dhtConnectCallback() ERROR UNKNOWN point, ignoring Callback";
|
|
std::cerr << std::endl;
|
|
return 0;
|
|
}
|
|
case BD_PROXY_CONNECTION_START_POINT:
|
|
peerId = *destId;
|
|
break;
|
|
case BD_PROXY_CONNECTION_END_POINT:
|
|
peerId = *srcId;
|
|
break;
|
|
case BD_PROXY_CONNECTION_MID_POINT:
|
|
{
|
|
/* AS a mid point, we can receive.... AUTH,PENDING,PROXY,FAILED */
|
|
|
|
switch(cbtype)
|
|
{
|
|
case BITDHT_CONNECT_CB_AUTH:
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Proxy Connection Requested Between:";
|
|
std::cerr << std::endl;
|
|
bdStdPrintId(std::cerr, srcId);
|
|
std::cerr << " and ";
|
|
bdStdPrintId(std::cerr, destId);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
/* if there is an error code - then it is just to inform us of a failed attempt */
|
|
if (errcode)
|
|
{
|
|
RelayHandler_LogFailedProxyAttempt(srcId, destId, mode, errcode);
|
|
/* END MID FAILED ATTEMPT */
|
|
return 1;
|
|
}
|
|
|
|
uint32_t bandwidth = 0;
|
|
|
|
int connectionAllowed = BITDHT_CONNECT_ERROR_GENERIC;
|
|
if (checkProxyAllowed(srcId, destId, mode, bandwidth))
|
|
{
|
|
connectionAllowed = BITDHT_CONNECT_ANSWER_OKAY;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Connection Allowed";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
connectionAllowed = BITDHT_CONNECT_ERROR_AUTH_DENIED;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Connection Denied";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
/* Push Back PeerAction */
|
|
PeerAction ca;
|
|
ca.mType = PEERNET_ACTION_TYPE_AUTHORISE;
|
|
ca.mMode = mode;
|
|
ca.mProxyId = *proxyId;
|
|
ca.mSrcId = *srcId;
|
|
ca.mDestId = *destId;
|
|
ca.mPoint = point;
|
|
ca.mAnswer = connectionAllowed;
|
|
ca.mDelayOrBandwidth = bandwidth;
|
|
|
|
mActions.push_back(ca);
|
|
}
|
|
break;
|
|
case BITDHT_CONNECT_CB_PENDING:
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Proxy Connection Pending:";
|
|
std::cerr << std::endl;
|
|
bdStdPrintId(std::cerr, srcId);
|
|
std::cerr << " and ";
|
|
bdStdPrintId(std::cerr, destId);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
break;
|
|
case BITDHT_CONNECT_CB_PROXY:
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Proxy Connection Starting:";
|
|
std::cerr << std::endl;
|
|
bdStdPrintId(std::cerr, srcId);
|
|
std::cerr << " and ";
|
|
bdStdPrintId(std::cerr, destId);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
break;
|
|
case BITDHT_CONNECT_CB_FAILED:
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Proxy Connection Failed:";
|
|
std::cerr << std::endl;
|
|
bdStdPrintId(std::cerr, srcId);
|
|
std::cerr << " and ";
|
|
bdStdPrintId(std::cerr, destId);
|
|
|
|
std::cerr << " ErrorCode: " << errcode;
|
|
int errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE;
|
|
int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE;
|
|
|
|
std::cerr << " ErrorSrc: " << errsrc;
|
|
std::cerr << " ErrorType: " << errtype;
|
|
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (mode == BITDHT_CONNECT_MODE_RELAY)
|
|
{
|
|
removeRelayConnection(srcId, destId);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
case BITDHT_CONNECT_CB_START:
|
|
{
|
|
std::cerr << "dhtConnectionCallback() ERROR unexpected Proxy ConnectionCallback:";
|
|
std::cerr << std::endl;
|
|
bdStdPrintId(std::cerr, srcId);
|
|
std::cerr << " and ";
|
|
bdStdPrintId(std::cerr, destId);
|
|
std::cerr << std::endl;
|
|
}
|
|
break;
|
|
}
|
|
/* End the MID Point stuff */
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/* if we get here, we are an endpoint (peer specified in peerId) */
|
|
|
|
/* translate id into string for exclusive mode */
|
|
std::ostringstream idstr;
|
|
bdStdPrintNodeId(idstr, &(peerId.id));
|
|
std::string pid = idstr.str();
|
|
|
|
switch(cbtype)
|
|
{
|
|
case BITDHT_CONNECT_CB_AUTH:
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Connection Requested By: ";
|
|
bdStdPrintId(std::cerr, &(peerId));
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
int connectionAllowed = BITDHT_CONNECT_ERROR_GENERIC;
|
|
if (checkConnectionAllowed(&(peerId), mode))
|
|
{
|
|
connectionAllowed = BITDHT_CONNECT_ANSWER_OKAY;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Connection Allowed";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
connectionAllowed = BITDHT_CONNECT_ERROR_AUTH_DENIED;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Connection Denied";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
/* Push Back PeerAction */
|
|
PeerAction ca;
|
|
ca.mType = PEERNET_ACTION_TYPE_AUTHORISE;
|
|
ca.mProxyId = *proxyId;
|
|
ca.mSrcId = *srcId;
|
|
ca.mDestId = *destId;
|
|
ca.mDelayOrBandwidth = 0;
|
|
|
|
/* Check Proxy ExtAddress Status (but only if connection is Allowed) */
|
|
if ((connectionAllowed == BITDHT_CONNECT_ANSWER_OKAY) &&
|
|
(mode == BITDHT_CONNECT_MODE_PROXY))
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Checking Address for Proxy";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
struct sockaddr_in extaddr;
|
|
uint8_t extStable = 0;
|
|
sockaddr_clear(&extaddr);
|
|
|
|
bool connectOk = false;
|
|
bool proxyPort = false;
|
|
bool exclusivePort = false;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback(): Proxy... deciding which port to use.";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RSDHT_PEERTYPE_FRIEND);
|
|
if (dpd)
|
|
{
|
|
proxyPort = dpd->mConnectLogic.shouldUseProxyPort(
|
|
mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode());
|
|
|
|
dpd->mConnectLogic.storeProxyPortChoice(0, proxyPort);
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback: Setting ProxyPort: ";
|
|
std::cerr << " UseProxyPort? " << proxyPort;
|
|
std::cerr << std::endl;
|
|
|
|
std::cerr << "dhtConnectionCallback: Checking ConnectLogic.NetState: ";
|
|
std::cerr << dpd->mConnectLogic.calcNetState(mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode());
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (proxyPort)
|
|
{
|
|
exclusivePort = (CSB_NETSTATE_EXCLUSIVENAT == dpd->mConnectLogic.calcNetState(
|
|
mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()));
|
|
}
|
|
|
|
if (exclusivePort)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback: we Require Exclusive Proxy Port for connection";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback: Dont need Exclusive Proxy Port for connection";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
|
|
connectOk = true;
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "PeerAction: Connect Proxy: ERROR Cannot find PeerStatus";
|
|
std::cerr << std::endl;
|
|
}
|
|
|
|
UdpStunner *stunner = mProxyStunner;
|
|
if (!proxyPort)
|
|
{
|
|
stunner = mDhtStunner;
|
|
}
|
|
|
|
if ((connectOk) && (stunner) && (stunner->externalAddr(extaddr, extStable)))
|
|
{
|
|
if (extStable)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Proxy Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(peerId));
|
|
std::cerr << " is Ok as we have Stable Own External Proxy Address";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (point == BD_PROXY_CONNECTION_END_POINT)
|
|
{
|
|
ca.mDestId.addr = extaddr;
|
|
}
|
|
else
|
|
{
|
|
ca.mSrcId.addr = extaddr;
|
|
std::cerr << "dhtConnectionCallback() ERROR Proxy Auth as SrcId";
|
|
std::cerr << std::endl;
|
|
}
|
|
|
|
/* check if we require exclusive use of the proxy port */
|
|
if (exclusivePort)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback: Attempting to Grab ExclusiveLock of UdpStunner";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
int stun_age = mProxyStunner->grabExclusiveMode(pid);
|
|
if (stun_age > 0)
|
|
{
|
|
int delay = 0;
|
|
if (stun_age < MIN_DETERMINISTIC_SWITCH_PERIOD)
|
|
{
|
|
delay = MIN_DETERMINISTIC_SWITCH_PERIOD - stun_age;
|
|
}
|
|
|
|
/* great we got it! */
|
|
ca.mDelayOrBandwidth = delay;
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback: GotExclusiveLock With Delay: " << delay;
|
|
std::cerr << " for stable port";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RSDHT_PEERTYPE_FRIEND);
|
|
if (dpd)
|
|
{
|
|
dpd->mExclusiveProxyLock = true;
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback: Success at grabbing ExclusiveLock of UdpStunner";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "PeerAction: Connect Proxy: ERROR Cannot find PeerStatus";
|
|
std::cerr << std::endl;
|
|
connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL;
|
|
mProxyStunner->releaseExclusiveMode(pid,false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* failed to get exclusive mode - must wait */
|
|
connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL;
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback: Failed to Grab ExclusiveLock, Returning TEMPUNAVAIL";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
if (exclusivePort)
|
|
{
|
|
connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Proxy Connection";
|
|
std::cerr << " is Discarded, as External Proxy Address is Not Stable! (EXCLUSIVE MODE)";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
connectionAllowed = BITDHT_CONNECT_ERROR_UNREACHABLE;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Proxy Connection";
|
|
std::cerr << " is Discarded, as Own External Proxy Address is Not Stable!";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() ERROR Proxy Connection ";
|
|
std::cerr << " is Discarded, as Failed to get Own External Proxy Address.";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
ca.mMode = mode;
|
|
ca.mPoint = point;
|
|
ca.mAnswer = connectionAllowed;
|
|
|
|
mActions.push_back(ca);
|
|
}
|
|
break;
|
|
|
|
case BITDHT_CONNECT_CB_START:
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Connection Starting with: ";
|
|
bdStdPrintId(std::cerr, &(peerId));
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
/* Push Back PeerAction */
|
|
PeerAction ca;
|
|
ca.mType = PEERNET_ACTION_TYPE_START;
|
|
ca.mMode = mode;
|
|
ca.mProxyId = *proxyId;
|
|
ca.mSrcId = *srcId;
|
|
ca.mDestId = *destId;
|
|
ca.mPoint = point;
|
|
ca.mDelayOrBandwidth = param;
|
|
ca.mAnswer = BITDHT_CONNECT_ERROR_NONE;
|
|
|
|
mActions.push_back(ca);
|
|
|
|
}
|
|
break;
|
|
|
|
case BITDHT_CONNECT_CB_FAILED:
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
#endif
|
|
std::cerr << "dhtConnectionCallback() Connection Attempt Failed with:";
|
|
bdStdPrintId(std::cerr, &(peerId));
|
|
std::cerr << std::endl;
|
|
|
|
std::cerr << "dhtConnectionCallback() Proxy:";
|
|
bdStdPrintId(std::cerr, proxyId);
|
|
std::cerr << std::endl;
|
|
|
|
std::cerr << "dhtConnectionCallback() ";
|
|
std::cerr << " ErrorCode: " << errcode;
|
|
int errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE;
|
|
int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE;
|
|
|
|
std::cerr << " ErrorSrc: " << errsrc;
|
|
std::cerr << " ErrorType: " << errtype;
|
|
std::cerr << std::endl;
|
|
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RSDHT_PEERTYPE_FRIEND);
|
|
if (dpd)
|
|
{
|
|
dpd->mPeerCbMsg = "ERROR : ";
|
|
dpd->mPeerCbMsg += decodeConnectionError(errcode);
|
|
dpd->mPeerCbMode = mode;
|
|
dpd->mPeerCbPoint = point;
|
|
dpd->mPeerCbProxyId = *proxyId;
|
|
dpd->mPeerCbDestId = peerId;
|
|
dpd->mPeerCbTS = now;
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "dhtConnectionCallback() ";
|
|
std::cerr << "ERROR Unknown Peer";
|
|
std::cerr << std::endl;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case BITDHT_CONNECT_CB_REQUEST:
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "dhtConnectionCallback() Local Connection Request Feedback:";
|
|
bdStdPrintId(std::cerr, &(peerId));
|
|
std::cerr << std::endl;
|
|
|
|
std::cerr << "dhtConnectionCallback() Proxy:";
|
|
bdStdPrintId(std::cerr, proxyId);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (point != BD_PROXY_CONNECTION_START_POINT)
|
|
{
|
|
std::cerr << "dhtConnectionCallback() ERROR not START_POINT";
|
|
std::cerr << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RSDHT_PEERTYPE_FRIEND);
|
|
if (dpd)
|
|
{
|
|
if (errcode)
|
|
{
|
|
ReleaseProxyExclusiveMode_locked(dpd, false);
|
|
|
|
dpd->mPeerReqStatusMsg = "STOPPED: ";
|
|
dpd->mPeerReqStatusMsg += decodeConnectionError(errcode);
|
|
dpd->mPeerReqState = RSDHT_PEERREQ_STOPPED;
|
|
dpd->mPeerReqTS = now;
|
|
|
|
int updatecode = CSB_UPDATE_FAILED_ATTEMPT;
|
|
int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE;
|
|
switch(errtype)
|
|
{
|
|
/* fatal errors */
|
|
case BITDHT_CONNECT_ERROR_AUTH_DENIED:
|
|
{
|
|
updatecode = CSB_UPDATE_AUTH_DENIED;
|
|
}
|
|
break;
|
|
|
|
/* move on errors */
|
|
case BITDHT_CONNECT_ERROR_UNREACHABLE: // sym NAT.
|
|
case BITDHT_CONNECT_ERROR_UNSUPPORTED: // mode unavailable.
|
|
{
|
|
updatecode = CSB_UPDATE_MODE_UNAVAILABLE;
|
|
}
|
|
break;
|
|
|
|
|
|
/* retry attempts */
|
|
case BITDHT_CONNECT_ERROR_TEMPUNAVAIL:
|
|
case BITDHT_CONNECT_ERROR_DUPLICATE:
|
|
{
|
|
updatecode = CSB_UPDATE_RETRY_ATTEMPT;
|
|
}
|
|
break;
|
|
/* standard failed attempts */
|
|
case BITDHT_CONNECT_ERROR_GENERIC:
|
|
case BITDHT_CONNECT_ERROR_PROTOCOL:
|
|
case BITDHT_CONNECT_ERROR_TIMEOUT:
|
|
case BITDHT_CONNECT_ERROR_NOADDRESS:
|
|
case BITDHT_CONNECT_ERROR_OVERLOADED:
|
|
/* CB_REQUEST errors */
|
|
case BITDHT_CONNECT_ERROR_TOOMANYRETRY:
|
|
case BITDHT_CONNECT_ERROR_OUTOFPROXY:
|
|
{
|
|
updatecode = CSB_UPDATE_FAILED_ATTEMPT;
|
|
}
|
|
break;
|
|
|
|
/* user cancelled ... no update */
|
|
case BITDHT_CONNECT_ERROR_USER:
|
|
{
|
|
updatecode = CSB_UPDATE_NONE;
|
|
}
|
|
break;
|
|
}
|
|
if (updatecode)
|
|
{
|
|
dpd->mConnectLogic.updateCb(updatecode);
|
|
}
|
|
}
|
|
else // a new connection attempt.
|
|
{
|
|
dpd->mPeerReqStatusMsg = "Connect Attempt";
|
|
dpd->mPeerReqState = RSDHT_PEERREQ_RUNNING;
|
|
dpd->mPeerReqMode = mode;
|
|
dpd->mPeerReqProxyId = *proxyId;
|
|
dpd->mPeerReqTS = now;
|
|
|
|
// This also is flagged into the instant Cb info.
|
|
dpd->mPeerCbMsg = "Local Connect Attempt";
|
|
dpd->mPeerCbMode = mode;
|
|
dpd->mPeerCbPoint = point;
|
|
dpd->mPeerCbProxyId = *proxyId;
|
|
dpd->mPeerCbDestId = peerId;
|
|
dpd->mPeerCbTS = now;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "dhtConnectionCallback() ERROR Cannot find PeerStatus";
|
|
std::cerr << std::endl;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
case BITDHT_CONNECT_CB_PENDING:
|
|
case BITDHT_CONNECT_CB_PROXY:
|
|
{
|
|
std::cerr << "dhtConnectionCallback() ERROR unexpected ConnectionCallback:";
|
|
std::cerr << std::endl;
|
|
bdStdPrintId(std::cerr, srcId);
|
|
std::cerr << " and ";
|
|
bdStdPrintId(std::cerr, destId);
|
|
std::cerr << std::endl;
|
|
}
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/******************************************************************************************
|
|
******************************** Dht Actions / Monitoring ********************************
|
|
******************************************************************************************/
|
|
|
|
|
|
/* tick stuff that isn't in its own thread */
|
|
|
|
int p3BitDht::tick()
|
|
{
|
|
doActions();
|
|
monitorConnections();
|
|
|
|
minuteTick();
|
|
|
|
#ifdef DEBUG_PEERNET_COMMON
|
|
time_t now = time(NULL);
|
|
std::cerr << "p3BitDht::tick() TIME: " << ctime(&now) << std::endl;
|
|
std::cerr.flush();
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
|
|
#define MINUTE_IN_SECS 60
|
|
#define TEN_IN_SECS 10
|
|
|
|
int p3BitDht::minuteTick()
|
|
{
|
|
time_t now = time(NULL);
|
|
int deltaT = 0;
|
|
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
deltaT = now-mMinuteTS;
|
|
}
|
|
|
|
//if (deltaT > MINUTE_IN_SECS)
|
|
if (deltaT > TEN_IN_SECS)
|
|
{
|
|
mRelay->checkRelays();
|
|
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
mMinuteTS = now;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int p3BitDht::doActions()
|
|
{
|
|
#ifdef DEBUG_PEERNET_COMMON
|
|
std::cerr << "p3BitDht::doActions()" << std::endl;
|
|
#endif
|
|
|
|
time_t now = time(NULL);
|
|
|
|
while(mActions.size() > 0)
|
|
{
|
|
PeerAction action;
|
|
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
if (mActions.size() < 1)
|
|
{
|
|
break;
|
|
}
|
|
|
|
action = mActions.front();
|
|
mActions.pop_front();
|
|
}
|
|
|
|
switch(action.mType)
|
|
{
|
|
case PEERNET_ACTION_TYPE_CONNECT:
|
|
{
|
|
/* connect attempt */
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction. Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " mode: " << action.mMode;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
bool doConnectionRequest = false;
|
|
bool connectionReqFailed = false;
|
|
bool grabbedExclusivePort = false;
|
|
|
|
/* translate id into string for exclusive mode */
|
|
std::ostringstream idstr;
|
|
bdStdPrintNodeId(idstr, &(action.mDestId.id));
|
|
std::string pid = idstr.str();
|
|
|
|
|
|
// Parameters that will be used for the Connect Request.
|
|
struct sockaddr_in connAddr; // We zero this address. (DHT Layer handles most cases)
|
|
sockaddr_clear(&connAddr);
|
|
uint32_t connStart = 1; /* > 0 indicates GO (number indicates required startup delay) */
|
|
uint32_t connDelay = 0;
|
|
|
|
uint32_t failReason = CSB_UPDATE_MODE_UNAVAILABLE;
|
|
|
|
if ((action.mMode == BITDHT_CONNECT_MODE_DIRECT) ||
|
|
(action.mMode == BITDHT_CONNECT_MODE_RELAY))
|
|
{
|
|
doConnectionRequest = true;
|
|
}
|
|
else if (action.mMode == BITDHT_CONNECT_MODE_PROXY)
|
|
{
|
|
struct sockaddr_in extaddr;
|
|
uint8_t extStable = 0;
|
|
sockaddr_clear(&extaddr);
|
|
bool proxyPort = true;
|
|
bool exclusivePort = false;
|
|
bool connectOk = false;
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: Proxy... deciding which port to use.";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RSDHT_PEERTYPE_FRIEND);
|
|
if (dpd)
|
|
{
|
|
connectOk = true;
|
|
proxyPort = dpd->mConnectLogic.getProxyPortChoice();
|
|
if (proxyPort)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: Using ProxyPort. Checking ConnectLogic.NetState: ";
|
|
std::cerr << dpd->mConnectLogic.calcNetState(mNetMgr->getNetworkMode(),
|
|
mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode());
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
exclusivePort = (CSB_NETSTATE_EXCLUSIVENAT == dpd->mConnectLogic.calcNetState(
|
|
mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()));
|
|
|
|
if (exclusivePort)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: NetState indicates Exclusive Mode";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "PeerAction: Connect Proxy: ERROR Cannot find PeerStatus";
|
|
std::cerr << std::endl;
|
|
}
|
|
}
|
|
UdpStunner *stunner = mProxyStunner;
|
|
if (!proxyPort)
|
|
{
|
|
stunner = mDhtStunner;
|
|
}
|
|
|
|
|
|
|
|
if ((connectOk) && (stunner) && (stunner->externalAddr(extaddr, extStable)))
|
|
{
|
|
if (extStable)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: Proxy Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " is OkGo as we have Stable Own External Proxy Address";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* check if we require exclusive use of the proxy port */
|
|
if (exclusivePort)
|
|
{
|
|
int stun_age = mProxyStunner->grabExclusiveMode(pid);
|
|
if (stun_age > 0)
|
|
{
|
|
int delay = 0;
|
|
if (stun_age < MIN_DETERMINISTIC_SWITCH_PERIOD)
|
|
{
|
|
delay = MIN_DETERMINISTIC_SWITCH_PERIOD - stun_age;
|
|
}
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: Stunner has indicated a Delay of " << delay;
|
|
std::cerr << " to ensure a stable Port!";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* great we got it! */
|
|
connAddr = extaddr;
|
|
connDelay = delay;
|
|
doConnectionRequest = true;
|
|
grabbedExclusivePort = true;
|
|
}
|
|
else
|
|
{
|
|
/* failed to get exclusive mode - must wait */
|
|
connectionReqFailed = true;
|
|
failReason = CSB_UPDATE_RETRY_ATTEMPT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* stable and non-exclusive - go for it */
|
|
connAddr = extaddr;
|
|
connStart = 1;
|
|
doConnectionRequest = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: WARNING Proxy Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " is Discarded, as Own External Proxy Address is Not Stable!";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
connectionReqFailed = true;
|
|
if (exclusivePort)
|
|
{
|
|
failReason = CSB_UPDATE_RETRY_ATTEMPT;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: As Exclusive Mode, Port Will stabilise => RETRY";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
failReason = CSB_UPDATE_MODE_UNAVAILABLE;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: Not Exclusive Mode, => MODE UNAVAILABLE";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: ERROR Proxy Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " is Discarded, as Failed to get Own External Proxy Address.";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
connectionReqFailed = true;
|
|
failReason = CSB_UPDATE_RETRY_ATTEMPT;
|
|
}
|
|
}
|
|
|
|
if (doConnectionRequest)
|
|
{
|
|
if (mUdpBitDht->ConnectionRequest(&connAddr, &(action.mDestId.id), action.mMode, connDelay, connStart))
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " has gone ahead";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RSDHT_PEERTYPE_FRIEND);
|
|
if (dpd)
|
|
{
|
|
dpd->mPeerReqStatusMsg = "Connect Request";
|
|
dpd->mPeerReqState = RSDHT_PEERREQ_RUNNING;
|
|
dpd->mPeerReqMode = action.mMode;
|
|
dpd->mPeerReqTS = now;
|
|
|
|
if (grabbedExclusivePort)
|
|
{
|
|
dpd->mExclusiveProxyLock = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "PeerAction: Connect ERROR Cannot find PeerStatus";
|
|
std::cerr << std::endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
connectionReqFailed = true;
|
|
failReason = CSB_UPDATE_MODE_UNAVAILABLE;
|
|
}
|
|
}
|
|
|
|
if (connectionReqFailed)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction: Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " is Discarded, as Mode is Unavailable";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
//if (grabbedExclusivePort)
|
|
//{
|
|
// mProxyStunner->releaseExclusiveMode(pid,false);
|
|
//}
|
|
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RSDHT_PEERTYPE_FRIEND);
|
|
if (dpd)
|
|
{
|
|
dpd->mConnectLogic.updateCb(failReason);
|
|
|
|
dpd->mPeerReqStatusMsg = "Req Mode Unavailable";
|
|
dpd->mPeerReqState = RSDHT_PEERREQ_STOPPED;
|
|
dpd->mPeerReqMode = action.mMode;
|
|
dpd->mPeerReqTS = now;
|
|
|
|
if (grabbedExclusivePort)
|
|
{
|
|
ReleaseProxyExclusiveMode_locked(dpd, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "PeerAction: ERROR Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " has no Internal Dht Peer!";
|
|
std::cerr << std::endl;
|
|
|
|
if (grabbedExclusivePort)
|
|
{
|
|
std::cerr << "PeerAction: ERROR ERROR, we grabd Exclusive Port to do this, trying emergency release";
|
|
std::cerr << std::endl;
|
|
mProxyStunner->releaseExclusiveMode(pid,false);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case PEERNET_ACTION_TYPE_AUTHORISE:
|
|
{
|
|
/* connect attempt */
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction. Authorise Connection between: ";
|
|
bdStdPrintId(std::cerr, &(action.mSrcId));
|
|
std::cerr << " and ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " mode: " << action.mMode;
|
|
std::cerr << " delay/bandwidth: " << action.mDelayOrBandwidth;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
int delay = 0;
|
|
int bandwidth = 0;
|
|
if (action.mMode == BITDHT_CONNECT_MODE_RELAY)
|
|
{
|
|
bandwidth = action.mDelayOrBandwidth;
|
|
}
|
|
else
|
|
{
|
|
delay = action.mDelayOrBandwidth;
|
|
}
|
|
|
|
mUdpBitDht->ConnectionAuth(&(action.mSrcId), &(action.mProxyId), &(action.mDestId),
|
|
action.mMode, action.mPoint, bandwidth, delay, action.mAnswer);
|
|
|
|
// Only feedback to the gui if we are at END.
|
|
if (action.mPoint == BD_PROXY_CONNECTION_END_POINT)
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mSrcId.id), RSDHT_PEERTYPE_ANY);
|
|
if (dpd)
|
|
{
|
|
if (action.mAnswer)
|
|
{
|
|
dpd->mPeerCbMsg = "WE DENIED AUTH: ERROR : ";
|
|
dpd->mPeerCbMsg += decodeConnectionError(action.mAnswer);
|
|
}
|
|
else
|
|
{
|
|
dpd->mPeerCbMsg = "We AUTHED";
|
|
}
|
|
dpd->mPeerCbMode = action.mMode;
|
|
dpd->mPeerCbPoint = action.mPoint;
|
|
dpd->mPeerCbProxyId = action.mProxyId;
|
|
dpd->mPeerCbDestId = action.mSrcId;
|
|
dpd->mPeerCbTS = now;
|
|
}
|
|
// Not an error if AUTH_DENIED - cos we don't know them! (so won't be in peerList).
|
|
else if (action.mAnswer | BITDHT_CONNECT_ERROR_AUTH_DENIED)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction Authorise Connection ";
|
|
std::cerr << "Denied Unknown Peer";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "PeerAction Authorise Connection ";
|
|
std::cerr << "ERROR Unknown Peer & !DENIED ???";
|
|
std::cerr << std::endl;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PEERNET_ACTION_TYPE_START:
|
|
{
|
|
/* connect attempt */
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction. Start Connection between: ";
|
|
bdStdPrintId(std::cerr, &(action.mSrcId));
|
|
std::cerr << " and ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " mode: " << action.mMode;
|
|
std::cerr << " delay/bandwidth: " << action.mDelayOrBandwidth;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
initiateConnection(&(action.mSrcId), &(action.mProxyId), &(action.mDestId),
|
|
action.mMode, action.mPoint, action.mDelayOrBandwidth);
|
|
}
|
|
break;
|
|
|
|
case PEERNET_ACTION_TYPE_RESTARTREQ:
|
|
{
|
|
/* connect attempt */
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction. Restart Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " mode: " << action.mMode;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
struct sockaddr_in laddr;
|
|
sockaddr_clear(&laddr);
|
|
uint32_t start = 1;
|
|
uint32_t delay = 0;
|
|
|
|
mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, delay, start);
|
|
}
|
|
break;
|
|
|
|
case PEERNET_ACTION_TYPE_KILLREQ:
|
|
{
|
|
/* connect attempt */
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction. Kill Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " mode: " << action.mMode;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
struct sockaddr_in laddr;
|
|
sockaddr_clear(&laddr);
|
|
uint32_t start = 0;
|
|
uint32_t delay = 0;
|
|
|
|
mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, delay, start);
|
|
}
|
|
break;
|
|
|
|
case PEERNET_ACTION_TYPE_TCPATTEMPT:
|
|
{
|
|
/* connect attempt */
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction. TCP Connection Attempt to: ";
|
|
bdStdPrintId(std::cerr, &(action.mDestId));
|
|
std::cerr << " mode: " << action.mMode;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
std::string peerRsId;
|
|
bool foundPeerId = false;
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RSDHT_PEERTYPE_ANY);
|
|
if (dpd)
|
|
{
|
|
peerRsId = dpd->mRsId;
|
|
foundPeerId = true;
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "PeerAction. TCP Connection Attempt. DoingCallback for RsID: ";
|
|
std::cerr << peerRsId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "PeerAction. TCP Connection Attempt. ERROR unknown peer";
|
|
std::cerr << std::endl;
|
|
}
|
|
}
|
|
|
|
if (foundPeerId)
|
|
{
|
|
ConnectCalloutTCPAttempt(peerRsId, action.mDestId.addr);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************** Connection Logic ***************************/
|
|
|
|
/* Proxies!.
|
|
*
|
|
* We can allow all PROXY connections, as it is just a couple of messages,
|
|
* however, we should be smart about how many RELAY connections are allowed.
|
|
*
|
|
* e.g. Allow 20 Relay connections.
|
|
* 15 for friends, 5 for randoms.
|
|
*
|
|
* Can also validate addresses with own secure connections.
|
|
*/
|
|
|
|
int p3BitDht::checkProxyAllowed(const bdId *srcId, const bdId *destId, int mode, uint32_t &bandwidth)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::checkProxyAllowed()";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
// Dont think that a mutex is required here! But might be so just lock to ensure that it is possible.
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
}
|
|
|
|
if (mode == BITDHT_CONNECT_MODE_PROXY)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::checkProxyAllowed() Allowing all PROXY connections, OKAY";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
bandwidth = 0; // unlimited as p2p.
|
|
return 1;
|
|
//return CONNECTION_OKAY;
|
|
}
|
|
|
|
if (mode != BITDHT_CONNECT_MODE_RELAY)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::checkProxyAllowed() unknown Connect Mode DENIED";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/* will install the Relay Here... so that we reserve the Relay Space for later.
|
|
* decide on relay bandwidth limitation as well
|
|
*/
|
|
if (RelayHandler_InstallRelayConnection(srcId, destId, mode, bandwidth))
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::checkProxyAllowed() Successfully added Relay, Connection OKAY";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return 1;
|
|
// CONNECT_OKAY.
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::checkProxyAllowed() Failed to install Relay, Connection DENIED";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return 0;
|
|
//return CONNECT_MODE_OVERLOADED;
|
|
}
|
|
|
|
return 0;
|
|
//return CONNECT_MODE_NOTAVAILABLE;
|
|
//return CONNECT_MODE_OVERLOADED;
|
|
}
|
|
|
|
|
|
int p3BitDht::checkConnectionAllowed(const bdId *peerId, int mode)
|
|
{
|
|
(void) mode;
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::checkConnectionAllowed() to: ";
|
|
bdStdPrintId(std::cerr,peerId);
|
|
std::cerr << " mode: " << mode;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
time_t now = time(NULL);
|
|
|
|
/* check if they are in our friend list */
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId->id), RSDHT_PEERTYPE_FRIEND);
|
|
if (!dpd)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::checkConnectionAllowed() Peer Not Friend, DENIED";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* store as failed connection attempt */
|
|
std::map<bdNodeId, DhtPeerDetails>::iterator it;
|
|
it = mFailedPeers.find(peerId->id);
|
|
if (it == mFailedPeers.end())
|
|
{
|
|
mFailedPeers[peerId->id] = DhtPeerDetails();
|
|
it = mFailedPeers.find(peerId->id);
|
|
}
|
|
|
|
/* flag as failed */
|
|
it->second.mDhtId = *peerId;
|
|
it->second.mDhtState = RSDHT_PEERDHT_NOT_ACTIVE;
|
|
it->second.mDhtUpdateTS = now;
|
|
|
|
it->second.mPeerType = RSDHT_PEERTYPE_OTHER;
|
|
it->second.mPeerCbMsg = "Denied Non-Friend";
|
|
|
|
it->second.mPeerReqStatusMsg = "Denied Non-Friend";
|
|
it->second.mPeerReqState = RSDHT_PEERREQ_STOPPED;
|
|
it->second.mPeerReqTS = now;
|
|
it->second.mPeerReqMode = 0;
|
|
//it->second.mPeerProxyId;
|
|
it->second.mPeerReqTS = now;
|
|
|
|
it->second.mPeerCbMsg = "Denied Non-Friend";
|
|
|
|
it->second.mPeerConnectMsg = "Denied Non-Friend";
|
|
it->second.mPeerConnectState = RSDHT_PEERCONN_DISCONNECTED;
|
|
|
|
|
|
return 0;
|
|
//return NOT_FRIEND;
|
|
}
|
|
|
|
/* are a friend */
|
|
|
|
if (dpd->mPeerConnectState == RSDHT_PEERCONN_CONNECTED)
|
|
{
|
|
std::cerr << "p3BitDht::checkConnectionAllowed() ERROR Peer Already Connected, DENIED";
|
|
std::cerr << std::endl;
|
|
|
|
// STATUS UPDATE DONE IN ACTION.
|
|
//it->second.mPeerStatusMsg = "2nd Connection Attempt!";
|
|
//it->second.mPeerUpdateTS = now;
|
|
return 0;
|
|
//return ALREADY_CONNECTED;
|
|
}
|
|
|
|
return 1;
|
|
//return CONNECTION_OKAY;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* So initiateConnection has to call out to other bits of RS.
|
|
* critical information is:
|
|
* Peer RsId, Peer Address, Connect Mode (includes Proxy/OrNot).
|
|
|
|
*
|
|
* What do we need: ACTIVE / PASSIVE / UNSPEC
|
|
* + Min Delay Time,
|
|
*/
|
|
|
|
|
|
void p3BitDht::ConnectCalloutTCPAttempt(const std::string &peerId, struct sockaddr_in raddr)
|
|
{
|
|
struct sockaddr_in proxyaddr;
|
|
struct sockaddr_in srcaddr;
|
|
|
|
sockaddr_clear(&proxyaddr);
|
|
sockaddr_clear(&srcaddr);
|
|
|
|
uint32_t source = RS_CB_DHT;
|
|
uint32_t connectFlags = RS_CB_FLAG_ORDER_UNSPEC | RS_CB_FLAG_MODE_TCP;
|
|
uint32_t delay = 0;
|
|
uint32_t bandwidth = 0;
|
|
|
|
mConnCb->peerConnectRequest(peerId, raddr, proxyaddr, srcaddr, source, connectFlags, delay, bandwidth);
|
|
}
|
|
|
|
|
|
void p3BitDht::ConnectCalloutDirectOrProxy(const std::string &peerId, struct sockaddr_in raddr, uint32_t connectFlags, uint32_t delay)
|
|
{
|
|
struct sockaddr_in proxyaddr;
|
|
struct sockaddr_in srcaddr;
|
|
|
|
sockaddr_clear(&proxyaddr);
|
|
sockaddr_clear(&srcaddr);
|
|
|
|
uint32_t source = RS_CB_DHT;
|
|
uint32_t bandwidth = 0;
|
|
|
|
mConnCb->peerConnectRequest(peerId, raddr, proxyaddr, srcaddr, source, connectFlags, delay, bandwidth);
|
|
}
|
|
|
|
void p3BitDht::ConnectCalloutRelay(const std::string &peerId,
|
|
struct sockaddr_in srcaddr, struct sockaddr_in proxyaddr, struct sockaddr_in destaddr,
|
|
uint32_t connectFlags, uint32_t bandwidth)
|
|
{
|
|
uint32_t source = RS_CB_DHT;
|
|
uint32_t delay = 0;
|
|
|
|
mConnCb->peerConnectRequest(peerId, destaddr, proxyaddr, srcaddr, source, connectFlags, delay, bandwidth);
|
|
}
|
|
|
|
|
|
|
|
|
|
//virtual void peerConnectRequest(std::string id, struct sockaddr_in raddr,
|
|
// struct sockaddr_in proxyaddr, struct sockaddr_in srcaddr,
|
|
// uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth) = 0;
|
|
|
|
|
|
void p3BitDht::initiateConnection(const bdId *srcId, const bdId *proxyId, const bdId *destId,
|
|
uint32_t mode, uint32_t loc, uint32_t delayOrBandwidth)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
#endif
|
|
std::cerr << "p3BitDht::initiateConnection()";
|
|
std::cerr << std::endl;
|
|
std::cerr << "\t srcId: ";
|
|
bdStdPrintId(std::cerr, srcId);
|
|
std::cerr << std::endl;
|
|
|
|
std::cerr << "\t proxyId: ";
|
|
bdStdPrintId(std::cerr, proxyId);
|
|
std::cerr << std::endl;
|
|
|
|
std::cerr << "\t destId: ";
|
|
bdStdPrintId(std::cerr, destId);
|
|
std::cerr << std::endl;
|
|
|
|
std::cerr << "\t Mode: " << mode << " loc: " << loc;
|
|
std::cerr << std::endl;
|
|
std::cerr << "\t DelayOrBandwidth: " << delayOrBandwidth;
|
|
std::cerr << std::endl;
|
|
|
|
bdId peerConnectId;
|
|
|
|
uint32_t connectFlags = 0;
|
|
|
|
uint32_t delay = 0;
|
|
uint32_t bandwidth = 0;
|
|
|
|
/* determine who the actual destination is.
|
|
* as we always specify the remote address, this is all we need.
|
|
*/
|
|
if (loc == BD_PROXY_CONNECTION_START_POINT)
|
|
{
|
|
peerConnectId = *destId;
|
|
/* lowest is active */
|
|
if (srcId < destId)
|
|
{
|
|
connectFlags |= RS_CB_FLAG_ORDER_ACTIVE;
|
|
}
|
|
else
|
|
{
|
|
connectFlags |= RS_CB_FLAG_ORDER_PASSIVE;
|
|
}
|
|
}
|
|
else if (loc == BD_PROXY_CONNECTION_END_POINT)
|
|
{
|
|
peerConnectId = *srcId;
|
|
/* lowest is active (we are now dest - in this case) */
|
|
if (destId < srcId)
|
|
{
|
|
connectFlags |= RS_CB_FLAG_ORDER_ACTIVE;
|
|
}
|
|
else
|
|
{
|
|
connectFlags |= RS_CB_FLAG_ORDER_PASSIVE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "p3BitDht::initiateConnection() ERROR, NOT either START or END";
|
|
std::cerr << std::endl;
|
|
/* ERROR */
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::initiateConnection() Connecting to ";
|
|
bdStdPrintId(std::cerr, &peerConnectId);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
uint32_t touConnectMode = 0;
|
|
std::string rsId;
|
|
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerConnectId.id), RSDHT_PEERTYPE_FRIEND);
|
|
/* grab a socket */
|
|
if (!dpd)
|
|
{
|
|
std::cerr << "p3BitDht::initiateConnection() ERROR Peer not found";
|
|
std::cerr << std::endl;
|
|
return;
|
|
}
|
|
|
|
if (dpd->mPeerConnectState != RSDHT_PEERCONN_DISCONNECTED)
|
|
{
|
|
std::cerr << "p3BitDht::initiateConnection() ERROR Peer is not Disconnected";
|
|
std::cerr << std::endl;
|
|
return;
|
|
}
|
|
|
|
rsId = dpd->mRsId;
|
|
|
|
/* start the connection */
|
|
/* These Socket Modes must match the TOU Stack - or it breaks. */
|
|
switch(mode)
|
|
{
|
|
default:
|
|
case BITDHT_CONNECT_MODE_DIRECT:
|
|
touConnectMode = RSDHT_TOU_MODE_DIRECT;
|
|
connectFlags |= RS_CB_FLAG_MODE_UDP_DIRECT;
|
|
delay = delayOrBandwidth;
|
|
break;
|
|
|
|
case BITDHT_CONNECT_MODE_PROXY:
|
|
{
|
|
bool useProxyPort = dpd->mConnectLogic.getProxyPortChoice();
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::initiateConnection() Peer Mode Proxy... deciding which port to use.";
|
|
std::cerr << " UseProxyPort? " << useProxyPort;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
delay = delayOrBandwidth;
|
|
if (useProxyPort)
|
|
{
|
|
touConnectMode = RSDHT_TOU_MODE_PROXY;
|
|
connectFlags |= RS_CB_FLAG_MODE_UDP_PROXY;
|
|
}
|
|
else
|
|
{
|
|
touConnectMode = RSDHT_TOU_MODE_DIRECT;
|
|
connectFlags |= RS_CB_FLAG_MODE_UDP_DIRECT;
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case BITDHT_CONNECT_MODE_RELAY:
|
|
touConnectMode = RSDHT_TOU_MODE_RELAY;
|
|
connectFlags |= RS_CB_FLAG_MODE_UDP_RELAY;
|
|
bandwidth = delayOrBandwidth;
|
|
break;
|
|
}
|
|
|
|
|
|
dpd->mPeerConnectProxyId = *proxyId;
|
|
dpd->mPeerConnectPeerId = peerConnectId;
|
|
|
|
|
|
/* store results in Status */
|
|
dpd->mPeerConnectMsg = "UDP started";
|
|
dpd->mPeerConnectState = RSDHT_PEERCONN_UDP_STARTED;
|
|
dpd->mPeerConnectUdpTS = time(NULL);
|
|
dpd->mPeerConnectMode = mode;
|
|
dpd->mPeerConnectPoint = loc;
|
|
}
|
|
|
|
/* finally we call out to start the connection (Outside of Mutex) */
|
|
|
|
if ((mode == BITDHT_CONNECT_MODE_DIRECT) || (mode == BITDHT_CONNECT_MODE_PROXY))
|
|
{
|
|
ConnectCalloutDirectOrProxy(rsId, peerConnectId.addr, connectFlags, delay);
|
|
}
|
|
else if (mode == BITDHT_CONNECT_MODE_RELAY)
|
|
{
|
|
if (loc == BD_PROXY_CONNECTION_START_POINT)
|
|
{
|
|
ConnectCalloutRelay(rsId, srcId->addr, proxyId->addr, destId->addr, connectFlags, bandwidth);
|
|
}
|
|
else // END_POINT
|
|
{
|
|
/* reverse order connection call */
|
|
ConnectCalloutRelay(rsId, destId->addr, proxyId->addr, srcId->addr, connectFlags, bandwidth);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
int p3BitDht::installRelayConnection(const bdId *srcId, const bdId *destId, uint32_t &bandwidth)
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
/* work out if either srcId or DestId is a friend */
|
|
int relayClass = UDP_RELAY_CLASS_GENERAL;
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::ostringstream str;
|
|
bdStdPrintNodeId(str, &(srcId->id));
|
|
std::string strId1 = str.str();
|
|
|
|
str.clear();
|
|
bdStdPrintNodeId(str, &(destId->id));
|
|
std::string strId2 = str.str();
|
|
#endif
|
|
|
|
/* grab a socket */
|
|
DhtPeerDetails *dpd_src = findInternalDhtPeer_locked(&(srcId->id), RSDHT_PEERTYPE_ANY);
|
|
DhtPeerDetails *dpd_dest = findInternalDhtPeer_locked(&(destId->id), RSDHT_PEERTYPE_ANY);
|
|
|
|
if ((dpd_src) && (dpd_src->mPeerType == RSDHT_PEERTYPE_FRIEND))
|
|
{
|
|
relayClass = UDP_RELAY_CLASS_FRIENDS;
|
|
}
|
|
else if ((dpd_dest) && (dpd_dest->mPeerType == RSDHT_PEERTYPE_FRIEND))
|
|
{
|
|
relayClass = UDP_RELAY_CLASS_FRIENDS;
|
|
}
|
|
else if ((dpd_src) && (dpd_src->mPeerType == RSDHT_PEERTYPE_FOF))
|
|
{
|
|
relayClass = UDP_RELAY_CLASS_FOF;
|
|
}
|
|
else if ((dpd_dest) && (dpd_dest->mPeerType == RSDHT_PEERTYPE_FOF))
|
|
{
|
|
relayClass = UDP_RELAY_CLASS_FOF;
|
|
}
|
|
else
|
|
{
|
|
relayClass = UDP_RELAY_CLASS_GENERAL;
|
|
}
|
|
|
|
/* will install the Relay Here... so that we reserve the Relay Space for later. */
|
|
UdpRelayAddrSet relayAddrs(&(srcId->addr), &(destId->addr));
|
|
if (mRelay->addUdpRelay(&relayAddrs, relayClass, bandwidth))
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::installRelayConnection() Successfully added Relay, Connection OKAY";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return 1;
|
|
// CONNECT_OKAY.
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::installRelayConnection() Failed to install Relay, Connection DENIED";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return 0;
|
|
//return CONNECT_MODE_OVERLOADED;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int p3BitDht::removeRelayConnection(const bdId *srcId, const bdId *destId)
|
|
{
|
|
//RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
|
|
UdpRelayAddrSet relayAddrs(&(srcId->addr), &(destId->addr));
|
|
if (mRelay->removeUdpRelay(&relayAddrs))
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::removeRelayConnection() Successfully removed Relay";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "p3BitDht::removeRelayConnection() ERROR Failed to remove Relay";
|
|
std::cerr << std::endl;
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/***************************************************** UDP Connections *****************************/
|
|
|
|
|
|
void p3BitDht::monitorConnections()
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
time_t now = time(NULL);
|
|
|
|
std::map<bdNodeId, DhtPeerDetails>::iterator it;
|
|
|
|
for(it = mPeers.begin(); it != mPeers.end(); it++)
|
|
{
|
|
/* ignore ones which aren't friends */
|
|
if (it->second.mPeerType != RSDHT_PEERTYPE_FRIEND)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (it->second.mPeerConnectState == RSDHT_PEERCONN_UDP_STARTED)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::monitorConnections() Connection in progress to: ";
|
|
|
|
bdStdPrintNodeId(std::cerr, &(it->second.mDhtId.id));
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (now - it->second.mPeerConnectUdpTS > PEERNET_CONNECT_TIMEOUT)
|
|
{
|
|
/* This CAN happen ;( */
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::monitorConnections() WARNING InProgress Connection Failed: ";
|
|
bdStdPrintNodeId(std::cerr, &(it->second.mDhtId.id));
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
UdpConnectionFailed_locked(&(it->second));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void p3BitDht::Feedback_Connected(std::string pid)
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
DhtPeerDetails *dpd = findInternalRsPeer_locked(pid);
|
|
|
|
if (!dpd)
|
|
{
|
|
/* ERROR */
|
|
std::cerr << "p3BitDht::Feedback_Connected() ERROR peer not found: " << pid;
|
|
std::cerr << std::endl;
|
|
|
|
return;
|
|
}
|
|
|
|
/* sanity checking */
|
|
if (dpd->mPeerConnectState != RSDHT_PEERCONN_UDP_STARTED)
|
|
{
|
|
/* ERROR */
|
|
std::cerr << "p3BitDht::Feedback_Connected() ERROR not in UDP_STARTED mode for: ";
|
|
bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id));
|
|
std::cerr << std::endl;
|
|
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::monitorConnections() InProgress Connection Now Active: ";
|
|
bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id));
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* switch state! */
|
|
dpd->mPeerConnectState = RSDHT_PEERCONN_CONNECTED;
|
|
dpd->mPeerConnectTS = time(NULL);
|
|
|
|
dpd->mConnectLogic.updateCb(CSB_UPDATE_CONNECTED);
|
|
|
|
std::ostringstream msg;
|
|
msg << "Connected in " << dpd->mPeerConnectTS - dpd->mPeerConnectUdpTS;
|
|
msg << " secs";
|
|
dpd->mPeerConnectMsg = msg.str();
|
|
|
|
// Remove the Connection Request.
|
|
if (dpd->mPeerReqState == RSDHT_PEERREQ_RUNNING)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::monitorConnections() Request Active, Stopping Request";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* Push Back PeerAction */
|
|
PeerAction ca;
|
|
ca.mType = PEERNET_ACTION_TYPE_KILLREQ;
|
|
ca.mMode = dpd->mPeerConnectMode;
|
|
//ca.mProxyId = *proxyId;
|
|
//ca.mSrcId = *srcId;
|
|
ca.mDestId = dpd->mPeerConnectPeerId;
|
|
//ca.mPoint = point;
|
|
ca.mAnswer = BITDHT_CONNECT_ERROR_NONE;
|
|
|
|
mActions.push_back(ca);
|
|
|
|
// What the Action should do...
|
|
//struct sockaddr_in tmpaddr;
|
|
//bdsockaddr_clear(&tmpaddr);
|
|
//int start = 0;
|
|
//mUdpBitDht->ConnectionRequest(&tmpaddr, &(it->second.mPeerConnectPeerId.id), it->second.mPeerConnectMode, start);
|
|
}
|
|
// only an error if we initiated the connection.
|
|
else if (dpd->mPeerConnectPoint == BD_PROXY_CONNECTION_START_POINT)
|
|
{
|
|
std::cerr << "p3BitDht::monitorConnections() ERROR Request not active, can't stop";
|
|
std::cerr << std::endl;
|
|
}
|
|
|
|
ReleaseProxyExclusiveMode_locked(dpd, true);
|
|
}
|
|
|
|
void p3BitDht::Feedback_ConnectionFailed(std::string pid)
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
DhtPeerDetails *dpd = findInternalRsPeer_locked(pid);
|
|
|
|
if (!dpd)
|
|
{
|
|
/* ERROR */
|
|
std::cerr << "p3BitDht::Feedback_Connected() ERROR peer not found: " << pid;
|
|
std::cerr << std::endl;
|
|
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::Feedback_ConnectionFailed() UDP Connection Failed: ";
|
|
bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id));
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return UdpConnectionFailed_locked(dpd);
|
|
}
|
|
|
|
void p3BitDht::Feedback_ConnectionClosed(std::string pid)
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/
|
|
DhtPeerDetails *dpd = findInternalRsPeer_locked(pid);
|
|
|
|
if (!dpd)
|
|
{
|
|
/* ERROR */
|
|
std::cerr << "p3BitDht::Feedback_Connected() ERROR peer not found: " << pid;
|
|
std::cerr << std::endl;
|
|
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::Feedback_ConnectionClosed() Active Connection Closed: ";
|
|
bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id));
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return UdpConnectionFailed_locked(dpd);
|
|
}
|
|
|
|
|
|
void p3BitDht::UdpConnectionFailed_locked(DhtPeerDetails *dpd)
|
|
{
|
|
if (dpd->mPeerConnectState == RSDHT_PEERCONN_UDP_STARTED)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::UdpConnectionFailed_locked() UDP Connection Failed: ";
|
|
bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id));
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* shut it down */
|
|
|
|
/* ONLY need to update ConnectLogic - if it was our Attempt Running */
|
|
if (dpd->mPeerReqState == RSDHT_PEERREQ_RUNNING)
|
|
{
|
|
dpd->mConnectLogic.updateCb(CSB_UPDATE_FAILED_ATTEMPT);
|
|
}
|
|
dpd->mPeerConnectState = RSDHT_PEERCONN_DISCONNECTED;
|
|
dpd->mPeerConnectMsg = "UDP Failed";
|
|
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::UdpConnectionFailed_locked() Active Connection Closed: ";
|
|
bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id));
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
dpd->mConnectLogic.updateCb(CSB_UPDATE_DISCONNECTED);
|
|
|
|
dpd->mPeerConnectState = RSDHT_PEERCONN_DISCONNECTED;
|
|
dpd->mPeerConnectClosedTS = time(NULL);
|
|
std::ostringstream msg;
|
|
msg << "Closed, Alive for: " << dpd->mPeerConnectClosedTS - dpd->mPeerConnectTS;
|
|
msg << " secs";
|
|
dpd->mPeerConnectMsg = msg.str();
|
|
}
|
|
|
|
|
|
|
|
if (dpd->mPeerReqState == RSDHT_PEERREQ_RUNNING)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::UdpConnectionFailed_locked() ";
|
|
std::cerr << "Request Active (Paused)... Killing for next Attempt";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* Push Back PeerAction */
|
|
PeerAction ca;
|
|
ca.mType = PEERNET_ACTION_TYPE_KILLREQ;
|
|
ca.mMode = dpd->mPeerConnectMode;
|
|
//ca.mProxyId = *proxyId;
|
|
//ca.mSrcId = *srcId;
|
|
ca.mDestId = dpd->mPeerConnectPeerId;
|
|
//ca.mPoint = point;
|
|
ca.mAnswer = BITDHT_CONNECT_ERROR_NONE;
|
|
|
|
mActions.push_back(ca);
|
|
}
|
|
// only an error if we initiated the connection.
|
|
else if (dpd->mPeerConnectPoint == BD_PROXY_CONNECTION_START_POINT)
|
|
{
|
|
std::cerr << "p3BitDht::UdpConnectionFailed_locked() ";
|
|
std::cerr << "ERROR Request not active, can't stop";
|
|
std::cerr << std::endl;
|
|
}
|
|
|
|
ReleaseProxyExclusiveMode_locked(dpd, true);
|
|
}
|
|
|
|
|
|
|
|
void p3BitDht::ReleaseProxyExclusiveMode_locked(DhtPeerDetails *dpd, bool addrChgLikely)
|
|
{
|
|
#ifdef DEBUG_BITDHT_COMMON
|
|
#endif
|
|
std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked()";
|
|
bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id));
|
|
std::cerr << std::endl;
|
|
|
|
/* translate id into string for exclusive mode */
|
|
std::ostringstream idstr;
|
|
bdStdPrintNodeId(idstr, &(dpd->mDhtId.id));
|
|
std::string pid = idstr.str();
|
|
|
|
|
|
if (dpd->mExclusiveProxyLock)
|
|
{
|
|
if (mProxyStunner->releaseExclusiveMode(pid, addrChgLikely))
|
|
{
|
|
dpd->mExclusiveProxyLock = false;
|
|
|
|
#ifdef DEBUG_PEERNET
|
|
#endif
|
|
std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() Lock released by Connection to peer: ";
|
|
bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id));
|
|
std::cerr << std::endl;
|
|
}
|
|
else
|
|
{
|
|
dpd->mExclusiveProxyLock = false;
|
|
|
|
std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() ERROR ProxyStunner is not Locked";
|
|
bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id));
|
|
std::cerr << std::endl;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_BITDHT_COMMON
|
|
#endif
|
|
std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() Don't Have a Lock";
|
|
std::cerr << std::endl;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void p3BitDht::ConnectionFeedback(std::string pid, int mode)
|
|
{
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::ConnectionFeedback() peer: " << pid;
|
|
std::cerr << " mode: " << mode;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
switch(mode)
|
|
{
|
|
case NETMGR_DHT_FEEDBACK_CONNECTED:
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::ConnectionFeedback() HAVE CONNECTED (tcp?/udp) to peer: " << pid;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
Feedback_Connected(pid);
|
|
break;
|
|
|
|
case NETMGR_DHT_FEEDBACK_CONN_FAILED:
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::ConnectionFeedback() UDP CONNECTION FAILED to peer: " << pid;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
Feedback_ConnectionFailed(pid);
|
|
break;
|
|
|
|
case NETMGR_DHT_FEEDBACK_CONN_CLOSED:
|
|
#ifdef DEBUG_PEERNET
|
|
std::cerr << "p3BitDht::ConnectionFeedback() CONNECTION (tcp?/udp) CLOSED to peer: " << pid;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
Feedback_ConnectionClosed(pid);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/***** Check for a RelayHandler... and call its functions preferentially */
|
|
|
|
int p3BitDht::RelayHandler_LogFailedProxyAttempt(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t errcode)
|
|
{
|
|
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********* LOCKED *********/
|
|
|
|
if ((mRelayHandler) && (mRelayHandler->mLogFailedConnection))
|
|
{
|
|
return mRelayHandler->mLogFailedConnection(srcId, destId, mode, errcode);
|
|
}
|
|
}
|
|
|
|
/* NO standard handler */
|
|
return 0;
|
|
}
|
|
|
|
|
|
int p3BitDht::RelayHandler_InstallRelayConnection(const bdId *srcId, const bdId *destId,
|
|
uint32_t mode, uint32_t &bandwidth)
|
|
{
|
|
|
|
{
|
|
RsStackMutex stack(dhtMtx); /********* LOCKED *********/
|
|
|
|
if ((mRelayHandler) && (mRelayHandler->mInstallRelay))
|
|
{
|
|
return mRelayHandler->mInstallRelay(srcId, destId, mode, bandwidth);
|
|
}
|
|
}
|
|
|
|
/* standard handler */
|
|
return installRelayConnection(srcId, destId, bandwidth);
|
|
}
|
|
|
|
|
|
|
|
|
|
|