First of the V0.6 changes.

- Adding basics for proxy connection.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.6-initdev@6682 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2013-09-03 13:35:39 +00:00
parent 23acb91915
commit 212b4c44c9
19 changed files with 916 additions and 73 deletions

View File

@ -363,6 +363,7 @@ HEADERS += pqi/authssl.h \
pqi/pqisslpersongrp.h \
pqi/pqissltunnel.h \
pqi/pqissludp.h \
pqi/pqisslproxy.h \
pqi/pqistore.h \
pqi/pqistreamer.h \
pqi/pqiqosstreamer.h \
@ -419,6 +420,8 @@ HEADERS += services/p3channels.h \
services/p3bwctrl.h \
services/p3tunnel.h
# services/p3discovery2.h \
HEADERS += distrib/p3distrib.h \
distrib/p3distribsecurity.h
# services/p3blogs.h \
@ -495,6 +498,7 @@ SOURCES += pqi/authgpg.cc \
pqi/pqisslpersongrp.cc \
pqi/pqissltunnel.cc \
pqi/pqissludp.cc \
pqi/pqisslproxy.cc \
pqi/pqistore.cc \
pqi/pqistreamer.cc \
pqi/pqiqosstreamer.cc \
@ -558,6 +562,9 @@ SOURCES += services/p3channels.cc \
services/p3banlist.cc \
services/p3bwctrl.cc \
# services/p3discovery2.cc \
# removed because getPeer() doesn t exist services/p3tunnel.cc
SOURCES += distrib/p3distrib.cc \

View File

@ -85,7 +85,7 @@ const uint32_t P3CONNMGR_UDP_DEFAULT_PERIOD = 30; // this represents how long i
void printConnectState(std::ostream &out, peerConnectState &peer);
peerConnectAddress::peerConnectAddress()
:delay(0), period(0), type(0), flags(0), ts(0)
:delay(0), period(0), type(0), flags(0), ts(0), domain_port(0)
{
sockaddr_clear(&addr);
}
@ -588,7 +588,8 @@ const std::string p3LinkMgrIMPL::getOwnId()
bool p3LinkMgrIMPL::connectAttempt(const std::string &id, struct sockaddr_in &raddr,
struct sockaddr_in &proxyaddr,
struct sockaddr_in &srcaddr,
uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth)
uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth,
std::string &domain_addr, uint16_t &domain_port)
{
RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/
@ -642,6 +643,9 @@ bool p3LinkMgrIMPL::connectAttempt(const std::string &id, struct sockaddr_in &ra
srcaddr = it->second.currentConnAddrAttempt.srcaddr;
bandwidth = it->second.currentConnAddrAttempt.bandwidth;
domain_addr = it->second.currentConnAddrAttempt.domain_addr;
domain_port = it->second.currentConnAddrAttempt.domain_port;
/********* Setup LinkType parameters **********/
#define TRICKLE_LIMIT 2001 // 2kb
@ -1632,6 +1636,29 @@ bool p3LinkMgrIMPL::retryConnectTCP(const std::string &id)
#endif
/* If we reach here, must retry .... extract the required info from p3PeerMgr */
/* first possibility - is it a hidden peer */
if (mPeerMgr->isHiddenPeer(id))
{
struct sockaddr_in proxy_addr;
std::string domain_addr;
uint16_t domain_port;
/* then we just have one connect attempt via the Proxy */
if (mPeerMgr->getProxyAddress(id, proxy_addr, domain_addr, domain_port))
{
RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/
std::map<std::string, peerConnectState>::iterator it;
if (mFriendList.end() != (it = mFriendList.find(id)))
{
locked_ConnectAttempt_ProxyAddress(&(it->second), &proxy_addr, domain_addr, domain_port);
return locked_ConnectAttempt_Complete(&(it->second));
}
}
return false;
}
struct sockaddr_in lAddr;
struct sockaddr_in eAddr;
pqiIpAddrSet histAddrs;
@ -1987,6 +2014,38 @@ void p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS(peerConnectState *peer, std
}
void p3LinkMgrIMPL::locked_ConnectAttempt_ProxyAddress(peerConnectState *peer, struct sockaddr_in *proxy_addr, const std::string &domain_addr, uint16_t domain_port)
{
#ifdef LINKMGR_DEBUG
std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_ProxyAddress() trying address: " << domain_addr << ":" << domain_port << std::endl;
#endif
peerConnectAddress pca;
pca.addr.sin_family = AF_INET;
pca.addr.sin_addr.s_addr = proxy_addr->sin_addr.s_addr;
pca.addr.sin_port = proxy_addr->sin_port;
pca.type = RS_NET_CONN_TCP_HIDDEN;
//for the delay, we add a random time and some more time when the friend list is big
pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY;
pca.ts = time(NULL);
pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD;
sockaddr_clear(&(pca.proxyaddr));
sockaddr_clear(&(pca.srcaddr));
pca.bandwidth = 0;
pca.domain_addr = domain_addr;
pca.domain_port = domain_port;
/* check address validity */
if (locked_CheckPotentialAddr(&(pca.addr), 0))
{
addAddressIfUnique(peer->connAddrs, pca, true);
}
}
void p3LinkMgrIMPL::locked_ConnectAttempt_AddTunnel(peerConnectState *peer)
{
if (!(peer->state & RS_PEER_S_CONNECTED) && mAllowTunnelConnection)

View File

@ -47,6 +47,8 @@ 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 = 0x0004;
const uint32_t RS_NET_CONN_TCP_HIDDEN = 0x0008;
const uint32_t RS_NET_CONN_UDP_DHT_SYNC = 0x0010;
const uint32_t RS_NET_CONN_UDP_PEER_SYNC = 0x0020; /* coming soon */
@ -80,6 +82,10 @@ class peerConnectAddress
struct sockaddr_in proxyaddr;
struct sockaddr_in srcaddr;
uint32_t bandwidth;
// Extra Parameters for Proxy/Hidden connection.
std::string domain_addr;
uint16_t domain_port;
};
class peerConnectState
@ -159,7 +165,8 @@ virtual void removeMonitor(pqiMonitor *mon) = 0;
/****************** Connections *******************/
virtual bool connectAttempt(const std::string &id, struct sockaddr_in &raddr,
struct sockaddr_in &proxyaddr, struct sockaddr_in &srcaddr,
uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth) = 0;
uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth,
std::string &domain_addr, uint16_t &domain_port) = 0;
virtual bool connectResult(const std::string &id, bool success, uint32_t flags, struct sockaddr_in remote_peer_address) = 0;
virtual bool retryConnect(const std::string &id) = 0;
@ -218,7 +225,8 @@ virtual void removeMonitor(pqiMonitor *mon);
/****************** Connections *******************/
virtual bool connectAttempt(const std::string &id, struct sockaddr_in &raddr,
struct sockaddr_in &proxyaddr, struct sockaddr_in &srcaddr,
uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth);
uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth,
std::string &domain_addr, uint16_t &domain_port);
virtual bool connectResult(const std::string &id, bool success, uint32_t flags, struct sockaddr_in remote_peer_address);
virtual bool retryConnect(const std::string &id);
@ -290,6 +298,7 @@ void locked_ConnectAttempt_CurrentAddresses(peerConnectState *peer, struct sock
void locked_ConnectAttempt_HistoricalAddresses(peerConnectState *peer, const pqiIpAddrSet &ipAddrs);
void locked_ConnectAttempt_AddDynDNS(peerConnectState *peer, std::string dyndns, uint16_t dynPort);
void locked_ConnectAttempt_AddTunnel(peerConnectState *peer);
void locked_ConnectAttempt_ProxyAddress(peerConnectState *peer, struct sockaddr_in *proxy_addr, const std::string &domain_addr, uint16_t domain_port);
bool locked_ConnectAttempt_Complete(peerConnectState *peer);

View File

@ -1124,6 +1124,9 @@ bool p3NetMgrIMPL::setNetworkMode(uint32_t netMode)
case RS_NET_MODE_UPNP:
mNetMode |= RS_NET_MODE_TRY_UPNP;
break;
case RS_NET_MODE_HIDDEN:
mNetMode |= RS_NET_MODE_TRY_UDP; // FOR THE MOMENT HIDDEN acts like = UDP.
break;
default:
case RS_NET_MODE_UDP:
mNetMode |= RS_NET_MODE_TRY_UDP;

View File

@ -77,7 +77,8 @@ void printConnectState(std::ostream &out, peerState &peer);
peerState::peerState()
:id("unknown"),
gpg_id("unknown"),
netMode(RS_NET_MODE_UNKNOWN), visState(RS_VIS_STATE_STD), lastcontact(0)
netMode(RS_NET_MODE_UNKNOWN), visState(RS_VIS_STATE_STD), lastcontact(0),
hiddenNode(false), hiddenPort(0)
{
sockaddr_clear(&localaddr);
sockaddr_clear(&serveraddr);
@ -120,6 +121,10 @@ p3PeerMgrIMPL::p3PeerMgrIMPL( const std::string& ssl_own_id,
lastGroupId = 1;
// setup default ProxyServerAddress.
sockaddr_clear(&mProxyServerAddress);
inet_aton("127.0.0.1", &(mProxyServerAddress.sin_addr));
mProxyServerAddress.sin_port = htons(7050);
}
@ -274,6 +279,77 @@ bool p3PeerMgrIMPL::getGpgId(const std::string &ssl_id, std::string &gpgId)
return true;
}
/**** HIDDEN STUFF ****/
bool p3PeerMgrIMPL::isHiddenPeer(const std::string &ssl_id)
{
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
/* check for existing */
std::map<std::string, peerState>::iterator it;
it = mFriendList.find(ssl_id);
if (it == mFriendList.end())
{
return (it->second).hiddenNode;
}
/* is it hidden ?? */
return false;
}
bool p3PeerMgrIMPL::setHiddenDomainPort(const std::string &ssl_id, const std::string &domain_addr, const uint16_t domain_port)
{
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
/* check for existing */
std::map<std::string, peerState>::iterator it;
it = mFriendList.find(ssl_id);
if (it == mFriendList.end())
{
return false;
}
it->second.hiddenDomain = domain_addr;
it->second.hiddenPort = domain_port;
it->second.hiddenNode = true;
return true;
}
bool p3PeerMgrIMPL::setProxyServerAddress(const struct sockaddr_in &proxy_addr)
{
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
mProxyServerAddress = proxy_addr;
return true;
}
bool p3PeerMgrIMPL::getProxyAddress(const std::string &ssl_id, struct sockaddr_in &proxy_addr, std::string &domain_addr, uint16_t &domain_port)
{
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
/* check for existing */
std::map<std::string, peerState>::iterator it;
it = mFriendList.find(ssl_id);
if (it == mFriendList.end())
{
return false;
}
if (!it->second.hiddenNode)
{
return false;
}
domain_addr = it->second.hiddenDomain;
domain_port = it->second.hiddenPort;
proxy_addr = mProxyServerAddress;
return true;
}
// Placeholder until we implement this functionality.
uint32_t p3PeerMgrIMPL::getConnectionType(const std::string &/*sslId*/)
{
@ -1368,6 +1444,9 @@ bool p3PeerMgrIMPL::saveList(bool &cleanup, std::list<RsItem *>& saveData)
(it->second).ipAddrs.mLocal.loadTlv(item->localAddrList);
(it->second).ipAddrs.mExt.loadTlv(item->extAddrList);
item->domain_addr = (it->second).hiddenDomain;
item->domain_port = (it->second).hiddenPort;
saveData.push_back(item);
saveCleanupList.push_back(item);
#ifdef PEER_DEBUG
@ -1494,6 +1573,14 @@ bool p3PeerMgrIMPL::loadList(std::list<RsItem *>& load)
setLocation(pitem->pid, pitem->location);
}
if (pitem->netMode == RS_NET_MODE_HIDDEN)
{
/* set only the hidden stuff */
setHiddenDomainPort(pitem->pid, pitem->domain_addr, pitem->domain_port);
}
else
{
setLocalAddress(pitem->pid, pitem->currentlocaladdr);
setExtAddress(pitem->pid, pitem->currentremoteaddr);
setDynDNS (pitem->pid, pitem->dyndns);
@ -1504,6 +1591,7 @@ bool p3PeerMgrIMPL::loadList(std::list<RsItem *>& load)
addrs.mExt.extractFromTlv(pitem->extAddrList);
updateAddressList(pitem->pid, addrs);
}
delete(*it);

View File

@ -55,20 +55,22 @@ const uint32_t RS_VIS_STATE_BROWN = RS_VIS_STATE_NODISC;
/* Startup Modes (confirmed later) */
const uint32_t RS_NET_MODE_TRYMODE = 0x00f0;
const uint32_t RS_NET_MODE_TRYMODE = 0xff00;
const uint32_t RS_NET_MODE_TRY_EXT = 0x0010;
const uint32_t RS_NET_MODE_TRY_UPNP = 0x0020;
const uint32_t RS_NET_MODE_TRY_UDP = 0x0040;
const uint32_t RS_NET_MODE_TRY_EXT = 0x0100;
const uint32_t RS_NET_MODE_TRY_UPNP = 0x0200;
const uint32_t RS_NET_MODE_TRY_UDP = 0x0400;
const uint32_t RS_NET_MODE_TRY_HIDDEN = 0x0800;
/* Actual State */
const uint32_t RS_NET_MODE_ACTUAL = 0x000f;
const uint32_t RS_NET_MODE_ACTUAL = 0x00ff;
const uint32_t RS_NET_MODE_UNKNOWN = 0x0000;
const uint32_t RS_NET_MODE_EXT = 0x0001;
const uint32_t RS_NET_MODE_UPNP = 0x0002;
const uint32_t RS_NET_MODE_UDP = 0x0004;
const uint32_t RS_NET_MODE_UNREACHABLE = 0x0008;
const uint32_t RS_NET_MODE_HIDDEN = 0x0008;
const uint32_t RS_NET_MODE_UNREACHABLE = 0x0010;
/* flags of peerStatus */
@ -87,9 +89,10 @@ class peerState
std::string id;
std::string gpg_id;
uint32_t netMode; /* EXT / UPNP / UDP / INVALID */
uint32_t netMode; /* EXT / UPNP / UDP / HIDDEN / INVALID */
uint32_t visState; /* STD, GRAY, DARK */
struct sockaddr_in localaddr;
struct sockaddr_in serveraddr;
std::string dyndns;
@ -99,6 +102,10 @@ class peerState
/* list of addresses from various sources */
pqiIpAddrSet ipAddrs;
bool hiddenNode; /* all IP addresses / dyndns must be blank */
std::string hiddenDomain;
uint16_t hiddenPort;
std::string location;
std::string name;
@ -162,6 +169,7 @@ virtual bool setNetworkMode(const std::string &id, uint32_t netMode) = 0;
virtual bool setVisState(const std::string &id, uint32_t visState) = 0;
virtual bool setLocation(const std::string &pid, const std::string &location) = 0;
virtual bool setHiddenDomainPort(const std::string &id, const std::string &domain_addr, const uint16_t domain_port) = 0;
virtual bool updateCurrentAddress(const std::string& id, const pqiIpAddress &addr) = 0;
virtual bool updateLastContact(const std::string& id) = 0;
@ -188,6 +196,11 @@ virtual bool getPeerName(const std::string &ssl_id, std::string &name) = 0;
virtual bool getGpgId(const std::string &sslId, std::string &gpgId) = 0;
virtual uint32_t getConnectionType(const std::string &sslId) = 0;
virtual bool setProxyServerAddress(const struct sockaddr_in &proxy_addr) = 0;
virtual bool isHiddenPeer(const std::string &ssl_id) = 0;
virtual bool getProxyAddress(const std::string &ssl_id, struct sockaddr_in &proxy_addr, std::string &domain_addr, uint16_t &domain_port) = 0;
virtual int getFriendCount(bool ssl, bool online) = 0;
/************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/
@ -253,6 +266,7 @@ virtual bool setNetworkMode(const std::string &id, uint32_t netMode);
virtual bool setVisState(const std::string &id, uint32_t visState);
virtual bool setLocation(const std::string &pid, const std::string &location);
virtual bool setHiddenDomainPort(const std::string &id, const std::string &domain_addr, const uint16_t domain_port);
virtual bool updateCurrentAddress(const std::string& id, const pqiIpAddress &addr);
virtual bool updateLastContact(const std::string& id);
@ -278,6 +292,10 @@ virtual bool getPeerName(const std::string &ssl_id, std::string &name);
virtual bool getGpgId(const std::string &sslId, std::string &gpgId);
virtual uint32_t getConnectionType(const std::string &sslId);
virtual bool setProxyServerAddress(const struct sockaddr_in &proxy_addr);
virtual bool isHiddenPeer(const std::string &ssl_id);
virtual bool getProxyAddress(const std::string &ssl_id, struct sockaddr_in &proxy_addr, std::string &domain_addr, uint16_t &domain_port);
virtual int getFriendCount(bool ssl, bool online);
/************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/
@ -349,6 +367,8 @@ private:
std::list<RsItem *> saveCleanupList; /* TEMPORARY LIST WHEN SAVING */
std::map<std::string, ServicePermissionFlags> mFriendsPermissionFlags ; // permission flags for each gpg key
struct sockaddr_in mProxyServerAddress;
};
#endif // MRK_PQI_PEER_MANAGER_HEADER

View File

@ -238,6 +238,7 @@ class PQInterface: public RateInterface
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_HIDDEN_TCP = 0x0004;
#define BIN_FLAGS_NO_CLOSE 0x0001
@ -322,6 +323,9 @@ static const uint32_t NET_PARAM_CONNECT_BANDWIDTH = 5;
static const uint32_t NET_PARAM_CONNECT_PROXY = 6;
static const uint32_t NET_PARAM_CONNECT_SOURCE = 7;
static const uint32_t NET_PARAM_CONNECT_DOMAIN_ADDRESS = 8;
static const uint32_t NET_PARAM_CONNECT_REMOTE_PORT = 9;
/*!
* ******************** Network INTERFACE ***************************
@ -357,6 +361,7 @@ virtual std::string PeerId() { return peerId; }
virtual int getConnectAddress(struct sockaddr_in &raddr) = 0;
virtual bool connect_parameter(uint32_t type, uint32_t value) = 0;
virtual bool connect_parameter(uint32_t /* type */ , const std::string & /* value */ ) { return false; } // not generally used.
virtual bool connect_additional_address(uint32_t /*type*/, struct sockaddr_in * /*addr*/) { return false; } // only needed by udp.
protected:

View File

@ -500,6 +500,10 @@ void printNetBinID(std::ostream &out, std::string id, uint32_t t)
{
out << "TCP)";
}
else if (t == PQI_CONNECT_HIDDEN_TCP)
{
out << "HTCP";
}
else
{
out << "UDP)";

View File

@ -368,7 +368,8 @@ int pqiperson::stoplistening()
int pqiperson::connect(uint32_t type, struct sockaddr_in raddr,
struct sockaddr_in &proxyaddr, struct sockaddr_in &srcaddr,
uint32_t delay, uint32_t period, uint32_t timeout, uint32_t flags, uint32_t bandwidth)
uint32_t delay, uint32_t period, uint32_t timeout, uint32_t flags, uint32_t bandwidth,
const std::string &domain_addr, uint16_t domain_port)
{
#ifdef PERSON_DEBUG
#endif
@ -417,15 +418,23 @@ int pqiperson::connect(uint32_t type, struct sockaddr_in raddr,
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::connect() setting connect_parameters" << std::endl;
#endif
// These two are universal.
(it->second)->connect_parameter(NET_PARAM_CONNECT_DELAY, delay);
(it->second)->connect_parameter(NET_PARAM_CONNECT_PERIOD, period);
(it->second)->connect_parameter(NET_PARAM_CONNECT_TIMEOUT, timeout);
// these 5 are only used by UDP connections.
(it->second)->connect_parameter(NET_PARAM_CONNECT_PERIOD, period);
(it->second)->connect_parameter(NET_PARAM_CONNECT_FLAGS, flags);
(it->second)->connect_parameter(NET_PARAM_CONNECT_BANDWIDTH, bandwidth);
(it->second)->connect_additional_address(NET_PARAM_CONNECT_PROXY, &proxyaddr);
(it->second)->connect_additional_address(NET_PARAM_CONNECT_SOURCE, &srcaddr);
// These are used by Proxy/Hidden
(it->second)->connect_parameter(NET_PARAM_CONNECT_DOMAIN_ADDRESS, domain_addr);
(it->second)->connect_parameter(NET_PARAM_CONNECT_REMOTE_PORT, domain_port);
(it->second)->connect(raddr);
// flag if we started a new connectionAttempt.

View File

@ -71,6 +71,7 @@ virtual int stoplistening() { return ni -> stoplistening(); }
virtual int reset() { return ni -> reset(); }
virtual int disconnect() { return ni -> reset(); }
virtual bool connect_parameter(uint32_t type, uint32_t value) { return ni -> connect_parameter(type, value);}
virtual bool connect_parameter(uint32_t type, std::string value) { return ni -> connect_parameter(type, value);}
virtual bool connect_additional_address(uint32_t type, struct sockaddr_in *addr) { return ni -> connect_additional_address(type, addr);}
@ -113,7 +114,8 @@ int stoplistening();
int connect(uint32_t type, struct sockaddr_in raddr,
struct sockaddr_in &proxyaddr, struct sockaddr_in &srcaddr,
uint32_t delay, uint32_t period, uint32_t timeout, uint32_t flags, uint32_t bandwidth);
uint32_t delay, uint32_t period, uint32_t timeout, uint32_t flags, uint32_t bandwidth,
const std::string &domain_addr, uint16_t domain_port);
int receiveHeartbeat();
// add in connection method.

View File

@ -546,8 +546,10 @@ int pqipersongrp::connectPeer(std::string id
struct sockaddr_in proxyaddr;
struct sockaddr_in srcaddr;
uint32_t bandwidth;
std::string domain_addr;
uint16_t domain_port;
if (!mLinkMgr->connectAttempt(id, addr, proxyaddr, srcaddr, delay, period, type, flags, bandwidth))
if (!mLinkMgr->connectAttempt(id, addr, proxyaddr, srcaddr, delay, period, type, flags, bandwidth, domain_addr, domain_port))
{
#ifdef PGRP_DEBUG
std::cerr << " pqipersongrp::connectPeer() No Net Address";
@ -563,14 +565,23 @@ int pqipersongrp::connectPeer(std::string id
std::cerr << " period: " << period;
std::cerr << " type: " << type;
std::cerr << " flags: " << flags;
std::cerr << " domain_addr: " << domain_addr;
std::cerr << " domain_port: " << domain_port;
std::cerr << std::endl;
#endif
uint32_t ptype;
if (type & RS_NET_CONN_TCP_ALL)
{
if (type == RS_NET_CONN_TCP_HIDDEN)
{
ptype = PQI_CONNECT_HIDDEN_TCP;
}
else
{
ptype = PQI_CONNECT_TCP;
}
timeout = RS_TCP_STD_TIMEOUT_PERIOD;
#ifdef PGRP_DEBUG
std::cerr << " pqipersongrp::connectPeer() connecting with TCP: Timeout :" << timeout;
@ -604,7 +615,7 @@ int pqipersongrp::connectPeer(std::string id
return 0;
}
p->connect(ptype, addr, proxyaddr, srcaddr, delay, period, timeout, flags, bandwidth);
p->connect(ptype, addr, proxyaddr, srcaddr, delay, period, timeout, flags, bandwidth, domain_addr, domain_port);
return 1;
}

View File

@ -265,6 +265,12 @@ int pqissl::reset()
return 1;
}
bool pqissl::connect_parameter(uint32_t type, const std::string &value)
{
return false;
}
bool pqissl::connect_parameter(uint32_t type, uint32_t value)
{
#ifdef PQISSL_LOG_DEBUG

View File

@ -100,6 +100,7 @@ virtual int reset();
virtual int disconnect();
virtual int getConnectAddress(struct sockaddr_in &raddr);
virtual bool connect_parameter(uint32_t type, const std::string &value);
virtual bool connect_parameter(uint32_t type, uint32_t value);
// BinInterface

View File

@ -39,6 +39,7 @@ const int pqipersongrpzone = 354;
#include "pqi/pqissl.h"
#include "pqi/pqissllistener.h"
#include "pqi/p3peermgr.h"
#ifndef PQI_DISABLE_TUNNEL
#include "pqi/pqissltunnel.h"
@ -48,6 +49,7 @@ const int pqipersongrpzone = 354;
#include "pqi/pqissludp.h"
#endif
#include "pqi/pqisslproxy.h"
pqilistener * pqisslpersongrp::locked_createListener(struct sockaddr_in laddr)
{
@ -71,6 +73,32 @@ pqiperson * pqisslpersongrp::locked_createPerson(std::string id, pqilistener *li
pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, "pqipersongrp::createPerson() PeerId: " + id);
pqiperson *pqip = new pqiperson(id, this);
// If using proxy, then only create a proxy item, otherwise can use any.
if (mPeerMgr->isHiddenPeer(id))
{
pqisslproxy *pqis = new pqisslproxy((pqissllistener *) listener, pqip, mLinkMgr);
/* construct the serialiser ....
* Needs:
* * FileItem
* * FileData
* * ServiceGeneric
*/
ssl_tunnels[id] = pqis ; // keeps for getting crypt info per peer.
RsSerialiser *rss = new RsSerialiser();
rss->addSerialType(new RsFileItemSerialiser());
rss->addSerialType(new RsCacheItemSerialiser());
rss->addSerialType(new RsServiceSerialiser());
pqiconnect *pqisc = new pqiconnect(rss, pqis);
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TCP, pqisc);
}
else
{
pqissl *pqis = new pqissl((pqissllistener *) listener, pqip, mLinkMgr);
/* construct the serialiser ....
@ -91,17 +119,6 @@ pqiperson * pqisslpersongrp::locked_createPerson(std::string id, pqilistener *li
pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc);
#ifndef PQI_DISABLE_TUNNEL
pqissltunnel *pqitun = new pqissltunnel(pqip, mLinkMgr);
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);
#endif
#ifndef PQI_DISABLE_UDP
pqissludp *pqius = new pqissludp(pqip, mLinkMgr);
@ -116,6 +133,7 @@ pqiperson * pqisslpersongrp::locked_createPerson(std::string id, pqilistener *li
// Add Proxy First.
pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc);
#endif
}
return pqip;
}

View File

@ -0,0 +1,486 @@
/*
* pqisslproxy.cc
*
* 3P/PQI network interface for RetroShare.
*
* Copyright 2004-2013 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.1 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/pqisslproxy.h"
#include "pqi/pqinetwork.h"
#include <errno.h>
#include <openssl/err.h>
#include <sstream>
#include "util/rsdebug.h"
#include "util/rsnet.h"
#include "pqi/p3linkmgr.h"
const int pqisslproxyzone = 3517;
#define PROXY_STATE_FAILED 0
#define PROXY_STATE_INIT 1
#define PROXY_STATE_WAITING_METHOD_RESPONSE 2
#define PROXY_STATE_WAITING_SOCKS_RESPONSE 3
#define PROXY_STATE_CONNECTION_COMPLETE 4
pqisslproxy::pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm)
:pqissl(l, parent, lm)
{
sockaddr_clear(&remote_addr);
return;
}
pqisslproxy::~pqisslproxy()
{
rslog(RSL_ALERT, pqisslproxyzone,
"pqisslproxy::~pqisslproxy -> destroying pqisslproxy");
return;
}
int pqisslproxy::Initiate_Connection()
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Initiate_Connection()";
std::cerr << std::endl;
#endif
rslog(RSL_DEBUG_BASIC, pqisslproxyzone,
"pqisslproxy::Initiate_Connection() Connection to Proxy");
/* init proxy state */
mProxyState = PROXY_STATE_INIT;
/* call standard Init_Conn() */
return pqissl::Initiate_Connection();
}
/********* VERY DIFFERENT **********/
int pqisslproxy::Basic_Connection_Complete()
{
rslog(RSL_DEBUG_BASIC, pqisslproxyzone,
"pqisslproxy::Basic_Connection_Complete()...");
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Basic_Connection_Complete() STATE: " << mProxyState;
std::cerr << std::endl;
#endif
int ret = 0;
switch(mProxyState)
{
case PROXY_STATE_INIT:
ret = Proxy_Send_Method(); // checks basic conn, sends Method when able.
break;
case PROXY_STATE_WAITING_METHOD_RESPONSE:
ret = Proxy_Send_Address(); // waits for Method Response, send Address when able.
break;
case PROXY_STATE_WAITING_SOCKS_RESPONSE:
ret = Proxy_Connection_Complete(); // wait for ACK.
break;
case PROXY_STATE_CONNECTION_COMPLETE:
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Basic_Connection_Complete() COMPLETED";
std::cerr << std::endl;
#endif
return 1;
case PROXY_STATE_FAILED:
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED";
std::cerr << std::endl;
#endif
return -1;
}
if (ret < 0)
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED(2)";
std::cerr << std::endl;
#endif
return -1; // FAILURE.
}
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Basic_Connection_Complete() IN PROGRESS";
std::cerr << std::endl;
#endif
// In Progress.
return 0;
}
int pqisslproxy::Proxy_Send_Method()
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Send_Method() Checking pqissl::Basic_Connection_Complete()";
std::cerr << std::endl;
#endif
int ret = pqissl::Basic_Connection_Complete();
if (ret != 1)
{
return ret; // basic connection not complete.
}
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Send_Method() Basic complete, sending Method";
std::cerr << std::endl;
#endif
/* send hello to proxy server */
uint8_t method_hello_data[3] = { 0x05, 0x01, 0x00 }; // [ Ver | nMethods (1) | No Auth Method ]
int sent = send(sockfd, method_hello_data, 3, 0);
if (sent != 3)
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Send_Method() Send Failure";
std::cerr << std::endl;
#endif
return -1;
}
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Send_Method() Send Method Okay";
std::cerr << std::endl;
#endif
mProxyState = PROXY_STATE_WAITING_METHOD_RESPONSE;
return 1;
}
int pqisslproxy::Proxy_Method_Response()
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Method_Response()";
std::cerr << std::endl;
#endif
/* get response from proxy server */
uint8_t method_response[2];
// read from the socket.
int recvd = recv(sockfd, method_response, 2, MSG_WAITALL);
if (recvd != 2)
{
if ((recvd == -1) && (errno == EAGAIN))
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Method_Response() EAGAIN";
std::cerr << std::endl;
#endif
return 0;
}
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Method_Response() Error recving response";
std::cerr << std::endl;
#endif
return -1;
}
// does it make sense?
if (method_response[0] != 0x05)
{
// Error.
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x05. Is: ";
std::cerr << (uint32_t) method_response[0];
std::cerr << std::endl;
#endif
return -1;
}
if (method_response[1] != 0x00)
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x00. Is: ";
std::cerr << (uint32_t) method_response[1];
std::cerr << std::endl;
#endif
// Error.
return -1;
}
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Method_Response() Response Okay";
std::cerr << std::endl;
#endif
return 1;
}
#define MAX_SOCKS_REQUEST_LEN 262 // 4 + 1 + 255 + 2.
int pqisslproxy::Proxy_Send_Address()
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Send_Address() Checking Method Response";
std::cerr << std::endl;
#endif
// Check Method Response.
int ret = Proxy_Method_Response();
if (ret != 1)
{
return ret; // Method Response not complete.
}
uint8_t socks_request[MAX_SOCKS_REQUEST_LEN] =
{ 0x05, // SOCKS VERSION.
0x01, // CONNECT (Tor doesn't support BIND or UDP).
0x00, // RESERVED.
0x03, // ADDRESS TYPE (Domain Name)
0x00, // Length of Domain name... the rest is variable so can't hard code it!
};
/* get the length of the domain name, pack so we can't overflow uint8_t */
uint8_t len = mDomainAddress.length();
socks_request[4] = len;
for(int i = 0; i < len; i++)
{
socks_request[5 + i] = mDomainAddress[i];
}
/* now add the port, being careful with packing */
uint16_t net_port = htons(mRemotePort);
socks_request[5 + len] = ((uint8_t *) &net_port)[0];
socks_request[5 + len + 1] = ((uint8_t *) &net_port)[1];
int pkt_len = 5 + len + 2;
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Send_Address() Sending String: ";
for(int i = 0; i < pkt_len; i++)
std::cerr << (uint32_t) socks_request[i];
std::cerr << std::endl;
#endif
int sent = send(sockfd, socks_request, pkt_len, 0);
if (sent != pkt_len)
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Send_Address() Send Error";
std::cerr << std::endl;
#endif
return -1;
}
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Send_Address() Sent Okay";
std::cerr << std::endl;
#endif
mProxyState = PROXY_STATE_WAITING_SOCKS_RESPONSE;
return 1;
}
int pqisslproxy::Proxy_Connection_Complete()
{
/* get response from proxy server */
/* response is similar format to request - with variable length data */
uint8_t socks_response[MAX_SOCKS_REQUEST_LEN];
int recvd = recv(sockfd, socks_response, 5, MSG_WAITALL);
if (recvd != 5)
{
if ((recvd == -1) && (errno == EAGAIN))
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() EAGAIN";
std::cerr << std::endl;
#endif
return 0;
}
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error";
std::cerr << std::endl;
#endif
return -1;
}
// error checking.
if (socks_response[0] != 0x05)
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[0] != 0x05. is: ";
std::cerr << (uint32_t) socks_response[0];
std::cerr << std::endl;
#endif
// error.
return -1;
}
if (socks_response[1] != 0x00)
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[1] != 0x00. is: ";
std::cerr << (uint32_t) socks_response[1];
std::cerr << std::endl;
#endif
// connection failed.
return -1;
}
int address_bytes = 0;
switch(socks_response[3]) // Address Type.
{
case 0x01:
// IPv4 4 address bytes.
address_bytes = 4;
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv4 Address Type";
std::cerr << std::endl;
#endif
break;
case 0x04:
// IPv6 16 address bytes.
address_bytes = 16;
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv6 Address Type";
std::cerr << std::endl;
#endif
break;
case 0x03:
// Variable address bytes - specified in next byte.
address_bytes = 1 + socks_response[4];
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() Domain Address Type. len: " << address_bytes;
std::cerr << std::endl;
#endif
break;
default:
// unknown error.
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR Unknown Address Type";
std::cerr << std::endl;
#endif
return -1;
break;
}
// read the remaining bytes.
recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, MSG_WAITALL); // address_bytes - 1 + 2...
if (recvd != address_bytes + 1)
{
if ((recvd == -1) && (errno == EAGAIN))
{
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR EAGAIN at end.";
std::cerr << std::endl;
#endif
// Waiting - shouldn't happen.
return 0;
}
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR recving(2)";
std::cerr << std::endl;
#endif
return -1;
}
#ifdef PROXY_DEBUG
std::cerr << "pqisslproxy::Proxy_Connection_Complete() Received String: ";
for(int i = 0; i < 4 + address_bytes + 2; i++)
std::cerr << (uint32_t) socks_response[i];
std::cerr << std::endl;
#endif
// should print address.
// if we get here - connection is good!.
mProxyState = PROXY_STATE_CONNECTION_COMPLETE;
return 1;
}
bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value)
{
if (type == NET_PARAM_CONNECT_DOMAIN_ADDRESS)
{
std::string out;
rs_sprintf(out, "pqisslproxy::connect_parameter() Peer: %s DOMAIN_ADDRESS: %s", PeerId().c_str(), value.c_str());
rslog(RSL_WARNING, pqisslproxyzone, out);
mDomainAddress = value;
std::cerr << out << std::endl;
return true;
}
return pqissl::connect_parameter(type, value);
}
bool pqisslproxy::connect_parameter(uint32_t type, uint32_t value)
{
if (type == NET_PARAM_CONNECT_REMOTE_PORT)
{
std::string out;
rs_sprintf(out, "pqisslproxy::connect_parameter() Peer: %s REMOTE_PORT: %lu", PeerId().c_str(), value);
rslog(RSL_WARNING, pqisslproxyzone, out);
mRemotePort = value;
std::cerr << out << std::endl;
return true;
}
return pqissl::connect_parameter(type, value);
}

View File

@ -0,0 +1,89 @@
/*
* pqisslproxy.h
*
* 3P/PQI network interface for RetroShare.
*
* Copyright 2004-2013 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.1 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_PROXY_HEADER
#define MRK_PQI_SSL_PROXY_HEADER
#include <openssl/ssl.h>
// operating system specific network header.
#include "pqi/pqinetwork.h"
#include <string>
#include <map>
#include "pqi/pqissl.h"
/* pqisslproxy uses SOCKS5 proxy to hidden your own address and connect to peers.
* It uses the Domain Name interface of SOCKS5, as opposed to an IP address.
*/
class pqisslproxy;
class cert;
/* This provides a NetBinInterface, which is
* primarily inherited from pqissl.
* fns declared here are different -> all others are identical.
*/
class pqisslproxy: public pqissl
{
public:
pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm);
virtual ~pqisslproxy();
// NetInterface. Is the same.
// BinInterface. Is the same.
virtual bool connect_parameter(uint32_t type, const std::string &value);
virtual bool connect_parameter(uint32_t type, uint32_t value);
protected:
//Initiate is the same - except it uses the Proxy Address rather than the Peer Address.
// minor tweaks to setup data state.
virtual int Initiate_Connection();
// The real overloading is done in Basic Connection Complete.
// Instead of just checking for an open socket, we need to communicate with the SOCKS5 proxy.
virtual int Basic_Connection_Complete();
// These are the internal steps in setting up the Proxy Connection.
virtual int Proxy_Send_Method();
virtual int Proxy_Method_Response();
virtual int Proxy_Send_Address();
virtual int Proxy_Connection_Complete();
private:
uint32_t mProxyState;
std::string mDomainAddress;
uint16_t mRemotePort;
};
#endif // MRK_PQI_SSL_PROXY_HEADER

View File

@ -1060,6 +1060,9 @@ void RsPeerNetItem::clear()
localAddrList.TlvClear();
extAddrList.TlvClear();
domain_addr.clear();
domain_port = 0;
}
std::ostream &RsPeerNetItem::print(std::ostream &out, uint16_t indent)
@ -1122,6 +1125,9 @@ uint32_t RsPeerConfigSerialiser::sizeNet(RsPeerNetItem *i)
s += i->localAddrList.TlvSize();
s += i->extAddrList.TlvSize();
s += GetTlvStringSize(i->domain_addr);
s += 2; /* domain_port */
return s;
}
@ -1173,6 +1179,10 @@ bool RsPeerConfigSerialiser::serialiseNet(RsPeerNetItem *item, void *data, uint3
ok &= item->localAddrList.SetTlv(data, tlvsize, &offset);
ok &= item->extAddrList.SetTlv(data, tlvsize, &offset);
// New for V0.6.
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_DOMADDR, item->domain_addr);
ok &= setRawUInt16(data, tlvsize, &offset, item->domain_port); /* Mandatory */
if(offset != tlvsize)
{
ok = false;
@ -1241,6 +1251,17 @@ RsPeerNetItem *RsPeerConfigSerialiser::deserialiseNet(void *data, uint32_t *size
ok &= item->localAddrList.GetTlv(data, rssize, &offset);
ok &= item->extAddrList.GetTlv(data, rssize, &offset);
// Allow acceptance of old format.
if (offset == rssize)
{
std::cerr << "RsPeerConfigSerialiser::deserialiseNet() Accepting Old format PeerNetItem" << std::endl;
return item;
}
// New for V0.6.
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_DOMADDR, item->domain_addr);
ok &= getRawUInt16(data, rssize, &offset, &(item->domain_port)); /* Mandatory */
if (offset != rssize)
{

View File

@ -118,6 +118,10 @@ std::ostream &print(std::ostream &out, uint16_t indent = 0);
RsTlvIpAddrSet localAddrList;
RsTlvIpAddrSet extAddrList;
// for proxy connection.
std::string domain_addr;
uint16_t domain_port;
};
class RsPeerServicePermissionItem : public RsItem

View File

@ -157,6 +157,7 @@ const uint16_t TLV_TYPE_IPV4_LOCAL = 0x0080;
const uint16_t TLV_TYPE_IPV4_REMOTE = 0x0081;
const uint16_t TLV_TYPE_IPV4_LAST = 0x0082;
const uint16_t TLV_TYPE_STR_DYNDNS = 0x0083;
const uint16_t TLV_TYPE_STR_DOMADDR = 0x0084;
/*** MORE STRING IDS ****/
const uint16_t TLV_TYPE_STR_GROUPID = 0x00a0;