Add the tunneling connection. Warning, encryption is not implemented yet for tunnel connection, use only for testing.

Redesign the udp connection
Remove the rsiface duplicates from retroshare-gui.
Add some randomness in timings for connect manager

Merge branch 'connectionTunneling'

Conflicts:
	libretroshare/src/libretroshare.pro
	libretroshare/src/pqi/p3connmgr.cc
	retroshare-gui/src/RetroShare.pro
	retroshare-gui/src/rsiface/rsfiles.h
	retroshare-gui/src/rsiface/rstypes.h

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@1867 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
joss17 2009-12-13 21:59:26 +00:00
parent 1d567a7faa
commit fdb3673ce2
56 changed files with 2420 additions and 3394 deletions

View file

@ -1786,6 +1786,29 @@ bool AuthSSL::FailedCertificate(X509 *x509, bool incoming)
return ProcessX509(x509, id);
}
bool AuthSSL::encrypt(void *&out, int &outlen, const void *in, int inlen, std::string peerId)
{
#ifdef AUTHSSL_DEBUG
std::cerr << "AuthSSL::encrypt() called with inlen : " << inlen << std::endl;
#endif
//TODO : use ssl to crypt the binary input buffer
out = malloc(inlen);
memcpy(out, in, inlen);
outlen = inlen;
}
bool AuthSSL::decrypt(void *&out, int &outlen, const void *in, int inlen)
{
#ifdef AUTHSSL_DEBUG
std::cerr << "AuthSSL::decrypt() called with inlen : " << inlen << std::endl;
#endif
//TODO : use ssl to decrypt the binary input buffer
out = malloc(inlen);
memcpy(out, in, inlen);
outlen = inlen;
}
/* check that they are exact match */
bool AuthSSL::CheckCertificate(std::string x509Id, X509 *x509)
{

View file

@ -149,6 +149,12 @@ virtual bool SignDataBin(std::string, unsigned char*, unsigned int*);
virtual bool SignDataBin(const void*, uint32_t, unsigned char*, unsigned int*);
virtual bool VerifySignBin(std::string, const void*, uint32_t, unsigned char*, unsigned int);
// return : false if encrypt failed
bool encrypt(void *&out, int &outlen, const void *in, int inlen, std::string peerId); //return the encrypted length
// return : false if decrypt fails
bool decrypt(void *&out, int &outlen, const void *in, int inlen); //return the encrypted length
/*********** Overloaded Functions from p3AuthMgr **********/

View file

@ -59,7 +59,7 @@ const uint32_t MAX_NETWORK_INIT = 70; /* timeout before network reset */
const uint32_t MIN_TIME_BETWEEN_NET_RESET = 5;
const uint32_t PEER_IP_CONNECT_STATE_MAX_LIST_SIZE = 10;
const uint32_t PEER_IP_CONNECT_STATE_MAX_LIST_SIZE = 6;
/****
* #define CONN_DEBUG 1
@ -72,11 +72,11 @@ const uint32_t PEER_IP_CONNECT_STATE_MAX_LIST_SIZE = 10;
***/
const uint32_t P3CONNMGR_TCP_DEFAULT_DELAY = 2; /* 2 Seconds? is it be enough! */
const uint32_t P3CONNMGR_UDP_DHT_DELAY = DHT_NOTIFY_PERIOD + 60; /* + 1 minute for DHT POST */
const uint32_t P3CONNMGR_UDP_PROXY_DELAY = 30; /* 30 seconds (NOT IMPLEMENTED YET!) */
const uint32_t P3CONNMGR_UDP_DEFAULT_DELAY = 2; /* 2 Seconds? is it be enough! */
const uint32_t P3CONNMGR_UDP_DEFAULT_TIMEOUT = 40; //a random timeout is set between P3CONNMGR_UDP_DEFAULT_TIMEOUT and 2 * P3CONNMGR_UDP_DEFAULT_TIMEOUT in the implementation
#define MAX_AVAIL_PERIOD (2 * DHT_NOTIFY_PERIOD) // If we haven't connected in 2 DHT periods.
#define MIN_RETRY_PERIOD (DHT_CHECK_PERIOD + 120) // just over DHT CHECK_PERIOD
#define MAX_AVAIL_PERIOD 180 //times a peer stay in available state when not connected
#define MIN_RETRY_PERIOD 90
void printConnectState(peerConnectState &peer);
@ -143,6 +143,7 @@ p3ConnectMgr::p3ConnectMgr(p3AuthMgr *am)
}
//use_extr_addr_finder = true ;
use_extr_addr_finder = false;
allow_tunnel_connection = true;
mExtAddrFinder = new ExtAddrFinder ;
return;
@ -161,6 +162,13 @@ void p3ConnectMgr::setIPServersEnabled(bool b)
std::cerr << "p3ConnectMgr: setIPServers to " << b << std::endl ;
}
void p3ConnectMgr::setTunnelConnection(bool b)
{
allow_tunnel_connection = b ;
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
}
void p3ConnectMgr::setOwnNetConfig(uint32_t netMode, uint32_t visState)
{
/* only change TRY flags */
@ -1495,8 +1503,9 @@ bool p3ConnectMgr::connectAttempt(std::string id, struct sockaddr_in &addr,
#endif
return false;
}
it->second.lastattempt = time(NULL); /* time of last connect attempt */
it->second.lastattempt = time(NULL) + ((time(NULL)*1664525 + 1013904223) % 3);//add a random perturbation between 0 and 2 sec. pseudo random number generator from Wikipedia/Numerical Recipies.
it->second.inConnAttempt = true;
it->second.currentConnAddrAttempt = it->second.connAddrs.front();
it->second.connAddrs.pop_front();
@ -1529,6 +1538,13 @@ bool p3ConnectMgr::connectResult(std::string id, bool success, uint32_t flags)
{
RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/
rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::connectResult() called Connect!: id: " + id);
if (success) {
rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::connectResult() called with SUCCESS.");
} else {
rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::connectResult() called with FAILED.");
}
/* check for existing */
std::map<std::string, peerConnectState>::iterator it;
it = mFriendList.find(id);
@ -1549,13 +1565,14 @@ bool p3ConnectMgr::connectResult(std::string id, bool success, uint32_t flags)
it->second.connAddrs.clear();
netAssistFriend(id, false);
/* update address (will come through from DISC) */
/* update address (will come through from DISC) */
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::connectResult() Connect!: id: " << id << std::endl;
std::cerr << " Success: " << success << " flags: " << flags << std::endl;
#endif
rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::connectResult() Success");
/* change state */
it->second.state |= RS_PEER_S_CONNECTED;
@ -1606,7 +1623,36 @@ bool p3ConnectMgr::connectResult(std::string id, bool success, uint32_t flags)
return true;
}
bool p3ConnectMgr::doNextAttempt(std::string id)
{
RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/
rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::doNextAttempt() called id : " + id);
/* check for existing */
std::map<std::string, peerConnectState>::iterator it;
it = mFriendList.find(id);
if (it == mFriendList.end())
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::connectResult() Failed, missing Friend " << " id: " << id << std::endl;
#endif
return false;
}
it->second.inConnAttempt = false;
if (it->second.connAddrs.size() < 1)
{
return true;
}
it->second.actions |= RS_PEER_CONNECT_REQ;
mStatusChanged = true;
return true;
}
/******************************** Feedback ...... *********************************
@ -1779,7 +1825,7 @@ void p3ConnectMgr::peerStatus(std::string id,
/* Determine Reachability (only advisory) */
if (ownState.netMode & RS_NET_MODE_UDP)
{
if ((details.type & RS_NET_CONN_UDP_DHT_SYNC) ||
if ((details.type & RS_NET_CONN_UDP) ||
(details.type & RS_NET_CONN_TCP_EXTERNAL))
{
/* reachable! */
@ -1849,11 +1895,7 @@ void p3ConnectMgr::peerStatus(std::string id,
#endif // P3CONNMGR_NO_TCP_CONNECTIONS
/* notify if they say we can, or we cannot connect ! */
if (details.type & RS_NET_CONN_UDP_DHT_SYNC)
{
retryConnectNotify(id);
}
retryConnectNotify(id);
#else
#endif // P3CONNMGR_NO_AUTO_CONNECTION
@ -1886,132 +1928,7 @@ void p3ConnectMgr::peerConnectRequest(std::string id, struct sockaddr_in radd
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() Try TCP first" << std::endl;
#endif
retryConnectTCP(id);
/******************** UDP PART *****************************/
RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/
if (ownState.netMode & RS_NET_MODE_UNREACHABLE)
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() Unreachable - no UDP connection" << std::endl;
#endif
return;
}
/* look up the id */
std::map<std::string, peerConnectState>::iterator it;
bool isFriend = true;
it = mFriendList.find(id);
if (it == mFriendList.end())
{
/* check Others list */
isFriend = false;
it = mOthersList.find(id);
if (it == mOthersList.end())
{
/* not found - ignore */
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() Peer Not Found - Ignore" << std::endl;
#endif
return;
}
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() Peer is in mOthersList - Ignore" << std::endl;
#endif
return;
}
/* if already connected -> done */
if (it->second.state & RS_PEER_S_CONNECTED)
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() Already connected - Ignore";
std::cerr << std::endl;
#endif
return;
}
time_t now = time(NULL);
/* this is a UDP connection request (DHT only for the moment!) */
if (isValidNet(&(raddr.sin_addr)))
{
/* add the remote address */
peerConnectAddress pca;
pca.ts = now;
pca.type = RS_NET_CONN_UDP_DHT_SYNC;
pca.delay = 0;
if (source == RS_CB_DHT)
{
pca.period = P3CONNMGR_UDP_DHT_DELAY;
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() source = DHT ";
std::cerr << std::endl;
#endif
}
else if (source == RS_CB_PROXY)
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() source = PROXY ";
std::cerr << std::endl;
#endif
pca.period = P3CONNMGR_UDP_PROXY_DELAY;
}
else
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() source = UNKNOWN ";
std::cerr << std::endl;
#endif
/* error! */
pca.period = P3CONNMGR_UDP_PROXY_DELAY;
}
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() period = " << pca.period;
std::cerr << std::endl;
#endif
pca.addr = raddr;
{
/* Log */
std::ostringstream out;
out << "p3ConnectMgr::peerConnectRequest() PushBack UDP Address: id: " << id << " raddr: " << inet_ntoa(pca.addr.sin_addr);
out << ":" << ntohs(pca.addr.sin_port) << " type: " << pca.type << " delay: " << pca.delay << " period: " << pca.period;
out << " ts: " << pca.ts;
rslog(RSL_WARNING, p3connectzone, out.str());
}
/* push to the back ... TCP ones should be tried first */
it->second.connAddrs.push_back(pca);
}
if (it->second.inConnAttempt)
{
/* -> it'll automatically use the addresses */
return;
}
/* start a connection attempt */
if (it->second.connAddrs.size() > 0)
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() Started CONNECT ATTEMPT! id: " << id << std::endl;
#endif
it->second.actions |= RS_PEER_CONNECT_REQ;
mStatusChanged = true;
}
else
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::peerConnectRequest() No addr suitable for CONNECT ATTEMPT! id: " << id << std::endl;
#endif
}
retryConnect(id);
}
@ -2261,29 +2178,27 @@ bool p3ConnectMgr::retryConnectTCP(std::string id)
if (mFriendList.end() == (it = mFriendList.find(id)))
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectTCP() Peer is not Friend" << std::endl;
std::cerr << "p3ConnectMgr::retryConnectTCP() Peer is not Friend" << std::endl;
#endif
return false;
}
/* if already connected -> done */
if (it->second.state & RS_PEER_S_CONNECTED)
if (it->second.state & RS_PEER_S_CONNECTED)
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectTCP() Peer Already Connected" << std::endl;
#endif
return true;
if (it->second.currentConnAddrAttempt.type & RS_NET_CONN_TUNNEL) {
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectTCP() Peer Connected through a tunnel connection, let's try a normal connection." << std::endl;
#endif
} else {
return true;
}
}
/* are the addresses different? */
time_t now = time(NULL);
/* add in attempts ... local(TCP), remote(TCP)
*/
#ifndef P3CONNMGR_NO_TCP_CONNECTIONS
//add the ips off the ipAdressList
//add the ips off the ipAdressList for TCP
std::list<IpAddressTimed> ipList = it->second.getIpAddressList();
for (std::list<IpAddressTimed>::iterator ipListIt = ipList.begin(); ipListIt!=(ipList.end()); ipListIt++) {
#ifdef CONN_DEBUG
@ -2293,30 +2208,95 @@ bool p3ConnectMgr::retryConnectTCP(std::string id)
//check that the address doens't exist already in the connAddrs
bool found = false;
for (std::list<peerConnectAddress>::iterator cit = it->second.connAddrs.begin(); cit != it->second.connAddrs.end(); cit++) {
if (cit->addr.sin_addr.s_addr == ipListIt->ipAddr.sin_addr.s_addr && cit->addr.sin_port == ipListIt->ipAddr.sin_port) {
if (cit->addr.sin_addr.s_addr == ipListIt->ipAddr.sin_addr.s_addr &&
cit->addr.sin_port == ipListIt->ipAddr.sin_port &&
cit->type == RS_NET_CONN_TCP_UNKNOW_TOPOLOGY) {
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectTCP() ip already in the conn addr attempt list." << std::endl;
std::cerr << "p3ConnectMgr::retryConnectTCP() tcp attempt already in list." << std::endl;
#endif
found = true;
break;
}
}
if (!found) {
peerConnectAddress pca;
pca.addr = ipListIt->ipAddr;
pca.type = RS_NET_CONN_TCP_UNKNOW_TOPOLOGY;
pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY;
pca.ts = time(NULL);
pca.period = 0;
it->second.connAddrs.push_back(pca);
}
}
if (!found) {
#ifdef CONN_DEBUG
std::cerr << "Adding tcp connection attempt list." << std::endl;
#endif
peerConnectAddress pca;
pca.addr = ipListIt->ipAddr;
pca.type = RS_NET_CONN_TCP_UNKNOW_TOPOLOGY;
pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY;
pca.ts = time(NULL);
pca.period = 0;
it->second.connAddrs.push_back(pca);
}
}
#endif // P3CONNMGR_NO_TCP_CONNECTIONS
//add the first 2 ips off the ipAdressList for UDP
ipList = it->second.getIpAddressList();
for (std::list<IpAddressTimed>::iterator ipListIt = ipList.begin(); ipListIt!=(ipList.end()); ipListIt++) {
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectTCP() adding ip : " << inet_ntoa(ipListIt->ipAddr.sin_addr);
std::cerr << ":" << ntohs(ipListIt->ipAddr.sin_port) << std::endl;
#endif
//check that the address doens't exist already in the connAddrs
bool found = false;
for (std::list<peerConnectAddress>::iterator cit = it->second.connAddrs.begin(); cit != it->second.connAddrs.end(); cit++) {
if (cit->addr.sin_addr.s_addr == ipListIt->ipAddr.sin_addr.s_addr &&
cit->addr.sin_port == ipListIt->ipAddr.sin_port &&
cit->type == RS_NET_CONN_UDP) {
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectTCP() udp attempt already in list." << std::endl;
#endif
found = true;
break;
}
}
if (!found && !isSameSubnet(&ipListIt->ipAddr.sin_addr, &ownState.currentlocaladdr.sin_addr)) {//add only if in different subnet
#ifdef CONN_DEBUG
std::cerr << "Adding udp connection attempt." << std::endl;
#endif
peerConnectAddress pca;
pca.addr = ipListIt->ipAddr;
pca.type = RS_NET_CONN_UDP;
pca.delay = P3CONNMGR_UDP_DEFAULT_DELAY;
pca.ts = time(NULL);
// pseudo random number generator from Wikipedia/Numerical Recipies.
pca.period = P3CONNMGR_UDP_DEFAULT_TIMEOUT + (time(NULL)*1664525 + 1013904223 % P3CONNMGR_UDP_DEFAULT_TIMEOUT); //add a random timeout between 1 and 2 times P3CONNMGR_UDP_DEFAULT_TIMEOUT
it->second.connAddrs.push_back(pca);
break; //add only one udp address
}
}
//ad the tunnel attempt
bool found = false;
for (std::list<peerConnectAddress>::iterator cit = it->second.connAddrs.begin(); cit != it->second.connAddrs.end(); cit++) {
if (cit->type == RS_NET_CONN_TUNNEL) {
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectTCP() tunnel is already in the list.." << std::endl;
#endif
found = true;
break;
}
}
if (!(it->second.state & RS_PEER_S_CONNECTED) && !found && allow_tunnel_connection)
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectTCP() Add the tunnel connection attempt." << std::endl;
#endif
peerConnectAddress pca;
pca.type = RS_NET_CONN_TUNNEL;
pca.ts = time(NULL);
pca.period = 0;
it->second.connAddrs.push_back(pca);
}
/* flag as last attempt to prevent loop */
it->second.lastattempt = time(NULL);
it->second.lastattempt = time(NULL) + ((time(NULL)*1664525 + 1013904223) % 3);//add a random perturbation between 0 and 2 sec. pseudo random number generator from Wikipedia/Numerical Recipies.
if (it->second.inConnAttempt)
{
@ -2337,7 +2317,7 @@ bool p3ConnectMgr::retryConnectTCP(std::string id)
else
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectTCP() No addr suitable for CONNECT ATTEMPT! " << " id: " << id << std::endl;
std::cerr << "p3ConnectMgr::retryConnectTCP() No addr in the connect attempt list. Not suitable for CONNECT ATTEMPT! " << " id: " << id << std::endl;
#endif
}
return true;
@ -2367,14 +2347,20 @@ bool p3ConnectMgr::retryConnectNotify(std::string id)
/* if already connected -> done */
if (it->second.state & RS_PEER_S_CONNECTED)
{
if (it->second.currentConnAddrAttempt.type & RS_NET_CONN_TUNNEL) {
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectNotify() Peer Already Connected" << std::endl;
std::cerr << "p3ConnectMgr::retryConnectNotify() Peer Connected through a tunnel connection, let's try a normal connection." << std::endl;
#endif
return true;
} else {
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::retryConnectNotify() Peer Already Connected, aborting retryConnect" << std::endl;
#endif
return true;
}
}
/* flag as last attempt to prevent loop */
it->second.lastattempt = time(NULL);
it->second.lastattempt = time(NULL) + ((time(NULL)*1664525 + 1013904223) % 3);//add a random perturbation between 0 and 2 sec. pseudo random number generator from Wikipedia/Numerical Recipies.
if (ownState.netMode & RS_NET_MODE_UNREACHABLE)
{
@ -2771,6 +2757,18 @@ std::list<RsItem *> p3ConnectMgr::saveList(bool &cleanup)
std::cout << "Pushing item for use_extr_addr_finder = " << use_extr_addr_finder << std::endl ;
saveData.push_back(vitem);
// Now save config for network digging strategies
RsConfigKeyValueSet *vitem2 = new RsConfigKeyValueSet ;
RsTlvKeyValue kv2;
kv2.key = "ALLOW_TUNNEL_CONNECTION" ;
kv2.value = (allow_tunnel_connection)?"TRUE":"FALSE" ;
vitem2->tlvkvs.pairs.push_back(kv2) ;
std::cout << "Pushing item for allow_tunnel_connection = " << allow_tunnel_connection << std::endl ;
saveData.push_back(vitem2);
return saveData;
}
@ -2844,7 +2842,11 @@ bool p3ConnectMgr::loadList(std::list<RsItem *> load)
{
use_extr_addr_finder = (vitem->tlvkvs.pairs.front().value == "TRUE") ;
std::cerr << "setting use_extr_addr_finder to " << use_extr_addr_finder << std::endl ;
}
} else if (vitem->tlvkvs.pairs.front().key == "ALLOW_TUNNEL_CONNECTION")
{
allow_tunnel_connection = (vitem->tlvkvs.pairs.front().value == "TRUE") ;
std::cerr << "setting allow_tunnel_connection to " << allow_tunnel_connection << std::endl ;
}
}
@ -3304,3 +3306,11 @@ void peerConnectState::printIpAddressList(std::list<IpAddressTimed> ipTimedList)
#endif
}
}
p3tunnel* p3ConnectMgr::getP3tunnel() {
return mP3tunnel;
}
void p3ConnectMgr::setP3tunnel(p3tunnel *p3tun) {
mP3tunnel = p3tun;
}

View file

@ -33,6 +33,7 @@
//#include "pqi/p3dhtmgr.h"
//#include "pqi/p3upnpmgr.h"
#include "pqi/pqiassist.h"
#include "services/p3tunnel.h"
#include "pqi/p3cfgmgr.h"
@ -80,12 +81,12 @@ const uint32_t RS_NET_MODE_UNREACHABLE = 0x0008;
/* order of attempts ... */
const uint32_t RS_NET_CONN_TCP_ALL = 0x000f;
const uint32_t RS_NET_CONN_UDP_ALL = 0x00f0;
const uint32_t RS_NET_CONN_TUNNEL = 0x0f00;
const uint32_t RS_NET_CONN_TCP_LOCAL = 0x0001;
const uint32_t RS_NET_CONN_TCP_EXTERNAL = 0x0002;
const uint32_t RS_NET_CONN_TCP_UNKNOW_TOPOLOGY = 0x0003;
const uint32_t RS_NET_CONN_UDP_DHT_SYNC = 0x0010;
const uint32_t RS_NET_CONN_UDP_PEER_SYNC = 0x0020; /* coming soon */
const uint32_t RS_NET_CONN_UDP = 0x0010;
/* extra flags */
// not sure if needed yet.
@ -211,6 +212,8 @@ bool getDHTEnabled();
bool getIPServersEnabled() { return use_extr_addr_finder ;}
void setIPServersEnabled(bool b) ;
void getIPServersList(std::list<std::string>& ip_servers) ;
void setTunnelConnection(bool b) ;
bool getTunnelConnection() { return allow_tunnel_connection ;}
bool getNetStatusLocalOk();
bool getNetStatusUpnpOk();
@ -266,6 +269,10 @@ virtual void stunStatus(std::string id, struct sockaddr_in raddr, uint32_t ty
bool connectAttempt(std::string id, struct sockaddr_in &addr,
uint32_t &delay, uint32_t &period, uint32_t &type);
bool connectResult(std::string id, bool success, uint32_t flags);
bool doNextAttempt(std::string id);
p3tunnel* getP3tunnel();
void setP3tunnel(p3tunnel *p3tun);
protected:
@ -365,6 +372,8 @@ private:
p3AuthMgr *mAuthMgr;
p3tunnel *mP3tunnel;
std::map<uint32_t, pqiNetAssistFirewall *> mFwAgents;
std::map<uint32_t, pqiNetAssistConnect *> mDhts;
@ -385,6 +394,7 @@ private:
ExtAddrFinder *mExtAddrFinder ;
bool use_extr_addr_finder ;
bool allow_tunnel_connection ;
/* external Address determination */
//bool mUpnpAddrValid, mStunAddrValid;

View file

@ -291,7 +291,8 @@ virtual int notifyEvent(NetInterface *ni, int event) { return 0; }
const uint32_t PQI_CONNECT_TCP = 0x0001;
const uint32_t PQI_CONNECT_UDP = 0x0002;
const uint32_t PQI_CONNECT_TUNNEL = 0x0003;
const uint32_t PQI_CONNECT_DO_NEXT_ATTEMPT = 0x0004;
/********************** Binary INTERFACE ****************************
* This defines the binary interface used by Network/loopback/file
@ -352,6 +353,9 @@ static const int NET_CONNECT_FAILED = 5;
static const uint32_t NET_PARAM_CONNECT_DELAY = 1;
static const uint32_t NET_PARAM_CONNECT_PERIOD = 2;
static const uint32_t NET_PARAM_CONNECT_TIMEOUT = 3;
//static const uint32_t NET_PARAM_CONNECT_TUNNEL_SOURCE_PEER_ID = 4;
//static const uint32_t NET_PARAM_CONNECT_TUNNEL_RELAY_PEER_ID = 5;
//static const uint32_t NET_PARAM_CONNECT_TUNNEL_DEST_PEER_ID = 6;
class NetInterface
{

View file

@ -216,6 +216,9 @@ int pqihandler::HandleRsItem(RsItem *item, int allowglobal)
out << "pqihandler::HandleSearchItem()";
out << " Cannot send out Global RsItem";
pqioutput(PQL_ALERT, pqihandlerzone, out.str());
#ifdef DEBUG_TICK
std::cerr << out.str();
#endif
delete item;
return -1;
}
@ -225,7 +228,10 @@ int pqihandler::HandleRsItem(RsItem *item, int allowglobal)
std::ostringstream out;
out << "pqihandler::HandleRsItem() checkOutgoingPQItem";
out << " Failed on item: " << std::endl;
item -> print(out);
#ifdef DEBUG_TICK
std::cerr << out.str();
#endif
item -> print(out);
pqioutput(PQL_ALERT, pqihandlerzone, out.str());
delete item;
@ -234,6 +240,9 @@ int pqihandler::HandleRsItem(RsItem *item, int allowglobal)
pqioutput(PQL_DEBUG_BASIC, pqihandlerzone,
"pqihandler::HandleRsItem() Sending to One Channel");
#ifdef DEBUG_TICK
std::cerr << "pqihandler::HandleRsItem() Sending to One Channel" << std::endl;
#endif
// find module.
@ -242,6 +251,9 @@ int pqihandler::HandleRsItem(RsItem *item, int allowglobal)
std::ostringstream out;
out << "pqihandler::HandleRsItem() Invalid chan!";
pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out.str());
#ifdef DEBUG_TICK
std::cerr << out.str();
#endif
delete item;
return -1;
@ -254,6 +266,9 @@ int pqihandler::HandleRsItem(RsItem *item, int allowglobal)
out << "pqihandler::HandleRsItem() sending to chan:";
out << it -> first << std::endl;
pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out.str());
#ifdef DEBUG_TICK
std::cerr << out.str();
#endif
// if yes send on item.
((it -> second) -> pqi) -> SendItem(item);
@ -265,6 +280,9 @@ int pqihandler::HandleRsItem(RsItem *item, int allowglobal)
out << "pqihandler::HandleRsItem()";
out << " Sec not approved";
pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out.str());
#ifdef DEBUG_TICK
std::cerr << out.str();
#endif
delete item;
return -1;
@ -298,6 +316,9 @@ int pqihandler::SendRsRawItem(RsRawItem *ns)
{
pqioutput(PQL_DEBUG_BASIC, pqihandlerzone,
"pqihandler::SendRsRawItem()");
#ifdef DEBUG_TICK
std::cerr << "pqihandler::SendRsRawItem()" << std ::endl;
#endif
return HandleRsItem(ns, 0);
}

View file

@ -66,7 +66,11 @@ int pqiperson::SendItem(RsItem *i)
out << "pqiperson::SendItem()";
if (active)
{
out << " Active: Sending On";
out << " Active: Sending On" << std::endl;
i->print(out, 5);
#ifdef PERSON_DEBUG
std::cerr << out.str() << std::endl;
#endif
return activepqi -> SendItem(i);
}
else
@ -76,6 +80,7 @@ int pqiperson::SendItem(RsItem *i)
out << " Now deleting...";
delete i;
}
pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str());
return 0; // queued.
}
@ -145,6 +150,7 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState)
out << "pqiperson::notifyEvent() Id: " << PeerId();
out << std::endl;
out << "Message: " << newState << " from: " << ni << std::endl;
out << "Active pqi : " << activepqi;
pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str());
}
@ -166,11 +172,11 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState)
out << " ni: " << (it->second)->ni;
out << " in_ni: " << ni;
pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str());
i++;
i++;
if ((it->second)->thisNetInterface(ni))
{
pqi = (it->second);
pqi = (it->second);
type = (it->first);
}
}
@ -180,7 +186,6 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState)
pqioutput(PQL_WARNING, pqipersonzone, "Unknown notfyEvent Source!");
return -1;
}
switch(newState)
{
@ -194,10 +199,10 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState)
if ((active) && (activepqi != pqi)) // already connected - trouble
{
pqioutput(PQL_WARNING, pqipersonzone,
"CONNECT_SUCCESS+active->trouble: shutdown EXISTING->switch to new one!");
"CONNECT_SUCCESS+active-> activing new connection, shutting others");
// This is the RESET that's killing the connections.....
activepqi -> reset();
//activepqi -> reset();
// this causes a recursive call back into this fn.
// which cleans up state.
// we only do this if its not going to mess with new conn.
@ -208,18 +213,21 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState)
pqioutput(PQL_WARNING, pqipersonzone,
"CONNECT_SUCCESS->marking so! (resetting others)");
// mark as active.
// mark as active.
active = true;
activepqi = pqi;
inConnectAttempt = false;
inConnectAttempt = false;
/* reset all other children? (clear up long UDP attempt) */
for(it = kids.begin(); it != kids.end(); it++)
{
if (it->second != activepqi)
{
it->second->reset();
}
std::cerr << "Resetting pqi" << std::endl;
it->second->reset();
} else {
std::cerr << "Active pqi : not resetting." << std::endl;
}
}
return 1;
}
@ -231,22 +239,17 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState)
if (active)
{
if (activepqi == pqi)
if (activepqi == pqi)
{
pqioutput(PQL_WARNING, pqipersonzone,
"CONNECT_FAILED->marking so!");
active = false;
activepqi = NULL;
}
else
{
pqioutput(PQL_WARNING, pqipersonzone,
"CONNECT_FAIL+not activepqi->strange!");
// probably UDP connect has failed,
// TCP connection has been made since attempt started.
return -1;
}
}
} else {
pqioutput(PQL_WARNING, pqipersonzone,
"CONNECT_FAILED-> from an unactive connection, don't flag the peer as not connected, just try next attempt !");
}
}
else
{
pqioutput(PQL_WARNING, pqipersonzone,
@ -254,8 +257,14 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState)
}
/* notify up (But not if we are actually active: rtn -1 case above) */
if (pqipg)
pqipg->notifyConnect(PeerId(), type, false);
if (!active) {
if (pqipg)
pqipg->notifyConnect(PeerId(), type, false);
} else {
if (pqipg)
pqipg->notifyConnect(PeerId(), PQI_CONNECT_DO_NEXT_ATTEMPT, false);
return -1;
}
return 1;
@ -399,6 +408,19 @@ int pqiperson::connect(uint32_t type, struct sockaddr_in raddr, uint32_t delay,
}
pqiconnect *pqiperson::getKid(uint32_t type)
{
std::map<uint32_t, pqiconnect *>::iterator it;
it = kids.find(type);
if (it == kids.end())
{
return NULL;
} else {
return it->second;
}
}
float pqiperson::getRate(bool in)
{
// get the rate from the active one.

View file

@ -122,6 +122,8 @@ int notifyEvent(NetInterface *ni, int event);
virtual float getRate(bool in);
virtual void setMaxRate(bool in, float val);
pqiconnect *getKid(uint32_t type);
private:
std::map<uint32_t, pqiconnect *> kids;

View file

@ -366,6 +366,27 @@ int pqipersongrp::removePeer(std::string id)
return 1;
}
pqiperson *pqipersongrp::getPeer(std::string id)
{
std::map<std::string, SearchModule *>::iterator it;
#ifdef PGRP_DEBUG
std::cerr << " pqipersongrp::getPeer() id: " << id;
std::cerr << std::endl;
#endif
RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/
it = mods.find(id);
if (it != mods.end())
{
SearchModule *mod = it->second;
pqiperson *p = (pqiperson *) mod -> pqi;
return p;
}
return NULL;
}
int pqipersongrp::connectPeer(std::string id)
{
/* get status from p3connectMgr */
@ -432,6 +453,15 @@ int pqipersongrp::connectPeer(std::string id)
#ifdef PGRP_DEBUG
std::cerr << " pqipersongrp::connectPeer() connecting with UDP: Timeout :" << timeout;
std::cerr << std::endl;
#endif
}
else if (type & RS_NET_CONN_TUNNEL)
{
ptype = PQI_CONNECT_TUNNEL;
timeout = period * 2;
#ifdef PGRP_DEBUG
std::cerr << " pqipersongrp::connectPeer() connecting with UDP: Timeout :" << timeout;
std::cerr << std::endl;
#endif
}
else
@ -448,19 +478,27 @@ int pqipersongrp::connectPeer(std::string id)
bool pqipersongrp::notifyConnect(std::string id, uint32_t ptype, bool success)
{
uint32_t type = 0;
uint32_t type = 0;
if (ptype == PQI_CONNECT_TCP)
{
type = RS_NET_CONN_TCP_ALL;
}
else
else if (ptype == PQI_CONNECT_UDP)
{
type = RS_NET_CONN_UDP_ALL;
}
else if (ptype == PQI_CONNECT_TUNNEL)
{
type = RS_NET_CONN_TUNNEL;
}
if (mConnMgr)
mConnMgr->connectResult(id, success, type);
if (mConnMgr) {
if (ptype == PQI_CONNECT_DO_NEXT_ATTEMPT) {
mConnMgr->doNextAttempt(id);
} else {
mConnMgr->connectResult(id, success, type);
}
}
return (NULL != mConnMgr);
}

View file

@ -67,6 +67,7 @@ virtual void statusChange(const std::list<pqipeer> &plist);
/******************* Peer Control **************************/
virtual int addPeer(std::string id); /* can be overloaded for testing */
virtual pqiperson *getPeer(std::string id); /* can be overloaded for testing */
int removePeer(std::string id);
int connectPeer(std::string id);

View file

@ -158,6 +158,7 @@ RsRawItem *p3ServiceServer::outgoing()
item -> print(out);
out << std::endl;
std::cerr << out.str();
pqioutput(PQL_DEBUG_BASIC, pqiservicezone, out.str());
#endif
@ -179,6 +180,7 @@ RsRawItem *p3ServiceServer::outgoing()
item -> print(out);
out << std::endl;
pqioutput(PQL_DEBUG_BASIC, pqiservicezone, out.str());
std::cerr << out.str();
#endif
return item;

View file

@ -57,14 +57,7 @@ const int pqissllistenzone = 49787;
pqissllistenbase::pqissllistenbase(struct sockaddr_in addr, p3AuthMgr *am, p3ConnectMgr *cm)
:laddr(addr), active(false),
/**************** PQI_USE_XPGP ******************/
#if defined(PQI_USE_XPGP)
mAuthMgr((AuthXPGP *) am), mConnMgr(cm)
#else /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
mAuthMgr((AuthSSL *) am), mConnMgr(cm)
#endif /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
{
if (!(mAuthMgr -> active()))
@ -471,14 +464,7 @@ int pqissllistenbase::Extract_Failed_SSL_Certificate(SSL *ssl, struct sockaddr_
"pqissllistenbase::Extract_Failed_SSL_Certificate()");
// Get the Peer Certificate....
/**************** PQI_USE_XPGP ******************/
#if defined(PQI_USE_XPGP)
XPGP *peercert = SSL_get_peer_pgp_certificate(ssl);
#else /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
X509 *peercert = SSL_get_peer_certificate(ssl);
#endif /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
if (peercert == NULL)
{
@ -492,14 +478,7 @@ int pqissllistenbase::Extract_Failed_SSL_Certificate(SSL *ssl, struct sockaddr_
// save certificate... (and ip locations)
// false for outgoing....
/**************** PQI_USE_XPGP ******************/
#if defined(PQI_USE_XPGP)
mAuthMgr->FailedCertificateXPGP(peercert, true);
#else /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
mAuthMgr->FailedCertificate(peercert, true);
#endif /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
return 1;
}
@ -631,14 +610,7 @@ int pqissllistener::completeConnection(int fd, SSL *ssl, struct sockaddr_in &rem
{
// Get the Peer Certificate....
/**************** PQI_USE_XPGP ******************/
#if defined(PQI_USE_XPGP)
XPGP *peercert = SSL_get_peer_pgp_certificate(ssl);
#else /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
X509 *peercert = SSL_get_peer_certificate(ssl);
#endif /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
if (peercert == NULL)
{
@ -653,11 +625,6 @@ int pqissllistener::completeConnection(int fd, SSL *ssl, struct sockaddr_in &rem
// Check cert.
std::string newPeerId;
/**************** PQI_USE_XPGP ******************/
#if defined(PQI_USE_XPGP)
bool certOk = mAuthMgr->ValidateCertificateXPGP(peercert, newPeerId);
#else /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
/****
* As the validation is actually done before this...
@ -666,9 +633,6 @@ int pqissllistener::completeConnection(int fd, SSL *ssl, struct sockaddr_in &rem
bool certOk = mAuthMgr->ValidateCertificate(peercert, newPeerId);
#endif /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
bool found = false;
std::map<std::string, pqissl *>::iterator it;
@ -680,14 +644,7 @@ int pqissllistener::completeConnection(int fd, SSL *ssl, struct sockaddr_in &rem
// bad - shutdown.
// pqissllistenbase will shutdown!
/**************** PQI_USE_XPGP ******************/
#if defined(PQI_USE_XPGP)
XPGP_free(peercert);
#else /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
X509_free(peercert);
#endif /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
return -1;
}
@ -723,27 +680,13 @@ int pqissllistener::completeConnection(int fd, SSL *ssl, struct sockaddr_in &rem
out << std::endl;
out << "pqissllistenbase: Will shut it down!" << std::endl;
pqioutput(PQL_WARNING, pqissllistenzone, out.str());
/**************** PQI_USE_XPGP ******************/
#if defined(PQI_USE_XPGP)
XPGP_free(peercert);
#else /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
X509_free(peercert);
#endif /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
return -1;
}
/* Certificate consumed! */
/**************** PQI_USE_XPGP ******************/
#if defined(PQI_USE_XPGP)
bool certKnown = mAuthMgr->CheckCertificateXPGP(it->first, peercert);
#else /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
bool certKnown = mAuthMgr->CheckCertificate(it->first, peercert);
#endif /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
if (certKnown == false)
{

View file

@ -39,14 +39,7 @@
#include "pqi/pqi_base.h"
#include "pqi/pqilistener.h"
/**************** PQI_USE_XPGP ******************/
#if defined(PQI_USE_XPGP)
#include "pqi/authxpgp.h"
#else /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
#include "pqi/authssl.h"
#endif /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
/***************************** pqi Net SSL Interface *********************************
*/
@ -95,19 +88,8 @@ int Extract_Failed_SSL_Certificate(SSL *ssl, struct sockaddr_in *inaddr);
protected:
/**************** PQI_USE_XPGP ******************/
#if defined(PQI_USE_XPGP)
AuthXPGP *mAuthMgr;
#else /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
AuthSSL *mAuthMgr;
#endif /* X509 Certificates */
/**************** PQI_USE_XPGP ******************/
p3ConnectMgr *mConnMgr;
};

View file

@ -40,12 +40,14 @@ const int pqipersongrpzone = 354;
/********************************** SSL Specific features ***************************/
#include "pqi/pqissl.h"
#include "pqi/pqissltunnel.h"
#include "pqi/pqissllistener.h"
#ifndef PQI_DISABLE_UDP
#include "pqi/pqissludp.h"
#endif
pqilistener * pqisslpersongrp::createListener(struct sockaddr_in laddr)
{
p3AuthMgr *authMgr = getAuthMgr();
@ -81,19 +83,27 @@ pqiperson * pqisslpersongrp::createPerson(std::string id, pqilistener *listener)
pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc);
pqissltunnel *pqitun = new pqissltunnel(pqip, authMgr, mConnMgr);
RsSerialiser *rss3 = new RsSerialiser();
rss3->addSerialType(new RsFileItemSerialiser());
rss3->addSerialType(new RsCacheItemSerialiser());
rss3->addSerialType(new RsServiceSerialiser());
pqiconnect *pqicontun = new pqiconnect(rss3, pqitun);
pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun);
#ifndef PQI_DISABLE_UDP
pqissludp *pqius = new pqissludp(pqip, authMgr, mConnMgr);
pqissludp *pqius = new pqissludp(pqip, authMgr, mConnMgr);
RsSerialiser *rss2 = new RsSerialiser();
rss2->addSerialType(new RsFileItemSerialiser());
rss2->addSerialType(new RsCacheItemSerialiser());
rss2->addSerialType(new RsServiceSerialiser());
RsSerialiser *rss2 = new RsSerialiser();
rss2->addSerialType(new RsFileItemSerialiser());
rss2->addSerialType(new RsCacheItemSerialiser());
rss2->addSerialType(new RsServiceSerialiser());
pqiconnect *pqiusc = new pqiconnect(rss2, pqius);
pqiconnect *pqiusc = new pqiconnect(rss2, pqius);
// add a ssl + proxy interface.
// Add Proxy First.
pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc);
// add a ssl + proxy interface.
// Add Proxy First.
pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc);
#endif
return pqip;

View file

@ -0,0 +1,562 @@
/*
* "$Id: pqissl.cc,v 1.28 2007-03-17 19:32:59 rmf24 Exp $"
*
* 3P/PQI network interface for RetroShare.
*
* Copyright 2004-2006 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 "pqi/pqissltunnel.h"
#include "pqi/pqinetwork.h"
#include "services/p3tunnel.h"
#include "util/rsnet.h"
#include "util/rsdebug.h"
#include <unistd.h>
#include <errno.h>
#include <openssl/err.h>
#include <sstream>
const int pqisslzone = 37714;
#define TUNNEL_WAITING_NOT 0
#define TUNNEL_WAITING_DELAY 1
#define TUNNEL_WAITING_SPAM_PING 2
#define TUNNEL_WAITING_PING_RETURN 3
#define TUNNEL_PASSIVE 0x00
#define TUNNEL_ACTIVE 0x01
#define TUNNEL_START_CONNECTION_DELAY 1
#define TUNNEL_PING_TIMEOUT 6
#define TUNNEL_REPEAT_PING_TIME 2
#define TUNNEL_TIMEOUT_AFTER_RESET 30
#define TUNNEL_TRY_OTHER_CONNECTION_INTERVAL 190 //let's try a normal tcp or udp connection every 190 sec
//const int TUNNEL_LOCAL_FLAG = 0x01;
//const int TUNNEL_REMOTE_FLAG = 0x02;
//const int TUNNEL_UDP_FLAG = 0x02;
//
//static const int PQISSL_MAX_READ_ZERO_COUNT = 20;
//static const int PQISSL_SSL_CONNECT_TIMEOUT = 30;
/********** PQI SSL STUFF ******************************************
*
* A little note on the notifyEvent(FAILED)....
*
* this is called from
* (1) reset if needed!
* (2) Determine_Remote_Address (when all options have failed).
*
* reset() is only called when a TCP/SSL connection has been
* established, and there is an error. If there is a failed TCP
* connection, then an alternative address can be attempted.
*
* reset() is called from
* (1) destruction.
* (2) disconnect()
* (3) bad waiting state.
*
* // TCP/or SSL connection already established....
* (5) pqissltunnel::SSL_Connection_Complete() <- okay -> cos we made a TCP connection already.
* (6) pqissltunnel::accept() <- okay cos something went wrong.
* (7) moretoread()/cansend() <- okay cos
*
*/
pqissltunnel::pqissltunnel(PQInterface *parent, p3AuthMgr *am, p3ConnectMgr *cm)
:NetBinInterface(parent, parent->PeerId()),
mAuthMgr((AuthSSL *) am), mConnMgr(cm)
{
active = false;
waiting = TUNNEL_WAITING_NOT;
{
std::ostringstream out;
out << "pqissltunnel for PeerId: " << PeerId();
rslog(RSL_ALERT, pqisslzone, out.str());
}
if (!(mAuthMgr->isAuthenticated(PeerId()))) {
rslog(RSL_ALERT, pqisslzone,
"pqissltunnel::Warning Certificate Not Approved!");
rslog(RSL_ALERT, pqisslzone,
"\t pqissltunnel will not initialise....");
}
mP3tunnel = mConnMgr->getP3tunnel();
current_data_offset = 0;
curent_data_packet.length = 0;
return;
}
pqissltunnel::~pqissltunnel() {
rslog(RSL_ALERT, pqisslzone,
"pqissltunnel::~pqissltunnel -> destroying pqissl");
stoplistening(); /* remove from pqissllistener only */
reset();
return;
}
/********** Implementation of NetInterface *************************/
int pqissltunnel::connect(struct sockaddr_in raddr) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::connect() called : " << PeerId() << std::endl;
#endif
last_normal_connection_attempt_time = time(NULL);
mConnectTS = time(NULL);
resetTime = time(NULL) - TUNNEL_TIMEOUT_AFTER_RESET;
waiting = TUNNEL_WAITING_DELAY;
return 0;
}
// tells pqilistener to listen for us.
int pqissltunnel::listen()
{
//no use
return 0;
}
int pqissltunnel::stoplistening()
{
//no use
return 1;
}
int pqissltunnel::disconnect()
{
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::disconnect() called : " << PeerId() << std::endl;
#endif
return reset();
}
/* BinInterface version of reset() for pqistreamer */
int pqissltunnel::close()
{
return reset();
}
// put back on the listening queue.
int pqissltunnel::reset()
{
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::reset() called : " << PeerId() << std::endl;
#endif
if (active)
{
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::reset() Reset Required because tunnel was activated !" << std::endl;
std::cerr << "pqissltunnel::reset() Will Attempt notifyEvent(FAILED)" << std::endl;
#endif
waiting = TUNNEL_WAITING_NOT;
active = false;
resetTime = time(NULL);
// clean up the streamer
if (parent()) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::reset() notifyEvent(FAILED)" << std::endl;
#endif
parent() -> notifyEvent(this, NET_CONNECT_FAILED);
}
} else {
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::reset() Reset not required because tunnel was not activated !" << std::endl;
#endif
}
return 1;
}
bool pqissltunnel::connect_parameter(uint32_t type, uint32_t value)
{
{
std::ostringstream out;
out << "pqissltunnel::connect_parameter() Peer: " << PeerId();
out << " type: " << type << "value: " << value;
rslog(RSL_DEBUG_ALL, pqisslzone, out.str());
}
if (type == NET_PARAM_CONNECT_DELAY)
{
std::ostringstream out;
out << "pqissltunnel::connect_parameter() Peer: " << PeerId();
out << " DELAY: " << value;
rslog(RSL_WARNING, pqisslzone, out.str());
return true;
}
else if (type == NET_PARAM_CONNECT_TIMEOUT)
{
std::ostringstream out;
out << "pqissltunnel::connect_parameter() Peer: " << PeerId();
out << " TIMEOUT: " << value;
rslog(RSL_WARNING, pqisslzone, out.str());
return true;
}
return false;
}
/********** End of Implementation of NetInterface ******************/
/********** Implementation of BinInterface **************************
* Only status() + tick() are here ... as they are really related
* to the NetInterface, and not the BinInterface,
*
*/
/* returns ...
* -1 if inactive.
* 0 if connecting.
* 1 if connected.
*/
int pqissltunnel::status()
{
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::status() called." << std::endl;
#endif
if (active) {
std::cerr << " active: " << std::endl;
// print out connection.
std::cerr << "dest : " << PeerId();
std::cerr << "relay : " << relayPeerId;
std::cerr << std::endl;
}
else {
std::cerr << " Waiting for connection!" << std::endl;
}
if (active) {
return 1;
} else if (waiting > 0) {
return 0;
}
return -1;
}
int pqissltunnel::tick()
{
if (active && ((time(NULL) - last_normal_connection_attempt_time) > TUNNEL_TRY_OTHER_CONNECTION_INTERVAL)) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::tick() attempt to connect through a normal tcp or udp connection." << std::endl;
#endif
last_normal_connection_attempt_time = time(NULL);
mConnMgr->retryConnect(parent()->PeerId());
}
if (active && ((time(NULL) - last_ping_send_time) > TUNNEL_REPEAT_PING_TIME)) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::tick() sending a ping." << std::endl;
#endif
last_ping_send_time = time(NULL);;
mP3tunnel->pingTunnelConnection(relayPeerId, parent()->PeerId());
}
if (active && ((time(NULL) - last_packet_time) > TUNNEL_PING_TIMEOUT)) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::tick() no packet received since PING_RECEIVE_TIME_OUT. Connection is broken." << std::endl;
#endif
reset();
}
// continue existing connection attempt.
if (!active)
{
// if we are waiting.. continue the connection (only)
if (waiting > 0)
{
std::cerr << "pqissltunnel::tick() Continuing Connection Attempt!" << std::endl;
ConnectAttempt();
return 1;
}
}
return 1;
}
/********** End of Implementation of BinInterface ******************/
/********** Internals of Tunnel Connection ****************************/
int pqissltunnel::ConnectAttempt()
{
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::ConnectAttempt() called." << std::endl;
#endif
switch(waiting)
{
case TUNNEL_WAITING_NOT:
active = true; /* we're starting this one */
std::cerr << "pqissltunnel::ConnectAttempt() STATE = Not Waiting." << std::endl;
case TUNNEL_WAITING_DELAY:
std::cerr << "pqissltunnel::ConnectAttempt() STATE = Waiting Delay, starting connection" << std::endl;
if ((time(NULL) - mConnectTS) > TUNNEL_START_CONNECTION_DELAY) {
waiting = TUNNEL_WAITING_SPAM_PING;
}
break;
case TUNNEL_WAITING_SPAM_PING:
std::cerr << "pqissltunnel::ConnectAttempt() STATE = Waiting for spamming ping." << std::endl;
Spam_Ping();
waiting = TUNNEL_WAITING_PING_RETURN;
break;
case TUNNEL_WAITING_PING_RETURN:
if ((time(NULL) - mConnectTS) < TUNNEL_PING_TIMEOUT) {
std::cerr << "pqissltunnel::ConnectAttempt() STATE = Waiting for ping reply." << std::endl;
} else {
std::cerr << "pqissltunnel::ConnectAttempt() no ping reply during imparing time. Connection failed." << std::endl;
waiting = TUNNEL_WAITING_NOT;
active = false;
// clean up the streamer
if (parent()) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::reset() Reset not required because tunnel was not activated !" << std::endl;
#endif
parent() -> notifyEvent(this, NET_CONNECT_FAILED);
}
}
break;
default:
std::cerr << "pqissltunnel::ConnectAttempt() STATE = Unknown - Reset" << std::endl;
reset();
break;
}
return -1;
}
void pqissltunnel::Spam_Ping()
{
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::Spam_Ping() starting to spam ping tunnel packet." << std::endl;
#endif
std::list<std::string> peers;
mConnMgr->getOnlineList(peers);
std::list<std::string>::iterator it = peers.begin();
while (it != peers.end()) {
//send a ping to the destination through the relay
if (*it != parent()->PeerId()) {
std::cerr << "sending ping with relay id : " << *it << std::endl;
mP3tunnel->pingTunnelConnection(*it, parent()->PeerId());
}
++it;
}
}
void pqissltunnel::addIncomingPacket(void* encoded_data, int encoded_data_length) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::addIncomingPacket() called." << std::endl;
std::cerr << "pqissltunnel::addIncomingPacket() getRsItemSize(encoded_data) : " << getRsItemSize(encoded_data) << std::endl;
#endif
last_packet_time = time(NULL);
data_with_length data_w_l;
data_w_l.data = (void*)malloc(encoded_data_length) ;
memcpy(data_w_l.data, encoded_data, encoded_data_length);
data_w_l.length = encoded_data_length;
data_packet_queue.push_front(data_w_l);
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::addIncomingPacket() getRsItemSize(data_w_l.data) : " << getRsItemSize(data_w_l.data) << std::endl;
#endif
}
void pqissltunnel::IncommingPingPacket(std::string incRelayPeerId) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::IncommingPingPacket() called with incRelayPeerId : " << incRelayPeerId << std::endl;
#endif
if ((time(NULL) - resetTime) <= TUNNEL_TIMEOUT_AFTER_RESET) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::IncommingPingPacket() a reset occured, don't activate the connection." << std::endl;
#endif
return;
}
last_packet_time = time(NULL);
std::string message = "pqissltunnel::IncommingPingPacket() mConnMgr->isOnline(parent()->PeerId() : ";
if (mConnMgr->isOnline(parent()->PeerId())) {
message += "true";
} else {
message += "false";
}
rslog(RSL_DEBUG_BASIC, pqisslzone, message);
if (active || mConnMgr->isOnline(parent()->PeerId())) {
//connection is already active, or peer is already online don't do nothing
return;
}
//TODO : check if cert is in order before accepting
//activate connection
waiting = TUNNEL_WAITING_NOT;
active = true;
relayPeerId = incRelayPeerId;
if (parent())
{
#ifdef DEBUG_PQISSL_TUNNEL
std::cerr << "pqissltunnel::IncommingPingPacket() Notify the pqiperson.... (Both Connect/Receive)" << parent()->PeerId() <<std::endl;
#endif
rslog(RSL_DEBUG_BASIC, pqisslzone, "pqissltunnel::IncommingPingPacket() Notify the pqiperson.... (Both Connect/Receive)");
parent() -> notifyEvent(this, NET_CONNECT_SUCCESS);
}
}
/********** Implementation of BinInterface **************************
* All the rest of the BinInterface.
*
*/
int pqissltunnel::senddata(void *data, int len)
{
#ifdef DEBUG_PQISSL_TUNNEL
std::cout << "pqissltunnel::senddata() called" << std::endl ;
#endif
if (!active) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cout << "pqissltunnel::senddata() connection is not active" << std::endl ;
#endif
return -1;
}
//create RsTunnelDataItem
RsTunnelDataItem *item = new RsTunnelDataItem;
item->destPeerId = parent()->PeerId();
item->relayPeerId = relayPeerId;
item->sourcePeerId = mConnMgr->getOwnId();
item->PeerId(relayPeerId);
item->connection_accepted = 1;
int oulen;
if (!mAuthMgr->encrypt(item->encoded_data, oulen, data, len, parent()->PeerId())) {
std::cerr << "pqissltunnel::readdata() problem while crypting packet, ignoring it." << std::endl;
return -1;
}
item->encoded_data_len = oulen;
#ifdef DEBUG_PQISSL_TUNNEL
std::cout << "pqissltunnel::senddata() sending item (Putting it into queue)" << std::endl ;
#endif
mP3tunnel->sendItem(item);
return oulen;
}
int pqissltunnel::readdata(void *data, int len)
{
#ifdef DEBUG_PQISSL_TUNNEL
std::cout << "pqissltunnel::readdata() called" << std::endl ;
#endif
//let's see if we got a new packet to read
if (current_data_offset >= curent_data_packet.length) {
//current packet has finished reading, let's pop out a new packet if available
if (data_packet_queue.size() ==0) {
//no more to read
return -1;
} else {
//let's read a new packet
current_data_offset = 0;
//decrypt one packet from the queue and put it into the current data packet.
if (!mAuthMgr->decrypt(curent_data_packet.data, curent_data_packet.length, data_packet_queue.back().data, data_packet_queue.back().length)) {
std::cerr << "pqissltunnel::readdata() problem while decrypting packet, ignoring it." << std::endl;
curent_data_packet.length = 0;
return -1;
}
data_packet_queue.pop_back();
}
}
if (current_data_offset < curent_data_packet.length) {
#ifdef DEBUG_PQISSL_TUNNEL
std::cout << "pqissltunnel::readdata() reading..." << std::endl ;
std::cout << "pqissltunnel::readdata() len : " << len << std::endl ;
std::cout << "pqissltunnel::readdata() current_data_offset : " << current_data_offset << std::endl ;
std::cout << "pqissltunnel::readdata() curent_data_packet.length : " << curent_data_packet.length << std::endl ;
std::cerr << "pqissltunnel::readdata() getRsItemSize(curent_data_packet.data) : " << getRsItemSize(curent_data_packet.data) << std::endl;
#endif
//read from packet
memcpy(data, (void*)((unsigned long int)curent_data_packet.data+(unsigned long int)current_data_offset), len);
current_data_offset += len;
return len;
}
return -1;
}
// dummy function currently.
int pqissltunnel::netstatus()
{
return 1;
}
int pqissltunnel::isactive()
{
return active;
}
bool pqissltunnel::moretoread()
{
//let's see if we got an old packet or a new packet to read
if (current_data_offset >= curent_data_packet.length && data_packet_queue.size() ==0) {
return false;
} else {
return true;
}
}
bool pqissltunnel::cansend()
{
if (!mConnMgr->isOnline(relayPeerId)) {
reset();
return false;
}
return true;
}
std::string pqissltunnel::gethash()
{
std::string dummyhash;
return dummyhash;
}
/********** End of Implementation of BinInterface ******************/

View file

@ -0,0 +1,145 @@
/*
* "$Id: pqissl.h,v 1.18 2007-03-11 14:54:22 rmf24 Exp $"
*
* 3P/PQI network interface for RetroShare.
*
* Copyright 2004-2006 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 MRK_PQI_SSL_TUNNEL_HEADER
#define MRK_PQI_SSL_TUNNEL_HEADER
#include <openssl/ssl.h>
// operating system specific network header.
//#include "pqi/pqinetwork.h"
#include "pqi/pqi_base.h"
#include "pqi/p3connmgr.h"
#include "services/p3tunnel.h"
#include "pqi/authssl.h"
/***************************** pqi Net SSL Interface *********************************
* This provides the base SSL interface class,
* and handles most of the required functionality.
*
* there are a series of small fn's that can be overloaded
* to provide alternative behaviour....
*
* Classes expected to inherit from this are:
*
* pqissllistener -> pqissllistener (tcp only)
* -> pqixpgplistener (tcp only)
*
* pqissl -> pqissltcp
* -> pqissludp
* -> pqixpgptcp
* -> pqixpgpudp
*
*/
class pqissl;
class cert;
class pqissltunnellistener;
struct data_with_length {
int length;
void *data;
};
class pqissltunnel: public NetBinInterface
{
public:
pqissltunnel(PQInterface *parent, p3AuthMgr *am, p3ConnectMgr *cm);
virtual ~pqissltunnel();
// NetInterface
//the addr is not used for the tunnel
virtual int connect(struct sockaddr_in raddr);
virtual int listen();
virtual int stoplistening();
virtual int reset();
virtual int disconnect();
virtual bool connect_parameter(uint32_t type, uint32_t value);
// BinInterface
virtual int tick();
virtual int status();
virtual int senddata(void*, int);
virtual int readdata(void*, int);
virtual int netstatus();
virtual int isactive();
virtual bool moretoread();
virtual bool cansend();
virtual int close(); /* BinInterface version of reset() */
virtual std::string gethash(); /* not used here */
virtual bool bandwidthLimited() { return true ; } // replace by !sameLAN to avoid bandwidth limiting on lAN
//called by the p3tunnel service to add incoming packets that will be read by the read data function.
void addIncomingPacket(void* encoded_data, int data_length);
void IncommingPingPacket(std::string incRelayPeerId);
private:
//if no packet (last_time_packet_time) is received since PING_RECEIVE_TIME_OUT, let's assume the connection is broken
int last_normal_connection_attempt_time;
//if no packet (last_time_packet_time) is received since PING_RECEIVE_TIME_OUT, let's assume the connection is broken
int last_packet_time;
//send a ping on a regular basis
int last_ping_send_time;
int ConnectAttempt();
void Spam_Ping();
int waiting;
bool active;
time_t resetTime;
pqissltunnellistener *pqil;
/* Need Certificate specific functions here! */
time_t mConnectTS;
AuthSSL *mAuthMgr;
p3ConnectMgr *mConnMgr;
p3tunnel *mP3tunnel;
std::list<data_with_length> data_packet_queue;
data_with_length curent_data_packet;
int current_data_offset;
//tunneling details
std::string relayPeerId;
};
#endif // MRK_PQI_SSL_HEADER

View file

@ -167,6 +167,7 @@ int pqistreamer::SendItem(RsItem *si)
out << "pqistreamer::SendItem():" << std::endl;
si -> print(out);
pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str());
std::cerr << out.str();
}
#endif
@ -297,7 +298,10 @@ int pqistreamer::status()
int pqistreamer::queue_outpqi(RsItem *pqi)
{
RsStackMutex stack(streamerMtx) ; // lock out_pkt and out_data
#ifdef DEBUG_PQISTREAMER
std::cerr << "pqistreamer::queue_outpqi() called." << std::endl;
#endif
RsStackMutex stack(streamerMtx) ; // lock out_pkt and out_data
// This is called by different threads, and by threads that are not the handleoutgoing thread,
// so it should be protected by a mutex !!
@ -323,7 +327,10 @@ int pqistreamer::queue_outpqi(RsItem *pqi)
uint32_t pktsize = rsSerialiser->size(pqi);
void *ptr = malloc(pktsize);
if (rsSerialiser->serialise(pqi, ptr, &pktsize))
#ifdef DEBUG_PQISTREAMER
std::cerr << "pqistreamer::queue_outpqi() serializing packet with packet size : " << pktsize << std::endl;
#endif
if (rsSerialiser->serialise(pqi, ptr, &pktsize))
{
if (isCntrl)
{
@ -462,7 +469,9 @@ int pqistreamer::handleoutgoing()
// write packet.
len = getRsItemSize(pkt_wpending);
// std::cout << "Sending Out Pkt of size " << len << " !" << std::endl ;
#ifdef DEBUG_PQISTREAMER
std::cout << "Sending Out Pkt of size " << len << " !" << std::endl;
#endif
if (len != (ss = bio->senddata(pkt_wpending, len)))
{
@ -599,7 +608,10 @@ continue_packet:
int extralen = getRsItemSize(block) - blen;
#ifdef DEBUG_PQISTREAMER
std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet state=" << reading_state << std::endl ;
std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet getRsItemSize(block) = " << getRsItemSize(block) << std::endl ;
std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet extralen = " << extralen << std::endl ;
std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet state=" << reading_state << std::endl ;
std::cerr << "[" << (void*)pthread_self() << "] " << "block 1 : " << (int)(((unsigned char*)block)[0]) << " " << (int)(((unsigned char*)block)[1]) << " " << (int)(((unsigned char*)block)[2]) << " " << (int)(((unsigned char*)block)[3]) << " "
<< (int)(((unsigned char*)block)[4]) << " "
<< (int)(((unsigned char*)block)[5]) << " "
@ -738,7 +750,7 @@ continue_packet:
pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out.str());
}
// std::cerr << "Deserializing packet of size " << pktlen <<std::endl ;
// std::cerr << "Deserializing packet of size " << pktlen <<std::endl ;
uint32_t pktlen = blen+extralen ;
#ifdef DEBUG_PQISTREAMER