Completed basics of the new p3bitdht system.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-netupgrade@4418 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2011-07-10 00:39:15 +00:00
parent 21145a29bb
commit 6eb27c9a1a
8 changed files with 3262 additions and 415 deletions

View File

@ -0,0 +1,777 @@
/* a connect state box */
#include "connectstatebox.h"
#include "netstatebox.h"
#include <iostream>
#include <sstream>
#define FAILED_WAIT_TIME (300) //(1800) // 30 minutes.
#define DIRECT_WAIT_TIME (60) // 1 minutes.
#define PROXY_WAIT_TIME (60) // 1 minutes.
#define RELAY_WAIT_TIME (60) // 1 minutes.
#define REVERSE_WAIT_TIME (300) // 5 minutes.
#define MAX_DIRECT_ATTEMPTS (3)
#define MAX_PROXY_ATTEMPTS (3)
#define MAX_RELAY_ATTEMPTS (3)
PeerConnectStateBox::PeerConnectStateBox()
{
//mPeerId = id;
mState = CSB_START;
mNetState = CSB_NETSTATE_UNKNOWN;
mStateTS = 0;
mNoAttempts = 0;
}
std::string NetStateAsString(uint32_t netstate)
{
std::string str;
switch(netstate)
{
case CSB_NETSTATE_FORWARD:
str = "Forwarded";
break;
case CSB_NETSTATE_STABLENAT:
str = "StableNat";
break;
case CSB_NETSTATE_FIREWALLED:
str = "Firewalled";
break;
default:
str = "Unknown NetState";
break;
}
return str;
}
std::string StateAsString(uint32_t state)
{
std::string str;
switch(state)
{
case CSB_START:
str = "Start";
break;
case CSB_DIRECT_ATTEMPT:
str = "Direct Attempt";
break;
case CSB_DIRECT_WAIT:
str = "Direct Wait";
break;
case CSB_PROXY_ATTEMPT:
str = "Proxy Attempt:";
break;
case CSB_PROXY_WAIT:
str = "Proxy Wait:";
break;
case CSB_RELAY_ATTEMPT:
str = "Relay Attempt:";
break;
case CSB_RELAY_WAIT:
str = "Relay Wait:";
break;
case CSB_REVERSE_WAIT:
str = "Reverse Wait:";
break;
case CSB_FAILED_WAIT:
str = "Failed Wait:";
break;
case CSB_CONNECTED:
str = "Connected:";
break;
default:
str = "Unknown State";
break;
}
return str;
}
std::string UpdateAsString(uint32_t update)
{
std::string str;
switch(update)
{
case CSB_UPDATE_NONE:
str = "none";
break;
case CSB_UPDATE_CONNECTED:
str = "Connected";
break;
case CSB_UPDATE_DISCONNECTED:
str = "Disconnected";
break;
case CSB_UPDATE_AUTH_DENIED:
str = "Auth Denied";
break;
case CSB_UPDATE_FAILED_ATTEMPT:
str = "Failed Attempt:";
break;
case CSB_UPDATE_MODE_UNAVAILABLE:
str = "Mode Unavailable:";
break;
default:
str = "Unknown Update";
break;
}
return str;
}
void PeerConnectStateBox::errorMsg(std::ostream &out, std::string msg, uint32_t updateParam)
{
out << "PeerConnectStateBox::ERROR " << msg;
out << " NetState: " << NetStateAsString(mNetState);
out << " State: " << StateAsString(mState);
out << " Update: " << UpdateAsString(updateParam);
out << " for peer: " << mPeerId;
out << std::endl;
}
void PeerConnectStateBox::stateMsg(std::ostream &out, std::string msg, uint32_t updateParam)
{
out << "PeerConnectStateBox::MSG " << msg;
out << " NetState: " << NetStateAsString(mNetState);
out << " State: " << StateAsString(mState);
out << " Update: " << UpdateAsString(updateParam);
out << " for peer: " << mPeerId;
out << std::endl;
}
std::string PeerConnectStateBox::connectState()
{
std::string str = StateAsString(mState);
std::ostringstream out;
time_t now = time(NULL);
out << str << "(" << mNoAttempts << ") for " << now - mStateTS << " secs";
return out.str();
}
uint32_t convertNetStateToInternal(uint32_t netmode, uint32_t nattype)
{
uint32_t connNet = CSB_NETSTATE_UNKNOWN;
if (netmode == PNSB_NETWORK_EXTERNALIP)
{
connNet = CSB_NETSTATE_FORWARD;
}
else if (netmode == PNSB_NETWORK_BEHINDNAT)
{
if ((nattype == PNSB_NATTYPE_RESTRICTED_CONE) ||
(nattype == PNSB_NATTYPE_FULL_CONE))
{
connNet = CSB_NETSTATE_STABLENAT;
}
else
{
connNet = CSB_NETSTATE_FIREWALLED;
}
}
return connNet;
}
bool shouldUseProxyPortInternal(uint32_t netstate)
{
if (netstate == CSB_NETSTATE_FORWARD)
{
return false;
}
return true;
}
bool PeerConnectStateBox::shouldUseProxyPort(uint32_t netmode, uint32_t nattype)
{
uint32_t netstate = convertNetStateToInternal(netmode, nattype);
return shouldUseProxyPortInternal(netstate);
}
uint32_t PeerConnectStateBox::connectCb(uint32_t cbtype, uint32_t netmode, uint32_t nattype)
{
uint32_t netstate = convertNetStateToInternal(netmode, nattype);
std::cerr << "PeerConnectStateBox::connectCb(";
if (cbtype == CSB_CONNECT_DIRECT)
{
std::cerr << "DIRECT";
}
else
{
std::cerr << "UNREACHABLE";
}
std::cerr << "," << NetStateAsString(netstate) << ")";
std::cerr << std::endl;
if (netstate != mNetState)
{
std::cerr << "PeerConnectStateBox::connectCb() WARNING Changing NetState from: ";
std::cerr << " from: " << NetStateAsString(mNetState);
std::cerr << " to: " << NetStateAsString(netstate);
std::cerr << " for peer: " << mPeerId;
std::cerr << std::endl;
mNetState = netstate;
}
if (cbtype == CSB_CONNECT_DIRECT)
{
return connectCb_direct();
}
else
{
return connectCb_unreachable();
}
}
uint32_t PeerConnectStateBox::connectCb_direct()
{
uint32_t retval = 0;
time_t now = time(NULL);
switch(mState)
{
case CSB_DIRECT_ATTEMPT:
{
errorMsg(std::cerr, "mState == DIRECT_ATTEMPT", 0);
retval = CSB_ACTION_WAIT;
}
break;
case CSB_PROXY_ATTEMPT:
{
errorMsg(std::cerr, "mState == PROXY_ATTEMPT", 0);
retval = CSB_ACTION_WAIT;
}
break;
case CSB_RELAY_ATTEMPT:
{
errorMsg(std::cerr, "mState == RELAY_ATTEMPT", 0);
retval = CSB_ACTION_WAIT;
}
break;
case CSB_FAILED_WAIT:
{
/* if too soon */
if (now - mStateTS < FAILED_WAIT_TIME)
{
/* same state */
retval = CSB_ACTION_WAIT;
break;
}
} /* FALLTHROUGH TO START CASE */
default:
case CSB_REVERSE_WAIT:
case CSB_PROXY_WAIT:
case CSB_RELAY_WAIT:
{
if (mState != CSB_FAILED_WAIT)
{
/* ERROR */
errorMsg(std::cerr, "mState != FAILED_WAIT", 0);
}
} /* FALLTHROUGH TO START CASE */
case CSB_START:
{
/* starting up the connection */
mState = CSB_DIRECT_ATTEMPT;
retval = CSB_ACTION_DIRECT_CONN | CSB_ACTION_DHT_PORT;
mStateTS = now;
mNoAttempts = 0;
}
break;
case CSB_DIRECT_WAIT:
{
/* if too soon */
if (now - mStateTS < DIRECT_WAIT_TIME)
{
/* same state */
retval = CSB_ACTION_WAIT;
}
else if (mNoAttempts >= MAX_DIRECT_ATTEMPTS) /* if too many attempts */
{
/* switch to RELAY attempt */
mState = CSB_FAILED_WAIT;
retval = CSB_ACTION_WAIT;
mStateTS = now;
mNoAttempts = 0;
}
else
{
/* try again */
mState = CSB_DIRECT_ATTEMPT;
retval = CSB_ACTION_DIRECT_CONN | CSB_ACTION_DHT_PORT;
mStateTS = now;
mNoAttempts++;
}
}
break;
case CSB_CONNECTED:
{
retval = CSB_ACTION_WAIT;
}
break;
}
return retval;
}
uint32_t PeerConnectStateBox::connectCb_unreachable()
{
uint32_t retval = 0;
uint32_t proxyPortMode = CSB_ACTION_PROXY_PORT;
if (!shouldUseProxyPortInternal(mNetState))
{
proxyPortMode = CSB_ACTION_DHT_PORT;
}
time_t now = time(NULL);
switch(mState)
{
case CSB_DIRECT_ATTEMPT:
{
errorMsg(std::cerr, "mState == DIRECT_ATTEMPT", 0);
retval = CSB_ACTION_WAIT;
}
break;
case CSB_PROXY_ATTEMPT:
{
errorMsg(std::cerr, "mState == PROXY_ATTEMPT", 0);
retval = CSB_ACTION_WAIT;
}
break;
case CSB_RELAY_ATTEMPT:
{
errorMsg(std::cerr, "mState == RELAY_ATTEMPT", 0);
retval = CSB_ACTION_WAIT;
}
break;
case CSB_FAILED_WAIT:
{
/* if too soon */
if (now - mStateTS < FAILED_WAIT_TIME)
{
/* same state */
stateMsg(std::cerr, "too soon, no action", 0);
retval = CSB_ACTION_WAIT;
break;
}
} /* FALLTHROUGH TO START CASE */
default:
case CSB_DIRECT_WAIT:
{
if (mState != CSB_FAILED_WAIT)
{
/* ERROR */
errorMsg(std::cerr, "mState != FAILED_WAIT", 0);
}
} /* FALLTHROUGH TO START CASE */
case CSB_START:
{
/* starting up the connection */
if (mState != CSB_NETSTATE_FIREWALLED)
{
stateMsg(std::cerr, "not Firewalled => PROXY_ATTEMPT", 0);
mState = CSB_PROXY_ATTEMPT;
retval = CSB_ACTION_PROXY_CONN | proxyPortMode;
}
else
{
stateMsg(std::cerr, "Firewalled => RELAY_ATTEMPT", 0);
mState = CSB_RELAY_ATTEMPT;
retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT;
}
mStateTS = now;
mNoAttempts = 0;
}
break;
case CSB_PROXY_WAIT:
{
/* if too soon */
if (now - mStateTS < PROXY_WAIT_TIME)
{
/* same state */
stateMsg(std::cerr, "too soon, no action", 0);
retval = CSB_ACTION_WAIT;
}
else if (mNoAttempts >= MAX_PROXY_ATTEMPTS) /* if too many attempts */
{
/* switch to RELAY attempt */
stateMsg(std::cerr, "too many PROXY => RELAY_ATTEMPT", 0);
mState = CSB_RELAY_ATTEMPT;
retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT;
mStateTS = now;
mNoAttempts = 0;
}
else
{
/* try again */
stateMsg(std::cerr, "PROXY_ATTEMPT try again", 0);
mState = CSB_PROXY_ATTEMPT;
retval = CSB_ACTION_PROXY_CONN | proxyPortMode;
mStateTS = now;
mNoAttempts++;
}
}
break;
case CSB_REVERSE_WAIT:
{
/* if too soon */
if (now - mStateTS < REVERSE_WAIT_TIME)
{
/* same state */
stateMsg(std::cerr, "too soon, no action", 0);
retval = CSB_ACTION_WAIT;
}
else
{
stateMsg(std::cerr, "timeout => RELAY_ATTEMPT", 0);
/* switch to RELAY attempt */
mState = CSB_RELAY_ATTEMPT;
retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT;
mStateTS = now;
mNoAttempts = 0;
}
}
break;
case CSB_RELAY_WAIT:
{
/* if too soon */
if (now - mStateTS < RELAY_WAIT_TIME)
{
/* same state */
stateMsg(std::cerr, "too soon, no action", 0);
retval = CSB_ACTION_WAIT;
}
else if (mNoAttempts >= MAX_RELAY_ATTEMPTS) /* if too many attempts */
{
/* switch to RELAY attempt */
stateMsg(std::cerr, "too many RELAY => FAILED_WAIT", 0);
mState = CSB_FAILED_WAIT;
retval = CSB_ACTION_WAIT;
mStateTS = now;
mNoAttempts = 0;
}
else
{
/* try again */
stateMsg(std::cerr, "RELAY_ATTEMPT try again", 0);
mState = CSB_RELAY_ATTEMPT;
retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT;
mStateTS = now;
mNoAttempts++;
}
}
break;
case CSB_CONNECTED:
{
stateMsg(std::cerr, "connected => no action", 0);
retval = CSB_ACTION_WAIT;
}
break;
}
return retval;
}
uint32_t PeerConnectStateBox::updateCb(uint32_t update)
{
/* The Error Callback doesn't trigger another connection.
* but can change the connection state
*
* Possible Errors:
* 1) AUTH DENIED. (fatal)
* 2) MODE UNAVILABLE
* 3) FAILED ATTEMPT
* 4) CONNECTION
* 5) DISCONNECTED.
*
* Fitting these into the states:
case CSB_START:
CONNECTION => CSB_CONNECTED
error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, DISCONNECTED
case CSB_CONNECTED:
CONNECTION => CSB_CONNECTED
DISCONNECTED => CSB_START
error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT
case CSB_FAILED_WAIT:
CONNECTION => CSB_CONNECTED
error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, DISCONNECTED
case CSB_REVERSE_WAIT:
CONNECTION => CSB_CONNECTED
error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, DISCONNECTED
case CSB_DIRECT_ATTEMPT:
CONNECTION => CSB_CONNECTED
AUTH DENIED => CSB_FAILED_WAIT
FAILED ATTEMPT => stay here.
MODE UNAVAILABLE - probably error => CSB_FAILED_WAIT
error if: MODE UNAVAILABLE, DISCONNECTED
case CSB_PROXY_ATTEMPT:
CONNECTION => CSB_CONNECTED
AUTH DENIED => CSB_FAILED_WAIT
FAILED ATTEMPT => stay here.
MODE_UNAVAILABLE => CSB_REVERSE_WAIT | CSB_RELAY_ATTEMPT
error if: DISCONNECTED
case CSB_RELAY_ATTEMPT:
CONNECTION => CSB_CONNECTED
AUTH DENIED => CSB_FAILED_WAIT
FAILED ATTEMPT => stay here.
MODE_UNAVAILABLE => CSB_FAILED_WAIT
error if: DISCONNECTED
case CSB_DIRECT_WAIT:
CONNECTION => CSB_CONNECTED
error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, DISCONNECTED
case CSB_PROXY_WAIT:
CONNECTION => CSB_CONNECTED
error if: AUTH_DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, DISCONNECTED
case CSB_RELAY_ATTEMPT:
CONNECTION => CSB_CONNECTED
error if: AUTH_DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, DISCONNECTED
*/
/* DO Connect / Disconnect Updates ... very specific! */
time_t now = time(NULL);
switch(update)
{
case CSB_UPDATE_CONNECTED:
{
stateMsg(std::cerr, "=> CONNECTED", update);
mState = CSB_CONNECTED;
mStateTS = now;
return 0;
}
break;
case CSB_UPDATE_DISCONNECTED:
{
if (mState != CSB_CONNECTED)
{
/* ERROR, ignore (as already in disconnected state) */
errorMsg(std::cerr, "mState != CSB_CONNECTED", update);
}
else
{
stateMsg(std::cerr, "=> START", update);
/* move to START state */
mState = CSB_START;
mStateTS = now;
return 1;
}
return 0;
}
break;
}
/* Now catch errors for feedback when we should be WAITING */
switch(mState)
{
default:
case CSB_DIRECT_WAIT:
case CSB_PROXY_WAIT:
case CSB_RELAY_WAIT:
case CSB_REVERSE_WAIT:
case CSB_FAILED_WAIT:
case CSB_START:
case CSB_CONNECTED: /* impossible */
{
/* ERROR */
/* shouldn't receive anything here! */
errorMsg(std::cerr, "shouldnt get anything", update);
return 0;
}
break;
case CSB_DIRECT_ATTEMPT:
case CSB_PROXY_ATTEMPT:
case CSB_RELAY_ATTEMPT:
{
/* OKAY */
}
break;
}
switch(update)
{
/* if AUTH_DENIED ... => FAILED_WAIT */
case CSB_UPDATE_AUTH_DENIED:
{
stateMsg(std::cerr, "=> FAILED WAIT", update);
mState = CSB_FAILED_WAIT;
mStateTS = now;
return 1;
}
break;
/* if standard FAIL => stay where we are */
case CSB_UPDATE_FAILED_ATTEMPT:
{
stateMsg(std::cerr, "STANDARD FAIL => switch to wait state", update);
switch(mState)
{
case CSB_DIRECT_ATTEMPT:
mState = CSB_DIRECT_WAIT;
mStateTS = now;
break;
case CSB_PROXY_ATTEMPT:
mState = CSB_PROXY_WAIT;
mStateTS = now;
break;
case CSB_RELAY_ATTEMPT:
mState = CSB_RELAY_WAIT;
mStateTS = now;
break;
default:
stateMsg(std::cerr, "STANDARD FAIL, but unusual state", update);
break;
}
return 1;
}
break;
/* finally MODE_UNAVAILABLE */
case CSB_UPDATE_MODE_UNAVAILABLE:
{
if (mState == CSB_PROXY_ATTEMPT)
{
if (mNetState == CSB_NETSTATE_FORWARD)
{
stateMsg(std::cerr, "as FORWARDED => REVERSE_WAIT", update);
mState = CSB_REVERSE_WAIT;
mStateTS = now;
}
else
{
stateMsg(std::cerr, "as !FORWARDED => RELAY_ATTEMPT", update);
mState = CSB_RELAY_WAIT;
mNoAttempts = 0;
mStateTS = now;
}
return 1;
}
else
{
stateMsg(std::cerr, "MODE UNAVAIL => FAILED_WAIT", update);
mState = CSB_FAILED_WAIT;
mStateTS = now;
if ((mState == CSB_DIRECT_ATTEMPT)
|| (mState == CSB_PROXY_ATTEMPT))
{
/* OKAY */
return 1;
}
else
{
/* ERROR */
errorMsg(std::cerr, "strange MODE", update);
return 0;
}
}
}
break;
default:
{
/* ERROR */
errorMsg(std::cerr, "impossible default", update);
}
break;
}
/* if we get here... ERROR */
errorMsg(std::cerr, "if we get here => ERROR", update);
return 0;
}
bool PeerConnectStateBox::storeProxyPortChoice(uint32_t flags, bool useProxyPort)
{
mProxyPortFlags = flags;
mProxyPortChoice = useProxyPort;
mProxyPortTS = time(NULL);
return useProxyPort;
}
bool PeerConnectStateBox::getProxyPortChoice()
{
time_t now = time(NULL);
std::cerr << "PeerConnectStateBox::getProxyPortChoice() Using ConnectLogic Info from: ";
std::cerr << now-mProxyPortTS << " ago. Flags: " << mProxyPortFlags;
std::cerr << " UseProxyPort? " << mProxyPortChoice;
std::cerr << std::endl;
return useProxyPort;
}

View File

@ -0,0 +1,91 @@
#ifndef CONNECT_STATUS_BOX_H
#define CONNECT_STATUS_BOX_H
/* a connect state box */
#define CSB_START 1
#define CSB_DIRECT_ATTEMPT 2
#define CSB_DIRECT_WAIT 3
#define CSB_PROXY_ATTEMPT 4
#define CSB_PROXY_WAIT 5
#define CSB_RELAY_ATTEMPT 6
#define CSB_RELAY_WAIT 7
#define CSB_REVERSE_WAIT 8
#define CSB_FAILED_WAIT 9
#define CSB_CONNECTED 10
#define CSB_NETSTATE_UNKNOWN 0
#define CSB_NETSTATE_FORWARD 1
#define CSB_NETSTATE_STABLENAT 2
#define CSB_NETSTATE_FIREWALLED 3
#define CSB_CONNECT_DIRECT 1
#define CSB_CONNECT_UNREACHABLE 2
/* return values */
#define CSB_ACTION_MASK_MODE 0x00ff
#define CSB_ACTION_MASK_PORT 0xff00
#define CSB_ACTION_WAIT 0x0001
#define CSB_ACTION_DIRECT_CONN 0x0002
#define CSB_ACTION_PROXY_CONN 0x0004
#define CSB_ACTION_RELAY_CONN 0x0008
#define CSB_ACTION_DHT_PORT 0x0100
#define CSB_ACTION_PROXY_PORT 0x0200
/* update input */
#define CSB_UPDATE_NONE 0x0000
#define CSB_UPDATE_CONNECTED 0x0001
#define CSB_UPDATE_DISCONNECTED 0x0002
#define CSB_UPDATE_AUTH_DENIED 0x0003
#define CSB_UPDATE_FAILED_ATTEMPT 0x0004
#define CSB_UPDATE_MODE_UNAVAILABLE 0x0005
#include <iosfwd>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <inttypes.h>
class PeerConnectStateBox
{
public:
PeerConnectStateBox();
uint32_t connectCb(uint32_t cbtype, uint32_t netmode, uint32_t nattype);
uint32_t updateCb(uint32_t updateType);
bool shouldUseProxyPort(uint32_t netmode, uint32_t nattype);
std::string connectState();
std::string mPeerId;
bool storeProxyPortChoice(uint32_t flags, bool useProxyPort);
bool getProxyPortChoice();
private:
uint32_t connectCb_direct();
uint32_t connectCb_unreachable();
void errorMsg(std::ostream &out, std::string msg, uint32_t updateParam);
void stateMsg(std::ostream &out, std::string msg, uint32_t updateParam);
uint32_t mState;
uint32_t mNetState;
time_t mStateTS;
uint32_t mNoAttempts;
// ProxyPort Storage.
uint32_t mProxyPortFlags;
bool mProxyPortChoice;
time_t mProxyPortTS;
};
#endif

View File

@ -28,9 +28,6 @@
#include "bitdht/bdstddht.h" #include "bitdht/bdstddht.h"
#include "pqi/p3linkmgr.h" // FOR FLAGS... move elsewhere
#include "pqi/p3peermgr.h"
#include "tcponudp/udprelay.h" #include "tcponudp/udprelay.h"
#include "tcponudp/udpstunner.h" #include "tcponudp/udpstunner.h"
@ -79,8 +76,9 @@ virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdI
}; };
p3BitDht::p3BitDht(std::string id, pqiConnectCb *cb, UdpStack *udpstack, std::string bootstrapfile) p3BitDht::p3BitDht(std::string id, pqiConnectCb *cb, p3NetMgr *nm,
:pqiNetAssistConnect(id, cb), dhtMtx("p3BitDht") UdpStack *udpstack, std::string bootstrapfile)
:pqiNetAssistConnect(id, cb), mNetMgr(nm), dhtMtx("p3BitDht")
{ {
mDhtStunner = NULL; mDhtStunner = NULL;
mProxyStunner = NULL; mProxyStunner = NULL;
@ -100,8 +98,8 @@ p3BitDht::p3BitDht(std::string id, pqiConnectCb *cb, UdpStack *udpstack, std::st
#endif #endif
/* setup ownId */ /* setup ownId */
storeTranslation(id); storeTranslation_locked(id);
lookupNodeId(id, &ownId); lookupNodeId_locked(id, &ownId);
#ifdef DEBUG_BITDHT #ifdef DEBUG_BITDHT
@ -202,6 +200,7 @@ bool p3BitDht::getNetworkStats(uint32_t &netsize, uint32_t &localnetsize)
return true; return true;
} }
#if 0
/* pqiNetAssistConnect - external interface functions */ /* pqiNetAssistConnect - external interface functions */
/* add / remove peers */ /* add / remove peers */
bool p3BitDht::findPeer(std::string pid) bool p3BitDht::findPeer(std::string pid)
@ -283,6 +282,9 @@ bool p3BitDht::dropPeer(std::string pid)
return true ; return true ;
} }
#endif
/* extract current peer status */ /* extract current peer status */
bool p3BitDht::getPeerStatus(std::string id, bool p3BitDht::getPeerStatus(std::string id,
struct sockaddr_in &laddr, struct sockaddr_in &raddr, struct sockaddr_in &laddr, struct sockaddr_in &raddr,
@ -311,396 +313,3 @@ bool p3BitDht::getExternalInterface(struct sockaddr_in &raddr,
} }
/* Adding a little bit of fixed test...
* This allows us to ensure that only compatible peers will find each other
*/
const uint8_t RS_DHT_VERSION_LEN = 17;
const uint8_t rs_dht_version_data[RS_DHT_VERSION_LEN] = "RS_VERSION_0.5.1";
/******************** Conversion Functions **************************/
int p3BitDht::calculateNodeId(const std::string pid, bdNodeId *id)
{
/* generate node id from pid */
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::calculateNodeId() " << pid;
#endif
/* use a hash to make it impossible to reverse */
uint8_t sha_hash[SHA_DIGEST_LENGTH];
memset(sha_hash,0,SHA_DIGEST_LENGTH*sizeof(uint8_t)) ;
SHA_CTX *sha_ctx = new SHA_CTX;
SHA1_Init(sha_ctx);
SHA1_Update(sha_ctx, rs_dht_version_data, RS_DHT_VERSION_LEN);
SHA1_Update(sha_ctx, pid.c_str(), pid.length());
SHA1_Final(sha_hash, sha_ctx);
for(int i = 0; i < SHA_DIGEST_LENGTH && (i < BITDHT_KEY_LEN); i++)
{
id->data[i] = sha_hash[i];
}
delete sha_ctx;
#ifdef DEBUG_BITDHT
std::cerr << " => ";
bdStdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
#endif
return 1;
}
int p3BitDht::lookupNodeId(const std::string pid, bdNodeId *id)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupNodeId() for : " << pid;
std::cerr << std::endl;
#endif
RsStackMutex stack(dhtMtx);
std::map<std::string, bdNodeId>::iterator it;
it = mTransToNodeId.find(pid);
if (it == mTransToNodeId.end())
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupNodeId() failed";
std::cerr << std::endl;
#endif
return 0;
}
*id = it->second;
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupNodeId() Found NodeId: ";
bdStdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
#endif
return 1;
}
int p3BitDht::lookupRsId(const bdNodeId *id, std::string &pid)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupRsId() for : ";
bdStdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
#endif
RsStackMutex stack(dhtMtx);
std::map<bdNodeId, std::string>::iterator nit;
nit = mTransToRsId.find(*id);
if (nit == mTransToRsId.end())
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupRsId() failed";
std::cerr << std::endl;
#endif
return 0;
}
pid = nit->second;
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupRsId() Found Matching RsId: " << pid;
std::cerr << std::endl;
#endif
return 1;
}
int p3BitDht::storeTranslation(const std::string pid)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::storeTranslation(" << pid << ")";
std::cerr << std::endl;
#endif
bdNodeId nid;
calculateNodeId(pid, &nid);
RsStackMutex stack(dhtMtx);
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::storeTranslation() Converts to NodeId: ";
bdStdPrintNodeId(std::cerr, &(nid));
std::cerr << std::endl;
#endif
mTransToNodeId[pid] = nid;
mTransToRsId[nid] = pid;
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::storeTranslation() Success";
std::cerr << std::endl;
#endif
return 1;
}
int p3BitDht::removeTranslation(const std::string pid)
{
RsStackMutex stack(dhtMtx);
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::removeTranslation(" << pid << ")";
std::cerr << std::endl;
#endif
std::map<std::string, bdNodeId>::iterator it = mTransToNodeId.find(pid);
it = mTransToNodeId.find(pid);
if (it == mTransToNodeId.end())
{
std::cerr << "p3BitDht::removeTranslation() ERROR MISSING TransToNodeId";
std::cerr << std::endl;
/* missing */
return 0;
}
bdNodeId nid = it->second;
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::removeTranslation() Found Translation: NodeId: ";
bdStdPrintNodeId(std::cerr, &(nid));
std::cerr << std::endl;
#endif
std::map<bdNodeId, std::string>::iterator nit;
nit = mTransToRsId.find(nid);
if (nit == mTransToRsId.end())
{
std::cerr << "p3BitDht::removeTranslation() ERROR MISSING TransToRsId";
std::cerr << std::endl;
/* inconsistent!!! */
return 0;
}
mTransToNodeId.erase(it);
mTransToRsId.erase(nit);
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::removeTranslation() SUCCESS";
std::cerr << std::endl;
#endif
return 1;
}
/********************** Callback Functions **************************/
uint32_t translatebdcbflgs(uint32_t peerflags);
int p3BitDht::NodeCallback(const bdId *id, uint32_t peerflags)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::NodeCallback()";
std::cerr << std::endl;
#endif
// XXX THIS IS A BAD HACK TO PREVENT connection attempt to MEDIASENTRY (dht spies)
// peers... These peers appear to masquerade as your OwnNodeId!!!!
// which means peers could attempt to connect too?? not sure about this?
// Anyway they don't appear to REPLY to FIND_NODE requests...
// So if we ignore these peers, we'll only get the true RS peers!
// This should be fixed by a collaborative IP filter system,
// EACH peer identifies dodgey IP (ones spoofing yourself), and shares them
// This are distributed around RS via a service, and the UDP ignores
// all comms from these sources. (AT a low level).
if (peerflags != BITDHT_PEER_STATUS_RECV_NODES)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::NodeCallback() Ignoring !FIND_NODE callback from:";
bdStdPrintNodeId(std::cerr, &(id->id));
std::cerr << " flags: " << peerflags;
std::cerr << std::endl;
#endif
return 0;
}
/* is it one that we are interested in? */
std::string pid;
/* check for translation */
if (lookupRsId(&(id->id), pid))
{
#ifdef DEBUG_BITDHT
/* we found it ... do callback to p3connmgr */
std::cerr << "p3BitDht::NodeCallback() FOUND NODE!!!: ";
bdStdPrintNodeId(std::cerr, &(id->id));
std::cerr << "-> " << pid << " flags: " << peerflags;
std::cerr << std::endl;
#endif
/* send status info to p3connmgr */
pqiIpAddress dhtpeer;
dhtpeer.mSrc = RS_CB_DHT;
dhtpeer.mSeenTime = time(NULL);
dhtpeer.mAddr = id->addr;
pqiIpAddrSet addrs;
addrs.updateExtAddrs(dhtpeer);
uint32_t type = RS_NET_CONN_UDP_DHT_SYNC;
uint32_t flags = translatebdcbflgs(peerflags);
uint32_t source = RS_CB_DHT;
mConnCb->peerStatus(pid, addrs, type, flags, source);
return 1;
}
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::NodeCallback() FAILED TO FIND NODE: ";
bdStdPrintNodeId(std::cerr, &(id->id));
std::cerr << std::endl;
#endif
return 0;
}
uint32_t translatebdcbflgs(uint32_t peerflags)
{
uint32_t outflags = 0;
outflags |= RS_NET_FLAGS_ONLINE;
return outflags;
#if 0
// The input flags.
#define BITDHT_PEER_STATUS_RECV_PONG 0x00000001
#define BITDHT_PEER_STATUS_RECV_NODES 0x00000002
#define BITDHT_PEER_STATUS_RECV_HASHES 0x00000004
#define BITDHT_PEER_STATUS_DHT_ENGINE 0x00000100
#define BITDHT_PEER_STATUS_DHT_APPL 0x00000200
#define BITDHT_PEER_STATUS_DHT_VERSION 0x00000400
if (peerflags & ONLINE)
{
outflags |= RS_NET_FLAGS_ONLINE;
}
if (peerflags & ONLINE)
{
outflags |= RS_NET_FLAGS_EXTERNAL_ADDR | RS_NET_FLAGS_STABLE_UDP;
}
#endif
}
int p3BitDht::PeerCallback(const bdId *id, uint32_t status)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::PeerCallback() bdId: ";
bdStdPrintId(std::cerr, id);
std::cerr << std::endl;
#endif
/* is it one that we are interested in? */
std::string pid;
/* check for translation */
if (lookupRsId(&(id->id), pid))
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::PeerCallback() => RsId: ";
std::cerr << pid << " status: " << status;
std::cerr << " NOOP for NOW";
std::cerr << std::endl;
#endif
bool connect = false;
switch(status)
{
case BITDHT_MGR_QUERY_FAILURE:
/* do nothing */
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::PeerCallback() QUERY FAILURE ... do nothin ";
std::cerr << std::endl;
#endif
break;
case BITDHT_MGR_QUERY_PEER_OFFLINE:
/* do nothing */
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::PeerCallback() QUERY PEER OFFLINE ... do nothin ";
std::cerr << std::endl;
#endif
break;
case BITDHT_MGR_QUERY_PEER_UNREACHABLE:
/* do nothing */
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::PeerCallback() QUERY PEER UNREACHABLE ... flag? / do nothin ";
std::cerr << std::endl;
#endif
break;
case BITDHT_MGR_QUERY_PEER_ONLINE:
/* do something */
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::PeerCallback() QUERY PEER ONLINE ... try udp connection";
std::cerr << std::endl;
#endif
connect = true;
break;
}
if (connect)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::PeerCallback() mConnCb->peerConnectRequest()";
std::cerr << std::endl;
#endif
mConnCb->peerConnectRequest(pid, id->addr, RS_CB_DHT);
return 1;
}
else
{
return 0;
}
}
else
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::PeerCallback()";
std::cerr << " FAILED TO TRANSLATE ID ";
std::cerr << " status: " << status;
std::cerr << " NOOP for NOW";
std::cerr << std::endl;
#endif
}
return 0;
}
int p3BitDht::ValueCallback(const bdNodeId *id, std::string key, uint32_t status)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::ValueCallback() NOOP for NOW";
std::cerr << std::endl;
#endif
/* ignore for now */
return 0;
}

View File

@ -40,24 +40,87 @@
#include "udp/udpbitdht.h" #include "udp/udpbitdht.h"
#include "bitdht/bdiface.h" #include "bitdht/bdiface.h"
#include "dht/connectstatebox.h"
class DhtPeerDetails class DhtPeerDetails
{ {
public: public:
uint32_t mPeerType;
bdId mDhtId; bdId mDhtId;
std::string mRsId; std::string mRsId;
/* direct from the DHT! */
uint32_t mDhtState; // One of RSDHT_PEERDHT_[...]
time_t mDhtUpdateTS;
/* internal state */
PeerConnectStateBox mConnectLogic;
/* Actual Connection Status */
uint32_t mPeerConnectState; // One of RSDHT_PEERCONN_
std::string mPeerConnectMsg;
uint32_t mPeerConnectMode;
bdId mPeerConnectPeerId;
bdId mPeerConnectProxyId;
struct sockaddr_in mPeerConnectAddr;
uint32_t mPeerConnectPoint;
time_t mPeerConnectUdpTS;
time_t mPeerConnectTS;
time_t mPeerConnectClosedTS;
/* keeping the PeerCbMsg, as we will need it for debugging */
/* don't think this data is ever used for decisions??? */
/* Connection Request Status */
std::string mPeerReqStatusMsg;
uint32_t mPeerReqState;
uint32_t mPeerReqMode;
bdId mPeerReqProxyId;
time_t mPeerReqTS;
/* Callback Info */
std::string mPeerCbMsg;
uint32_t mPeerCbMode;
uint32_t mPeerCbPoint;
bdId mPeerCbProxyId;
bdId mPeerCbDestId;
time_t mPeerCbTS;
}; };
#define PEERNET_ACTION_TYPE_CONNECT 1
#define PEERNET_ACTION_TYPE_AUTHORISE 2
#define PEERNET_ACTION_TYPE_START 3
#define PEERNET_ACTION_TYPE_RESTARTREQ 4
#define PEERNET_ACTION_TYPE_KILLREQ 5
class PeerAction
{
public:
uint32_t mType;
bdId mSrcId;
bdId mProxyId;
bdId mDestId;
uint32_t mMode;
uint32_t mPoint;
uint32_t mAnswer;
};
class UdpRelayReceiver; class UdpRelayReceiver;
class UdpStunner; class UdpStunner;
class p3NetMgr;
class p3BitDht: public pqiNetAssistConnect, public RsDht class p3BitDht: public pqiNetAssistConnect, public RsDht
{ {
public: public:
p3BitDht(std::string id, pqiConnectCb *cb, p3BitDht(std::string id, pqiConnectCb *cb, p3NetMgr *nm,
UdpStack *udpstack, std::string bootstrapfile); UdpStack *udpstack, std::string bootstrapfile);
@ -120,31 +183,83 @@ virtual bool getExternalInterface(struct sockaddr_in &raddr,
/* pqiNetAssistConnect - external interface functions */ /* pqiNetAssistConnect - external interface functions */
/***********************************************************************************************
****************************** Connections (p3bitdht_peernet.cc) ******************************
************************************************************************************************/
/* Callback functions - from bitdht */ /* Callback functions - from bitdht */
int NodeCallback(const bdId *id, uint32_t peerflags); int NodeCallback(const bdId *id, uint32_t peerflags);
int PeerCallback(const bdId *id, uint32_t status); int PeerCallback(const bdId *id, uint32_t status);
int ValueCallback(const bdNodeId *id, std::string key, uint32_t status); int ValueCallback(const bdNodeId *id, std::string key, uint32_t status);
int ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId,
uint32_t mode, uint32_t point, uint32_t cbtype, uint32_t errcode);
int OnlinePeerCallback_locked(const bdId *id, uint32_t status, DhtPeerDetails *dpd);
int UnreachablePeerCallback_locked(const bdId *id, uint32_t status, DhtPeerDetails *dpd);
int tick();
int minuteTick();
int doActions();
int checkProxyAllowed(const bdId *srcId, const bdId *destId, int mode);
int checkConnectionAllowed(const bdId *peerId, int mode);
void initiateConnection(const bdId *srcId, const bdId *proxyId, const bdId *destId, uint32_t mode, uint32_t loc, uint32_t answer);
int installRelayConnection(const bdId *srcId, const bdId *destId);
int removeRelayConnection(const bdId *srcId, const bdId *destId);
void monitorConnections();
void ConnectCallout(const std::string &peerId, struct sockaddr_in addr, uint32_t connectMode);
void Feedback_Connected(std::string pid);
void Feedback_ConnectionFailed(std::string pid);
void UdpConnectionFailed_locked(DhtPeerDetails *dpd);
void Feedback_ConnectionClosed(std::string pid);
/***********************************************************************************************
************************** Internal Accounting (p3bitdht_peers.cc) ****************************
************************************************************************************************/
public:
//bool findPeer(std::string pid)
//bool dropPeer(std::string pid);
int addFriend(const std::string pid);
int addFriendOfFriend(const std::string pid);
int addOther(const std::string pid);
int removePeer(const std::string pid);
private: private:
/* translation stuff */
int calculateNodeId(const std::string pid, bdNodeId *id);
int lookupNodeId(const std::string pid, bdNodeId *id); DhtPeerDetails *addInternalPeer_locked(const std::string pid, int type);
int lookupRsId(const bdNodeId *id, std::string &pid); int removeInternalPeer_locked(const std::string pid);
int storeTranslation(const std::string pid); DhtPeerDetails *findInternalDhtPeer_locked(const bdNodeId *id, int type);
int removeTranslation(const std::string pid); DhtPeerDetails *findInternalRsPeer_locked(const std::string &pid);
bool havePeerTranslation_locked(const std::string &pid);
int lookupNodeId_locked(const std::string pid, bdNodeId *id);
int lookupRsId_locked(const bdNodeId *id, std::string &pid);
int storeTranslation_locked(const std::string pid);
int removeTranslation_locked(const std::string pid);
int calculateNodeId(const std::string pid, bdNodeId *id);
UdpBitDht *mUdpBitDht; /* has own mutex, is static except for creation/destruction */ UdpBitDht *mUdpBitDht; /* has own mutex, is static except for creation/destruction */
UdpStunner *mDhtStunner; UdpStunner *mDhtStunner;
UdpStunner *mProxyStunner; UdpStunner *mProxyStunner;
UdpRelayReceiver *mRelay; UdpRelayReceiver *mRelay;
p3NetMgr *mNetMgr;
RsMutex dhtMtx; RsMutex dhtMtx;
time_t mMinuteTS;
/* translation maps */ /* translation maps */
std::map<std::string, bdNodeId> mTransToNodeId; std::map<std::string, bdNodeId> mTransToNodeId;
std::map<bdNodeId, std::string> mTransToRsId; std::map<bdNodeId, std::string> mTransToRsId;
std::map<std::string, DhtPeerDetails> mPeers; std::map<bdNodeId, DhtPeerDetails> mPeers;
std::map<bdNodeId, DhtPeerDetails> mFailedPeers;
/* Connection Action Queue */
std::list<PeerAction> mActions;
}; };
#endif /* MRK_P3_BITDHT_H */ #endif /* MRK_P3_BITDHT_H */

View File

@ -69,10 +69,10 @@ int p3BitDht::getDhtPeers(int lvl, std::list<RsDhtPeer> &peers)
int p3BitDht::getNetPeerList(std::list<std::string> &peerIds) int p3BitDht::getNetPeerList(std::list<std::string> &peerIds)
{ {
RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ RsStackMutex stack(dhtMtx); /*********** LOCKED **********/
std::map<std::string, DhtPeerDetails>::iterator it; std::map<bdNodeId, DhtPeerDetails>::iterator it;
for(it = mPeers.begin(); it != mPeers.end(); it++) for(it = mPeers.begin(); it != mPeers.end(); it++)
{ {
peerIds.push_back(it->first); peerIds.push_back(it->second.mRsId);
} }
return 1; return 1;
@ -83,14 +83,13 @@ int p3BitDht::getNetPeerStatus(std::string peerId, RsDhtNetPeer &status)
RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ RsStackMutex stack(dhtMtx); /*********** LOCKED **********/
std::map<std::string, DhtPeerDetails>::iterator it; DhtPeerDetails *dpd = findInternalRsPeer_locked(peerId);
it = mPeers.find(peerId); if (!dpd)
if (it == mPeers.end())
{ {
return 0; return 0;
} }
convertDhtPeerDetailsToRsDhtNetPeer(status, it->second); convertDhtPeerDetailsToRsDhtNetPeer(status, *dpd);
return 1; return 1;
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,461 @@
/*
* libretroshare/src/dht: p3bitdht.h
*
* BitDht interface for RetroShare.
*
* Copyright 2009-2010 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "dht/p3bitdht.h"
#include "bitdht/bdstddht.h"
#include "tcponudp/udprelay.h"
#include "tcponudp/udpstunner.h"
#include <openssl/sha.h>
/******************************************************************************************
********************************* Existing Interface *************************************
******************************************************************************************/
/* pqiNetAssistConnect - external interface functions */
/* add / remove peers */
/*****
* At the moment, findPeer, dropPeer are the only way that peer info enters the dht.
* This will obviously change, and we will have a list of Friends and FoF,
* but for now we need to expect that this function will add unknown pids.
*
*/
#define USE_OLD_DHT_INTERFACE 1
bool p3BitDht::findPeer(std::string pid)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::findPeer(" << pid << ")";
std::cerr << std::endl;
#endif
DhtPeerDetails *dpd = findInternalRsPeer_locked(pid);
if (!dpd)
{
dpd = addInternalPeer_locked(pid, RSDHT_PEERTYPE_FRIEND);
if (!dpd)
{
/* ERROR */
return false;
}
}
/* flag as searching */
dpd->mDhtState = RSDHT_PEERDHT_SEARCHING;
bdNodeId nid = dpd->mDhtId.id;
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::findPeer() calling AddFindNode() with pid => NodeId: ";
bdStdPrintNodeId(std::cerr, &nid);
std::cerr << std::endl;
#endif
/* add in peer */
mUdpBitDht->addFindNode(&nid, BITDHT_QFLAGS_DO_IDLE);
return true ;
}
bool p3BitDht::dropPeer(std::string pid)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::dropPeer(" << pid << ")";
std::cerr << std::endl;
#endif
DhtPeerDetails *dpd = findInternalRsPeer_locked(pid);
if (!dpd)
{
/* ERROR */
return false;
}
/* flag as searching */
dpd->mDhtState = RSDHT_PEERDHT_NOT_ACTIVE;
bdNodeId nid = dpd->mDhtId.id;
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::dropPeer() calling removeFindNode() with pid => NodeId: ";
bdStdPrintNodeId(std::cerr, &nid);
std::cerr << std::endl;
#endif
/* remove in peer */
mUdpBitDht->removeFindNode(&nid);
/* not removing from translation */
return true ;
}
/******************************************************************************************
********************************* Basic Peer Details *************************************
******************************************************************************************/
int p3BitDht::addFriend(const std::string pid)
{
RsStackMutex stack(dhtMtx); /********* LOCKED *********/
return (NULL != addInternalPeer_locked(pid, RSDHT_PEERTYPE_FRIEND));
}
int p3BitDht::addFriendOfFriend(const std::string pid)
{
RsStackMutex stack(dhtMtx); /********* LOCKED *********/
return (NULL != addInternalPeer_locked(pid, RSDHT_PEERTYPE_FOF));
}
int p3BitDht::addOther(const std::string pid)
{
RsStackMutex stack(dhtMtx); /********* LOCKED *********/
return (NULL != addInternalPeer_locked(pid, RSDHT_PEERTYPE_OTHER));
}
int p3BitDht::removePeer(const std::string pid)
{
RsStackMutex stack(dhtMtx); /********* LOCKED *********/
return removeInternalPeer_locked(pid);
}
/******************************************************************************************
********************************* Basic Peer Details *************************************
******************************************************************************************/
DhtPeerDetails *p3BitDht::addInternalPeer_locked(const std::string pid, int type)
{
/* create the data structure */
if (!havePeerTranslation_locked(pid))
{
storeTranslation_locked(pid);
}
bdNodeId id;
if (!lookupNodeId_locked(pid, &id))
{
return 0;
}
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&id, RSDHT_PEERTYPE_ANY);
if (!dpd)
{
DhtPeerDetails newdpd;
mPeers[id] = newdpd;
dpd = findInternalDhtPeer_locked(&id, RSDHT_PEERTYPE_ANY);
}
/* what do we need to reset? */
dpd->mPeerType = type;
return dpd;
}
int p3BitDht::removeInternalPeer_locked(const std::string pid)
{
bdNodeId id;
if (!lookupNodeId_locked(pid, &id))
{
return 0;
}
std::map<bdNodeId, DhtPeerDetails>::iterator it = mPeers.find(id);
if (it == mPeers.end())
{
return 0;
}
mPeers.erase(it);
// remove the translation?
removeTranslation_locked(pid);
return 1;
}
/* indexed by bdNodeId, as this is the more used call interface */
DhtPeerDetails *p3BitDht::findInternalDhtPeer_locked(const bdNodeId *id, int type)
{
std::map<bdNodeId, DhtPeerDetails>::iterator it = mPeers.find(*id);
if (it == mPeers.end())
{
return NULL;
}
if (type)
{
if (it->second.mPeerType != type)
{
return NULL;
}
}
return &(it->second);
}
/* interface to get with alt id */
DhtPeerDetails *p3BitDht::findInternalRsPeer_locked(const std::string &pid)
{
/* create the data structure */
if (!havePeerTranslation_locked(pid))
{
return NULL;
}
bdNodeId id;
if (!lookupNodeId_locked(pid, &id))
{
return NULL;
}
DhtPeerDetails *dpd = findInternalDhtPeer_locked(&id,RSDHT_PEERTYPE_ANY);
return dpd;
}
/******************************************************************************************
*************************** Fundamental Node Translation *********************************
******************************************************************************************/
bool p3BitDht::havePeerTranslation_locked(const std::string &pid)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::havePeerTranslation_locked() for : " << pid;
std::cerr << std::endl;
#endif
std::map<std::string, bdNodeId>::iterator it;
it = mTransToNodeId.find(pid);
if (it == mTransToNodeId.end())
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::havePeerTranslation_locked() failed Missing translation";
std::cerr << std::endl;
#endif
return false;
}
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::havePeerTranslation_locked() Found NodeId: ";
bdStdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
#endif
return true;
}
int p3BitDht::lookupNodeId_locked(const std::string pid, bdNodeId *id)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupNodeId_locked() for : " << pid;
std::cerr << std::endl;
#endif
std::map<std::string, bdNodeId>::iterator it;
it = mTransToNodeId.find(pid);
if (it == mTransToNodeId.end())
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupNodeId_locked() failed";
std::cerr << std::endl;
#endif
return 0;
}
*id = it->second;
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupNodeId_locked() Found NodeId: ";
bdStdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
#endif
return 1;
}
int p3BitDht::lookupRsId_locked(const bdNodeId *id, std::string &pid)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupRsId_locked() for : ";
bdStdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
#endif
std::map<bdNodeId, std::string>::iterator nit;
nit = mTransToRsId.find(*id);
if (nit == mTransToRsId.end())
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupRsId_locked() failed";
std::cerr << std::endl;
#endif
return 0;
}
pid = nit->second;
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::lookupRsId_locked() Found Matching RsId: " << pid;
std::cerr << std::endl;
#endif
return 1;
}
int p3BitDht::storeTranslation_locked(const std::string pid)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::storeTranslation_locked(" << pid << ")";
std::cerr << std::endl;
#endif
bdNodeId nid;
calculateNodeId(pid, &nid);
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::storeTranslation_locked() Converts to NodeId: ";
bdStdPrintNodeId(std::cerr, &(nid));
std::cerr << std::endl;
#endif
mTransToNodeId[pid] = nid;
mTransToRsId[nid] = pid;
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::storeTranslation_locked() Success";
std::cerr << std::endl;
#endif
return 1;
}
int p3BitDht::removeTranslation_locked(const std::string pid)
{
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::removeTranslation_locked(" << pid << ")";
std::cerr << std::endl;
#endif
std::map<std::string, bdNodeId>::iterator it = mTransToNodeId.find(pid);
it = mTransToNodeId.find(pid);
if (it == mTransToNodeId.end())
{
std::cerr << "p3BitDht::removeTranslation_locked() ERROR MISSING TransToNodeId";
std::cerr << std::endl;
/* missing */
return 0;
}
bdNodeId nid = it->second;
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::removeTranslation_locked() Found Translation: NodeId: ";
bdStdPrintNodeId(std::cerr, &(nid));
std::cerr << std::endl;
#endif
std::map<bdNodeId, std::string>::iterator nit;
nit = mTransToRsId.find(nid);
if (nit == mTransToRsId.end())
{
std::cerr << "p3BitDht::removeTranslation_locked() ERROR MISSING TransToRsId";
std::cerr << std::endl;
/* inconsistent!!! */
return 0;
}
mTransToNodeId.erase(it);
mTransToRsId.erase(nit);
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::removeTranslation_locked() SUCCESS";
std::cerr << std::endl;
#endif
return 1;
}
/* Adding a little bit of fixed text...
* This allows us to ensure that only compatible peers will find each other
*/
const uint8_t RS_DHT_VERSION_LEN = 17;
const uint8_t rs_dht_version_data[RS_DHT_VERSION_LEN] = "RS_VERSION_0.5.1";
/******************** Conversion Functions **************************/
int p3BitDht::calculateNodeId(const std::string pid, bdNodeId *id)
{
/* generate node id from pid */
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::calculateNodeId() " << pid;
#endif
/* use a hash to make it impossible to reverse */
uint8_t sha_hash[SHA_DIGEST_LENGTH];
memset(sha_hash,0,SHA_DIGEST_LENGTH*sizeof(uint8_t)) ;
SHA_CTX *sha_ctx = new SHA_CTX;
SHA1_Init(sha_ctx);
SHA1_Update(sha_ctx, rs_dht_version_data, RS_DHT_VERSION_LEN);
SHA1_Update(sha_ctx, pid.c_str(), pid.length());
SHA1_Final(sha_hash, sha_ctx);
for(int i = 0; i < SHA_DIGEST_LENGTH && (i < BITDHT_KEY_LEN); i++)
{
id->data[i] = sha_hash[i];
}
delete sha_ctx;
#ifdef DEBUG_BITDHT
std::cerr << " => ";
bdStdPrintNodeId(std::cerr, id);
std::cerr << std::endl;
#endif
return 1;
}

View File

@ -0,0 +1,53 @@
/*
* libretroshare/src/dht: stunaddrassist.h
*
* BitDht interface for RetroShare.
*
* Copyright 2011-2011 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef STUN_ADDR_ASSIST_H
#define STUN_ADDR_ASSIST_H
#include "pqi/pqiassist.h"
#include "tcponudp/udpstunner.h"
class stunAddrAssist: public pqiAddrAssist
{
public:
stunAddrAssist(UdpStunner *stunner)
{
mStunner = stunner;
}
virtual bool getExternalAddr(struct sockaddr_in &remote, uint8_t &stable)
{
return mStunner->externalAddr(remote, stable);
}
private:
UdpStunner *mStunner;
};
#endif