mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
2863 lines
80 KiB
C++
2863 lines
80 KiB
C++
/*
|
|
* libretroshare/src/pqi: p3peermgr.cc
|
|
*
|
|
* 3P/PQI network interface for RetroShare.
|
|
*
|
|
* Copyright 2007-2011 by Robert Fernie.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License Version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
* USA.
|
|
*
|
|
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
|
*
|
|
*/
|
|
|
|
#include "rsserver/p3face.h"
|
|
#include "util/rsnet.h"
|
|
#include "pqi/authgpg.h"
|
|
#include "pqi/authssl.h"
|
|
|
|
#include "pqi/p3peermgr.h"
|
|
#include "pqi/p3linkmgr.h"
|
|
#include "pqi/p3netmgr.h"
|
|
#include "pqi/p3historymgr.h"
|
|
|
|
//#include "pqi/p3dhtmgr.h" // Only need it for constants.
|
|
//#include "tcponudp/tou.h"
|
|
//#include "util/extaddrfinder.h"
|
|
//#include "util/dnsresolver.h"
|
|
|
|
#include "util/rsprint.h"
|
|
#include "util/rsstring.h"
|
|
#include "util/rsdebug.h"
|
|
|
|
#include "rsitems/rsconfigitems.h"
|
|
|
|
#include "retroshare/rsiface.h" // Needed for rsicontrol (should remove this dependancy)
|
|
#include "retroshare/rspeers.h" // Needed for Group Parameters.
|
|
#include "retroshare/rsbanlist.h" // Needed for banned IPs
|
|
|
|
/* Network setup States */
|
|
|
|
const uint32_t RS_NET_NEEDS_RESET = 0x0000;
|
|
const uint32_t RS_NET_UNKNOWN = 0x0001;
|
|
const uint32_t RS_NET_UPNP_INIT = 0x0002;
|
|
const uint32_t RS_NET_UPNP_SETUP = 0x0003;
|
|
const uint32_t RS_NET_EXT_SETUP = 0x0004;
|
|
const uint32_t RS_NET_DONE = 0x0005;
|
|
const uint32_t RS_NET_LOOPBACK = 0x0006;
|
|
const uint32_t RS_NET_DOWN = 0x0007;
|
|
|
|
const uint32_t MIN_TIME_BETWEEN_NET_RESET = 5;
|
|
|
|
const uint32_t PEER_IP_CONNECT_STATE_MAX_LIST_SIZE = 4;
|
|
|
|
static struct RsLog::logInfo p3peermgrzoneInfo = {RsLog::Default, "p3peermgr"};
|
|
#define p3peermgrzone &p3peermgrzoneInfo
|
|
|
|
/****
|
|
* #define PEER_DEBUG 1
|
|
***/
|
|
|
|
#define MAX_AVAIL_PERIOD 230 //times a peer stay in available state when not connected
|
|
#define MIN_RETRY_PERIOD 140
|
|
|
|
static const std::string kConfigDefaultProxyServerIpAddr = "127.0.0.1";
|
|
static const uint16_t kConfigDefaultProxyServerPortTor = 9050; // standard port.
|
|
static const uint16_t kConfigDefaultProxyServerPortI2P = 4447; // I2Pd's standard port
|
|
|
|
static const std::string kConfigKeyExtIpFinder = "USE_EXTR_IP_FINDER";
|
|
static const std::string kConfigKeyProxyServerIpAddrTor = "PROXY_SERVER_IPADDR";
|
|
static const std::string kConfigKeyProxyServerPortTor = "PROXY_SERVER_PORT";
|
|
static const std::string kConfigKeyProxyServerIpAddrI2P = "PROXY_SERVER_IPADDR_I2P";
|
|
static const std::string kConfigKeyProxyServerPortI2P = "PROXY_SERVER_PORT_I2P";
|
|
|
|
void printConnectState(std::ostream &out, peerState &peer);
|
|
|
|
peerState::peerState()
|
|
:netMode(RS_NET_MODE_UNKNOWN), vs_disc(RS_VS_DISC_FULL), vs_dht(RS_VS_DHT_FULL), lastcontact(0),
|
|
hiddenNode(false), hiddenPort(0), hiddenType(RS_HIDDEN_TYPE_NONE)
|
|
{
|
|
sockaddr_storage_clear(localaddr);
|
|
sockaddr_storage_clear(serveraddr);
|
|
|
|
return;
|
|
}
|
|
|
|
std::string textPeerConnectState(peerState &state)
|
|
{
|
|
std::string out = "Id: " + state.id.toStdString() + "\n";
|
|
rs_sprintf_append(out, "NetMode: %lu\n", state.netMode);
|
|
rs_sprintf_append(out, "VisState: Disc: %u Dht: %u\n", state.vs_disc, state.vs_dht);
|
|
|
|
out += "laddr: ";
|
|
out += sockaddr_storage_tostring(state.localaddr);
|
|
out += "\neaddr: ";
|
|
out += sockaddr_storage_tostring(state.serveraddr);
|
|
out += "\n";
|
|
|
|
return out;
|
|
}
|
|
|
|
|
|
p3PeerMgrIMPL::p3PeerMgrIMPL(const RsPeerId& ssl_own_id, const RsPgpId& gpg_own_id, const std::string& gpg_own_name, const std::string& ssl_own_location)
|
|
:p3Config(), mPeerMtx("p3PeerMgr"), mStatusChanged(false)
|
|
{
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
mLinkMgr = NULL;
|
|
mNetMgr = NULL;
|
|
|
|
/* setup basics of own state */
|
|
mOwnState.id = ssl_own_id ;
|
|
mOwnState.gpg_id = gpg_own_id ;
|
|
mOwnState.name = gpg_own_name ;
|
|
mOwnState.location = ssl_own_location ;
|
|
mOwnState.netMode = RS_NET_MODE_UPNP; // Default to UPNP.
|
|
mOwnState.vs_disc = RS_VS_DISC_FULL;
|
|
mOwnState.vs_dht = RS_VS_DHT_FULL;
|
|
|
|
// setup default ProxyServerAddress.
|
|
// Tor
|
|
sockaddr_storage_clear(mProxyServerAddressTor);
|
|
sockaddr_storage_ipv4_aton(mProxyServerAddressTor,
|
|
kConfigDefaultProxyServerIpAddr.c_str());
|
|
sockaddr_storage_ipv4_setport(mProxyServerAddressTor,
|
|
kConfigDefaultProxyServerPortTor);
|
|
// I2P
|
|
sockaddr_storage_clear(mProxyServerAddressI2P);
|
|
sockaddr_storage_ipv4_aton(mProxyServerAddressI2P,
|
|
kConfigDefaultProxyServerIpAddr.c_str());
|
|
sockaddr_storage_ipv4_setport(mProxyServerAddressI2P,
|
|
kConfigDefaultProxyServerPortI2P);
|
|
|
|
mProxyServerStatusTor = RS_NET_PROXY_STATUS_UNKNOWN ;
|
|
mProxyServerStatusI2P = RS_NET_PROXY_STATUS_UNKNOWN;
|
|
}
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgr() Startup" << std::endl;
|
|
#endif
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
void p3PeerMgrIMPL::setManagers(p3LinkMgrIMPL *linkMgr, p3NetMgrIMPL *netMgr)
|
|
{
|
|
mLinkMgr = linkMgr;
|
|
mNetMgr = netMgr;
|
|
}
|
|
|
|
|
|
bool p3PeerMgrIMPL::setupHiddenNode(const std::string &hiddenAddress, const uint16_t hiddenPort)
|
|
{
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setupHiddenNode()";
|
|
std::cerr << " Address: " << hiddenAddress;
|
|
std::cerr << " Port: " << hiddenPort;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
mOwnState.hiddenNode = true;
|
|
mOwnState.hiddenPort = hiddenPort;
|
|
mOwnState.hiddenDomain = hiddenAddress;
|
|
mOwnState.hiddenType = hiddenDomainToHiddenType(hiddenAddress);
|
|
}
|
|
|
|
forceHiddenNode();
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3PeerMgrIMPL::forceHiddenNode()
|
|
{
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
if (RS_NET_MODE_HIDDEN != mOwnState.netMode)
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::forceHiddenNode() Required!";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
mOwnState.hiddenNode = true;
|
|
mOwnState.hiddenType = hiddenDomainToHiddenType(mOwnState.hiddenDomain);
|
|
|
|
// force external address - otherwise its invalid.
|
|
sockaddr_storage_clear(mOwnState.serveraddr);
|
|
sockaddr_storage_ipv4_aton(mOwnState.serveraddr, "0.0.0.0");
|
|
sockaddr_storage_ipv4_setport(mOwnState.serveraddr, 0);
|
|
}
|
|
|
|
setOwnNetworkMode(RS_NET_MODE_HIDDEN);
|
|
|
|
// switch off DHT too.
|
|
setOwnVisState(mOwnState.vs_disc, RS_VS_DHT_OFF);
|
|
|
|
// Force the Port.
|
|
struct sockaddr_storage loopback;
|
|
sockaddr_storage_clear(loopback);
|
|
sockaddr_storage_ipv4_aton(loopback, "127.0.0.1");
|
|
uint16_t port = sockaddr_storage_port(mOwnState.localaddr);
|
|
sockaddr_storage_ipv4_setport(loopback, port);
|
|
|
|
setLocalAddress(AuthSSL::getAuthSSL()->OwnId(), loopback);
|
|
|
|
mNetMgr->setIPServersEnabled(false);
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3PeerMgrIMPL::setOwnNetworkMode(uint32_t netMode)
|
|
{
|
|
bool changed = false;
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setOwnNetworkMode() :";
|
|
std::cerr << " Existing netMode: " << mOwnState.netMode;
|
|
std::cerr << " Input netMode: " << netMode;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (mOwnState.netMode != (netMode & RS_NET_MODE_ACTUAL))
|
|
{
|
|
mOwnState.netMode = (netMode & RS_NET_MODE_ACTUAL);
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
// Pass on Flags to NetMgr.
|
|
mNetMgr->setNetworkMode((netMode & RS_NET_MODE_ACTUAL));
|
|
return changed;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::setOwnVisState(uint16_t vs_disc, uint16_t vs_dht)
|
|
{
|
|
bool changed = false;
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
std::string out;
|
|
rs_sprintf(out, "p3PeerMgr::setOwnVisState() Existing vis: %u/%u Input vis: %u/%u",
|
|
mOwnState.vs_disc, mOwnState.vs_dht, vs_disc, vs_dht);
|
|
rslog(RSL_WARNING, p3peermgrzone, out);
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << out.c_str() << std::endl;
|
|
#endif
|
|
|
|
if (mOwnState.vs_disc != vs_disc || mOwnState.vs_dht != vs_dht)
|
|
{
|
|
mOwnState.vs_disc = vs_disc;
|
|
mOwnState.vs_dht = vs_dht;
|
|
changed = true;
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
}
|
|
}
|
|
|
|
// Pass on Flags to NetMgr.
|
|
mNetMgr->setVisState(vs_disc, vs_dht);
|
|
|
|
return changed;
|
|
}
|
|
|
|
|
|
void p3PeerMgrIMPL::tick()
|
|
{
|
|
static const time_t INTERVAL_BETWEEN_LOCATION_CLEANING = 300 ; // Remove unused locations and clean IPs every 10 minutes.
|
|
|
|
static time_t last_friends_check = time(NULL) ; // first cleaning after 1 hour.
|
|
|
|
time_t now = time(NULL) ;
|
|
|
|
if(now > INTERVAL_BETWEEN_LOCATION_CLEANING + last_friends_check )
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::tick(): cleaning unused locations." << std::endl ;
|
|
#endif
|
|
|
|
rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::tick() removeUnusedLocations()");
|
|
|
|
removeUnusedLocations() ;
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::tick(): cleaning banned/old IPs." << std::endl ;
|
|
#endif
|
|
removeBannedIps() ;
|
|
|
|
last_friends_check = now ;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************** Network Status *********************************
|
|
* Configuration Loading / Saving.
|
|
*/
|
|
|
|
|
|
const RsPeerId& p3PeerMgrIMPL::getOwnId()
|
|
{
|
|
return AuthSSL::getAuthSSL()->OwnId();
|
|
}
|
|
|
|
|
|
bool p3PeerMgrIMPL::getOwnNetStatus(peerState &state)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
state = mOwnState;
|
|
return true;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::isFriend(const RsPeerId& id)
|
|
{
|
|
#ifdef PEER_DEBUG_COMMON
|
|
std::cerr << "p3PeerMgrIMPL::isFriend(" << id << ") called" << std::endl;
|
|
#endif
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
bool ret = (mFriendList.end() != mFriendList.find(id));
|
|
#ifdef PEER_DEBUG_COMMON
|
|
std::cerr << "p3PeerMgrIMPL::isFriend(" << id << ") returning : " << ret << std::endl;
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::getPeerName(const RsPeerId &ssl_id, std::string &name)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* check for existing */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
it = mFriendList.find(ssl_id);
|
|
if (it == mFriendList.end())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
name = it->second.name + " (" + it->second.location + ")";
|
|
return true;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::getGpgId(const RsPeerId &ssl_id, RsPgpId &gpgId)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* check for existing */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
it = mFriendList.find(ssl_id);
|
|
if (it == mFriendList.end())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
gpgId = it->second.gpg_id;
|
|
return true;
|
|
}
|
|
|
|
/**** HIDDEN STUFF ****/
|
|
|
|
bool p3PeerMgrIMPL::isHidden()
|
|
{
|
|
RS_STACK_MUTEX(mPeerMtx);
|
|
return mOwnState.hiddenNode;
|
|
}
|
|
|
|
/**
|
|
* @brief checks the hidden type of the own peer.
|
|
* @param type type to check
|
|
* @return true when the peer has the same hidden type than type
|
|
*/
|
|
bool p3PeerMgrIMPL::isHidden(const uint32_t type)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
switch (type) {
|
|
case RS_HIDDEN_TYPE_TOR:
|
|
return mOwnState.hiddenType == RS_HIDDEN_TYPE_TOR;
|
|
break;
|
|
case RS_HIDDEN_TYPE_I2P:
|
|
return mOwnState.hiddenType == RS_HIDDEN_TYPE_I2P;
|
|
break;
|
|
default:
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::isHidden(" << type << ") unkown type -> false";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::isHiddenPeer(const RsPeerId &ssl_id)
|
|
{
|
|
return isHiddenPeer(ssl_id, RS_HIDDEN_TYPE_NONE);
|
|
}
|
|
|
|
/**
|
|
* @brief checks the hidden type of a given ssl id. When type RS_HIDDEN_TYPE_NONE is choosen it returns the 'hiddenNode' value instead
|
|
* @param ssl_id to check
|
|
* @param type type to check. Use RS_HIDDEN_TYPE_NONE to check 'hiddenNode' value
|
|
* @return true when the peer has the same hidden type than type
|
|
*/
|
|
bool p3PeerMgrIMPL::isHiddenPeer(const RsPeerId &ssl_id, const uint32_t type)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* check for existing */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
it = mFriendList.find(ssl_id);
|
|
if (it == mFriendList.end())
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::isHiddenPeer(" << ssl_id << ") Missing Peer => false";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::isHiddenPeer(" << ssl_id << ") = " << (it->second).hiddenNode;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
switch (type) {
|
|
case RS_HIDDEN_TYPE_TOR:
|
|
return (it->second).hiddenType == RS_HIDDEN_TYPE_TOR;
|
|
break;
|
|
case RS_HIDDEN_TYPE_I2P:
|
|
return (it->second).hiddenType == RS_HIDDEN_TYPE_I2P;
|
|
break;
|
|
default:
|
|
return (it->second).hiddenNode;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool hasEnding (std::string const &fullString, std::string const &ending) {
|
|
if (fullString.length() < ending.length())
|
|
return false;
|
|
|
|
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
|
|
}
|
|
|
|
/**
|
|
* @brief resolves the hidden type (tor or i2p) from a domain
|
|
* @param domain to check
|
|
* @return RS_HIDDEN_TYPE_TOR, RS_HIDDEN_TYPE_I2P or RS_HIDDEN_TYPE_NONE
|
|
*
|
|
* Tor: ^[a-z2-7]{16}\.onion$
|
|
*
|
|
* I2P: There is more than one address:
|
|
* - pub. key in base64
|
|
* - hash in base32 ( ^[a-z2-7]{52}\.b32\.i2p$ )
|
|
* - "normal" .i2p domains
|
|
*/
|
|
uint32_t p3PeerMgrIMPL::hiddenDomainToHiddenType(const std::string &domain)
|
|
{
|
|
if(hasEnding(domain, ".onion"))
|
|
return RS_HIDDEN_TYPE_TOR;
|
|
if(hasEnding(domain, ".i2p"))
|
|
return RS_HIDDEN_TYPE_I2P;
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::hiddenDomainToHiddenType() unknown hidden type: " << domain;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return RS_HIDDEN_TYPE_UNKNOWN;
|
|
}
|
|
|
|
/**
|
|
* @brief returns the hidden type of a peer
|
|
* @param ssl_id peer id
|
|
* @return hidden type
|
|
*/
|
|
uint32_t p3PeerMgrIMPL::getHiddenType(const RsPeerId &ssl_id)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
if (ssl_id == AuthSSL::getAuthSSL()->OwnId())
|
|
return mOwnState.hiddenType;
|
|
|
|
/* check for existing */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
it = mFriendList.find(ssl_id);
|
|
if (it == mFriendList.end())
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::getHiddenType(" << ssl_id << ") Missing Peer => false";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::getHiddenType(" << ssl_id << ") = " << (it->second).hiddenType;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return (it->second).hiddenType;
|
|
}
|
|
|
|
/**
|
|
* @brief sets hidden domain and port for a given ssl ID
|
|
* @param ssl_id peer to set domain and port for
|
|
* @param domain_addr
|
|
* @param domain_port
|
|
* @return true on success
|
|
*/
|
|
bool p3PeerMgrIMPL::setHiddenDomainPort(const RsPeerId &ssl_id, const std::string &domain_addr, const uint16_t domain_port)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort()";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
std::string domain = domain_addr;
|
|
// trim whitespace!
|
|
size_t pos = domain.find_last_not_of(" \t\n");
|
|
if (std::string::npos != pos)
|
|
{
|
|
domain = domain.substr(0, pos + 1);
|
|
}
|
|
pos = domain.find_first_not_of(" \t\n");
|
|
if (std::string::npos != pos)
|
|
{
|
|
domain = domain.substr(pos);
|
|
}
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
|
|
if (ssl_id == AuthSSL::getAuthSSL()->OwnId())
|
|
{
|
|
mOwnState.hiddenNode = true;
|
|
mOwnState.hiddenDomain = domain;
|
|
mOwnState.hiddenPort = domain_port;
|
|
mOwnState.hiddenType = hiddenDomainToHiddenType(domain);
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort() Set own State";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
/* check for existing */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
it = mFriendList.find(ssl_id);
|
|
if (it == mFriendList.end())
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort() Peer Not Found";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
it->second.hiddenDomain = domain;
|
|
it->second.hiddenPort = domain_port;
|
|
it->second.hiddenNode = true;
|
|
it->second.hiddenType = hiddenDomainToHiddenType(domain);
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort() Set Peers State";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief sets the proxy server address for a hidden service
|
|
* @param type hidden service type
|
|
* @param proxy_addr proxy address
|
|
* @return true on success
|
|
*/
|
|
bool p3PeerMgrIMPL::setProxyServerAddress(const uint32_t type, const struct sockaddr_storage &proxy_addr)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
switch (type) {
|
|
case RS_HIDDEN_TYPE_I2P:
|
|
if (!sockaddr_storage_same(mProxyServerAddressI2P, proxy_addr))
|
|
{
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
mProxyServerAddressI2P = proxy_addr;
|
|
}
|
|
break;
|
|
case RS_HIDDEN_TYPE_TOR:
|
|
if (!sockaddr_storage_same(mProxyServerAddressTor, proxy_addr))
|
|
{
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
mProxyServerAddressTor = proxy_addr;
|
|
}
|
|
break;
|
|
case RS_HIDDEN_TYPE_UNKNOWN:
|
|
default:
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setProxyServerAddress() unknown hidden type " << type << " -> false";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::resetOwnExternalAddressList()
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
mOwnState.ipAddrs.mLocal.mAddrs.clear() ;
|
|
mOwnState.ipAddrs.mExt.mAddrs.clear() ;
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
|
|
return true ;
|
|
}
|
|
|
|
/**
|
|
* @brief returs proxy server status for a hidden service proxy
|
|
* @param type hidden service type
|
|
* @param proxy_status
|
|
* @return true on success
|
|
*/
|
|
bool p3PeerMgrIMPL::getProxyServerStatus(const uint32_t type, uint32_t& proxy_status)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
switch (type) {
|
|
case RS_HIDDEN_TYPE_I2P:
|
|
proxy_status = mProxyServerStatusI2P;
|
|
break;
|
|
case RS_HIDDEN_TYPE_TOR:
|
|
proxy_status = mProxyServerStatusTor;
|
|
break;
|
|
case RS_HIDDEN_TYPE_UNKNOWN:
|
|
default:
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::getProxyServerStatus() unknown hidden type " << type << " -> false";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief returs proxy server address for a hidden service proxy
|
|
* @param type hidden service type
|
|
* @param proxy_addr
|
|
* @return true on success
|
|
*/
|
|
bool p3PeerMgrIMPL::getProxyServerAddress(const uint32_t type, struct sockaddr_storage &proxy_addr)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
switch (type) {
|
|
case RS_HIDDEN_TYPE_I2P:
|
|
proxy_addr = mProxyServerAddressI2P;
|
|
break;
|
|
case RS_HIDDEN_TYPE_TOR:
|
|
proxy_addr = mProxyServerAddressTor;
|
|
break;
|
|
case RS_HIDDEN_TYPE_UNKNOWN:
|
|
default:
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::getProxyServerAddress() unknown hidden type " << type << " -> false";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief looks up the proxy address and domain/port that have to be used when connecting to a peer
|
|
* @param ssl_id peer to connect to
|
|
* @param proxy_addr proxy address to be used
|
|
* @param domain_addr domain to connect to
|
|
* @param domain_port port to connect to
|
|
* @return true on success
|
|
*/
|
|
bool p3PeerMgrIMPL::getProxyAddress(const RsPeerId &ssl_id, struct sockaddr_storage &proxy_addr, std::string &domain_addr, uint16_t &domain_port)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* check for existing */
|
|
std::map<RsPeerId, 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;
|
|
|
|
switch (it->second.hiddenType) {
|
|
case RS_HIDDEN_TYPE_I2P:
|
|
proxy_addr = mProxyServerAddressI2P;
|
|
break;
|
|
case RS_HIDDEN_TYPE_TOR:
|
|
proxy_addr = mProxyServerAddressTor;
|
|
break;
|
|
case RS_HIDDEN_TYPE_UNKNOWN:
|
|
default:
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::getProxyAddress() no valid hidden type (" << it->second.hiddenType << ") for peer id " << ssl_id << " -> false";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Placeholder until we implement this functionality.
|
|
uint32_t p3PeerMgrIMPL::getConnectionType(const RsPeerId &/*sslId*/)
|
|
{
|
|
return RS_NET_CONN_TYPE_FRIEND;
|
|
}
|
|
|
|
int p3PeerMgrIMPL::getFriendCount(bool ssl, bool online)
|
|
{
|
|
if (online) {
|
|
// count only online id's
|
|
std::list<RsPeerId> onlineIds;
|
|
mLinkMgr->getOnlineList(onlineIds);
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
std::set<RsPgpId> gpgIds;
|
|
int count = 0;
|
|
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
for(it = mFriendList.begin(); it != mFriendList.end(); ++it) {
|
|
if (online && std::find(onlineIds.begin(), onlineIds.end(), it->first) == onlineIds.end()) {
|
|
continue;
|
|
}
|
|
if (ssl) {
|
|
// count ssl id's only
|
|
count++;
|
|
} else {
|
|
// count unique gpg id's
|
|
gpgIds.insert(it->second.gpg_id);
|
|
}
|
|
}
|
|
|
|
return ssl ? count : gpgIds.size();
|
|
}
|
|
|
|
if (ssl) {
|
|
// count all ssl id's
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
return mFriendList.size();
|
|
}
|
|
|
|
// count all gpg id's
|
|
std::list<RsPgpId> gpgIds;
|
|
AuthGPG::getAuthGPG()->getGPGAcceptedList(gpgIds);
|
|
|
|
// add own gpg id, if we have more than one location
|
|
std::list<RsPeerId> ownSslIds;
|
|
getAssociatedPeers(AuthGPG::getAuthGPG()->getGPGOwnId(), ownSslIds);
|
|
|
|
return gpgIds.size() + ((ownSslIds.size() > 0) ? 1 : 0);
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::getFriendNetStatus(const RsPeerId &id, peerState &state)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* check for existing */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
it = mFriendList.find(id);
|
|
if (it == mFriendList.end())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
state = it->second;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3PeerMgrIMPL::getOthersNetStatus(const RsPeerId &id, peerState &state)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* check for existing */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
it = mOthersList.find(id);
|
|
if (it == mOthersList.end())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
state = it->second;
|
|
return true;
|
|
}
|
|
|
|
int p3PeerMgrIMPL::getConnectAddresses(const RsPeerId &id,
|
|
struct sockaddr_storage &lAddr, struct sockaddr_storage &eAddr,
|
|
pqiIpAddrSet &histAddrs, std::string &dyndns)
|
|
{
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* check for existing */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
it = mFriendList.find(id);
|
|
if (it == mFriendList.end())
|
|
{
|
|
/* ERROR */
|
|
std::cerr << "p3PeerMgrIMPL::getConnectAddresses() ERROR unknown Peer";
|
|
std::cerr << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
lAddr = it->second.localaddr;
|
|
eAddr = it->second.serveraddr;
|
|
histAddrs = it->second.ipAddrs;
|
|
dyndns = it->second.dyndns;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
bool p3PeerMgrIMPL::haveOnceConnected()
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* check for existing */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
for(it = mFriendList.begin(); it != mFriendList.end(); ++it)
|
|
{
|
|
if (it->second.lastcontact > 0)
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::haveOnceConnected() lastcontact: ";
|
|
std::cerr << time(NULL) - it->second.lastcontact << " for id: " << it->first;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::haveOnceConnected() all Last Contacts = 0";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
|
|
bool p3PeerMgrIMPL::addFriend(const RsPeerId& input_id, const RsPgpId& input_gpg_id, uint32_t netMode, uint16_t vs_disc, uint16_t vs_dht, time_t lastContact,ServicePermissionFlags service_flags)
|
|
{
|
|
bool notifyLinkMgr = false;
|
|
RsPeerId id = input_id ;
|
|
RsPgpId gpg_id = input_gpg_id ;
|
|
|
|
rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::addFriend() id: " + id.toStdString());
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
|
|
if (id == AuthSSL::getAuthSSL()->OwnId())
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::addFriend() cannot add own id as a friend." << std::endl;
|
|
#endif
|
|
/* (1) already exists */
|
|
return false;
|
|
}
|
|
/* so four possibilities
|
|
* (1) already exists as friend -> do nothing.
|
|
* (2) is in others list -> move over.
|
|
* (3) is non-existant -> create new one.
|
|
*/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::addFriend() " << id << "; gpg_id : " << gpg_id << std::endl;
|
|
#endif
|
|
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
if (mFriendList.end() != mFriendList.find(id))
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::addFriend() Already Exists" << std::endl;
|
|
#endif
|
|
/* (1) already exists */
|
|
return true;
|
|
}
|
|
|
|
//Authentication is now tested at connection time, we don't store the ssl cert anymore
|
|
//
|
|
if (!AuthGPG::getAuthGPG()->isGPGAccepted(gpg_id) && gpg_id != AuthGPG::getAuthGPG()->getGPGOwnId())
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::addFriend() gpg is not accepted" << std::endl;
|
|
#endif
|
|
/* no auth */
|
|
return false;
|
|
}
|
|
|
|
|
|
/* check if it is in others */
|
|
if (mOthersList.end() != (it = mOthersList.find(id)))
|
|
{
|
|
/* (2) in mOthersList -> move over */
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::addFriend() Move from Others" << std::endl;
|
|
#endif
|
|
|
|
mFriendList[id] = it->second;
|
|
mOthersList.erase(it);
|
|
|
|
it = mFriendList.find(id);
|
|
|
|
/* setup connectivity parameters */
|
|
it->second.vs_disc = vs_disc;
|
|
it->second.vs_dht = vs_dht;
|
|
|
|
it->second.netMode = netMode;
|
|
it->second.lastcontact = lastContact;
|
|
|
|
mStatusChanged = true;
|
|
|
|
notifyLinkMgr = true;
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
}
|
|
else
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::addFriend() Creating New Entry" << std::endl;
|
|
#endif
|
|
|
|
/* create a new entry */
|
|
peerState pstate;
|
|
|
|
pstate.id = id;
|
|
pstate.gpg_id = gpg_id;
|
|
pstate.name = AuthGPG::getAuthGPG()->getGPGName(gpg_id);
|
|
|
|
pstate.vs_disc = vs_disc;
|
|
pstate.vs_dht = vs_dht;
|
|
pstate.netMode = netMode;
|
|
pstate.lastcontact = lastContact;
|
|
|
|
/* addr & timestamps -> auto cleared */
|
|
|
|
mFriendList[id] = pstate;
|
|
|
|
mStatusChanged = true;
|
|
|
|
notifyLinkMgr = true;
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
}
|
|
}
|
|
|
|
if (notifyLinkMgr)
|
|
{
|
|
mLinkMgr->addFriend(id, vs_dht != RS_VS_DHT_OFF);
|
|
}
|
|
|
|
service_flags &= servicePermissionFlags(gpg_id) ; // Always reduce the permissions.
|
|
setServicePermissionFlags(gpg_id,service_flags) ;
|
|
|
|
#ifdef PEER_DEBUG
|
|
printPeerLists(std::cerr);
|
|
mLinkMgr->printPeerLists(std::cerr);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::removeFriend(const RsPgpId &id)
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::removeFriend() for id : " << id << std::endl;
|
|
std::cerr << "p3PeerMgrIMPL::removeFriend() mFriendList.size() : " << mFriendList.size() << std::endl;
|
|
#endif
|
|
|
|
rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::removeFriend() id: " + id.toStdString());
|
|
|
|
std::list<RsPeerId> sslid_toRemove; // This is a list of SSLIds.
|
|
rsPeers->getAssociatedSSLIds(id,sslid_toRemove) ;
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* move to othersList */
|
|
//bool success = false;
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
//remove ssl and gpg_ids
|
|
for(it = mFriendList.begin(); it != mFriendList.end(); ++it)
|
|
{
|
|
if (find(sslid_toRemove.begin(),sslid_toRemove.end(),it->second.id) != sslid_toRemove.end())
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::removeFriend() friend found in the list." << id << std::endl;
|
|
#endif
|
|
peerState peer = it->second;
|
|
|
|
sslid_toRemove.push_back(it->second.id);
|
|
|
|
mOthersList[it->second.id] = peer;
|
|
mStatusChanged = true;
|
|
|
|
//success = true;
|
|
}
|
|
}
|
|
|
|
for(std::list<RsPeerId>::iterator rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit)
|
|
if (mFriendList.end() != (it = mFriendList.find(*rit)))
|
|
mFriendList.erase(it);
|
|
|
|
std::map<RsPgpId,ServicePermissionFlags>::iterator it2 = mFriendsPermissionFlags.find(id) ;
|
|
|
|
if(it2 != mFriendsPermissionFlags.end())
|
|
mFriendsPermissionFlags.erase(it2);
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::removeFriend() new mFriendList.size() : " << mFriendList.size() << std::endl;
|
|
#endif
|
|
}
|
|
|
|
std::list<RsPeerId>::iterator rit;
|
|
for(rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit)
|
|
{
|
|
mLinkMgr->removeFriend(*rit);
|
|
}
|
|
|
|
/* remove id from all groups */
|
|
|
|
std::list<RsPgpId> ids ;
|
|
ids.push_back(id) ;
|
|
assignPeersToGroup(RsNodeGroupId(), ids, false);
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
|
|
#ifdef PEER_DEBUG
|
|
printPeerLists(std::cerr);
|
|
mLinkMgr->printPeerLists(std::cerr);
|
|
#endif
|
|
|
|
return !sslid_toRemove.empty();
|
|
}
|
|
bool p3PeerMgrIMPL::removeFriend(const RsPeerId &id, bool removePgpId)
|
|
{
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::removeFriend() for id : " << id << std::endl;
|
|
std::cerr << "p3PeerMgrIMPL::removeFriend() mFriendList.size() : " << mFriendList.size() << std::endl;
|
|
#endif
|
|
|
|
rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::removeFriend() id: " + id.toStdString());
|
|
|
|
std::list<RsPeerId> sslid_toRemove; // This is a list of SSLIds.
|
|
std::list<RsPgpId> pgpid_toRemove; // This is a list of SSLIds.
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* move to othersList */
|
|
//bool success = false;
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
//remove ssl and gpg_ids
|
|
for(it = mFriendList.begin(); it != mFriendList.end(); ++it)
|
|
{
|
|
if (it->second.id == id)
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::removeFriend() friend found in the list." << id << std::endl;
|
|
#endif
|
|
peerState peer = it->second;
|
|
|
|
sslid_toRemove.push_back(it->second.id);
|
|
if(removePgpId)
|
|
pgpid_toRemove.push_back(it->second.gpg_id);
|
|
|
|
mOthersList[id] = peer;
|
|
mStatusChanged = true;
|
|
|
|
//success = true;
|
|
}
|
|
}
|
|
|
|
for(std::list<RsPeerId>::iterator rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit)
|
|
if (mFriendList.end() != (it = mFriendList.find(*rit)))
|
|
mFriendList.erase(it);
|
|
|
|
std::map<RsPgpId,ServicePermissionFlags>::iterator it2 ;
|
|
|
|
for(std::list<RsPgpId>::iterator rit = pgpid_toRemove.begin(); rit != pgpid_toRemove.end(); ++rit)
|
|
if (mFriendsPermissionFlags.end() != (it2 = mFriendsPermissionFlags.find(*rit)))
|
|
mFriendsPermissionFlags.erase(it2);
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::removeFriend() new mFriendList.size() : " << mFriendList.size() << std::endl;
|
|
#endif
|
|
}
|
|
|
|
std::list<RsPeerId>::iterator rit;
|
|
for(rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit)
|
|
{
|
|
mLinkMgr->removeFriend(*rit);
|
|
}
|
|
|
|
/* remove id from all groups */
|
|
|
|
assignPeersToGroup(RsNodeGroupId(), pgpid_toRemove, false);
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
|
|
#ifdef PEER_DEBUG
|
|
printPeerLists(std::cerr);
|
|
mLinkMgr->printPeerLists(std::cerr);
|
|
#endif
|
|
|
|
return !sslid_toRemove.empty();
|
|
}
|
|
|
|
|
|
void p3PeerMgrIMPL::printPeerLists(std::ostream &out)
|
|
{
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
out << "p3PeerMgrIMPL::printPeerLists() Friend List";
|
|
out << std::endl;
|
|
|
|
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
for(it = mFriendList.begin(); it != mFriendList.end(); ++it)
|
|
{
|
|
out << "\t SSL ID: " << it->second.id;
|
|
out << "\t GPG ID: " << it->second.gpg_id;
|
|
out << std::endl;
|
|
}
|
|
|
|
out << "p3PeerMgrIMPL::printPeerLists() Others List";
|
|
out << std::endl;
|
|
for(it = mOthersList.begin(); it != mOthersList.end(); ++it)
|
|
{
|
|
out << "\t SSL ID: " << it->second.id;
|
|
out << "\t GPG ID: " << it->second.gpg_id;
|
|
out << std::endl;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
|
|
|
|
/**********************************************************************
|
|
**********************************************************************
|
|
******************** External Setup **********************************
|
|
**********************************************************************
|
|
**********************************************************************/
|
|
|
|
|
|
/* This function should only be called from NetMgr,
|
|
* as it doesn't call back to there.
|
|
*/
|
|
|
|
bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, const struct sockaddr_storage &extAddr)
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress(";
|
|
std::cerr << sockaddr_storage_tostring(localAddr);
|
|
std::cerr << ", ";
|
|
std::cerr << sockaddr_storage_tostring(extAddr);
|
|
std::cerr << ")" << std::endl;
|
|
#endif
|
|
|
|
if(!rsBanList->isAddressAccepted(localAddr, RSBANLIST_CHECKING_FLAGS_BLACKLIST))
|
|
{
|
|
std::cerr << "(SS) Trying to set own IP to a banned IP " << sockaddr_storage_iptostring(localAddr) << ". This probably means that a friend in under traffic re-routing attack." << std::endl;
|
|
return false ;
|
|
}
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
//update ip address list
|
|
pqiIpAddress ipAddressTimed;
|
|
ipAddressTimed.mAddr = localAddr;
|
|
ipAddressTimed.mSeenTime = time(NULL);
|
|
ipAddressTimed.mSrc = 0 ;
|
|
mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed);
|
|
|
|
mOwnState.localaddr = localAddr;
|
|
}
|
|
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
//update ip address list
|
|
pqiIpAddress ipAddressTimed;
|
|
ipAddressTimed.mAddr = extAddr;
|
|
ipAddressTimed.mSeenTime = time(NULL);
|
|
ipAddressTimed.mSrc = 0 ;
|
|
mOwnState.ipAddrs.updateExtAddrs(ipAddressTimed);
|
|
|
|
/* Attempted Fix to MANUAL FORWARD Mode....
|
|
* don't update the server address - if we are in this mode
|
|
*
|
|
* It is okay - if they get it wrong, as we put the address in the address list anyway.
|
|
* This should keep people happy, and allow for misconfiguration!
|
|
*/
|
|
|
|
if (mOwnState.netMode & RS_NET_MODE_TRY_EXT)
|
|
{
|
|
/**** THIS CASE SHOULD NOT BE TRIGGERED ****/
|
|
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port ";
|
|
std::cerr << " as MANUAL FORWARD Mode (ERROR - SHOULD NOT BE TRIGGERED: TRY_EXT_MODE)";
|
|
std::cerr << std::endl;
|
|
std::cerr << "Address is Now: ";
|
|
std::cerr << sockaddr_storage_tostring(mOwnState.serveraddr);
|
|
std::cerr << std::endl;
|
|
}
|
|
else if (mOwnState.netMode & RS_NET_MODE_EXT)
|
|
{
|
|
sockaddr_storage_copyip(mOwnState.serveraddr,extAddr);
|
|
|
|
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port ";
|
|
std::cerr << " as MANUAL FORWARD Mode";
|
|
std::cerr << std::endl;
|
|
std::cerr << "Address is Now: ";
|
|
std::cerr << sockaddr_storage_tostring(mOwnState.serveraddr);
|
|
std::cerr << std::endl;
|
|
}
|
|
else
|
|
{
|
|
mOwnState.serveraddr = extAddr;
|
|
}
|
|
}
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
mLinkMgr->setLocalAddress(localAddr);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
bool p3PeerMgrIMPL::setLocalAddress(const RsPeerId &id, const struct sockaddr_storage &addr)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (id == AuthSSL::getAuthSSL()->OwnId())
|
|
{
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
if (!sockaddr_storage_same(mOwnState.localaddr, addr))
|
|
{
|
|
mOwnState.localaddr = addr;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
|
|
mNetMgr->setLocalAddress(addr);
|
|
mLinkMgr->setLocalAddress(addr);
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
/* check if it is a friend */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
if (mFriendList.end() == (it = mFriendList.find(id)))
|
|
{
|
|
if (mOthersList.end() == (it = mOthersList.find(id)))
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setLocalAddress() cannot add addres info : peer id not found in friend list id: " << id << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/* "it" points to peer */
|
|
if (!sockaddr_storage_same(it->second.localaddr, addr))
|
|
{
|
|
it->second.localaddr = addr;
|
|
changed = true;
|
|
}
|
|
|
|
#if 0
|
|
//update ip address list
|
|
IpAddressTimed ipAddressTimed;
|
|
ipAddressTimed.ipAddr = addr;
|
|
ipAddressTimed.seenTime = time(NULL);
|
|
it->second.updateIpAddressList(ipAddressTimed);
|
|
#endif
|
|
|
|
if (changed) {
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::setExtAddress(const RsPeerId &id, const struct sockaddr_storage &addr)
|
|
{
|
|
bool changed = false;
|
|
uint32_t check_res = 0 ;
|
|
|
|
if(!rsBanList->isAddressAccepted(addr,RSBANLIST_CHECKING_FLAGS_BLACKLIST,&check_res))
|
|
{
|
|
std::cerr << "(SS) trying to set external contact address for peer " << id << " to a banned address " << sockaddr_storage_iptostring(addr )<< std::endl;
|
|
return false ;
|
|
}
|
|
|
|
if (id == AuthSSL::getAuthSSL()->OwnId())
|
|
{
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
if (!sockaddr_storage_same(mOwnState.serveraddr, addr))
|
|
{
|
|
mOwnState.serveraddr = addr;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
mNetMgr->setExtAddress(addr);
|
|
|
|
return changed;
|
|
}
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
/* check if it is a friend */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
if (mFriendList.end() == (it = mFriendList.find(id)))
|
|
{
|
|
if (mOthersList.end() == (it = mOthersList.find(id)))
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setLocalAddress() cannot add addres info : peer id not found in friend list id: " << id << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/* "it" points to peer */
|
|
if (!sockaddr_storage_same(it->second.serveraddr, addr))
|
|
{
|
|
it->second.serveraddr = addr;
|
|
changed = true;
|
|
}
|
|
|
|
#if 0
|
|
//update ip address list
|
|
IpAddressTimed ipAddressTimed;
|
|
ipAddressTimed.ipAddr = addr;
|
|
ipAddressTimed.seenTime = time(NULL);
|
|
it->second.updateIpAddressList(ipAddressTimed);
|
|
#endif
|
|
|
|
if (changed) {
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
|
|
bool p3PeerMgrIMPL::setDynDNS(const RsPeerId &id, const std::string &dyndns)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (id == AuthSSL::getAuthSSL()->OwnId())
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
if (mOwnState.dyndns.compare(dyndns) != 0) {
|
|
mOwnState.dyndns = dyndns;
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
changed = true;
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
/* check if it is a friend */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
if (mFriendList.end() == (it = mFriendList.find(id)))
|
|
{
|
|
if (mOthersList.end() == (it = mOthersList.find(id)))
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setDynDNS() cannot add dyn dns info : peer id not found in friend list id: " << id << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/* "it" points to peer */
|
|
if (it->second.dyndns.compare(dyndns) != 0) {
|
|
it->second.dyndns = dyndns;
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
changed = true;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
struct ZeroedInt
|
|
{
|
|
ZeroedInt() { n=0 ;}
|
|
int n ;
|
|
};
|
|
|
|
bool p3PeerMgrIMPL::addCandidateForOwnExternalAddress(const RsPeerId &from, const sockaddr_storage &addr)
|
|
{
|
|
// The algorithm is the following:
|
|
// - collect for each friend the last external connection address that is reported
|
|
// - everytime the list is changed, parse it entirely and
|
|
// * emit a warnign when the address is unknown
|
|
// * if multiple peers report the same address => notify the LinkMgr that the external address had changed.
|
|
|
|
sockaddr_storage addr_filtered ;
|
|
sockaddr_storage_clear(addr_filtered) ;
|
|
sockaddr_storage_copyip(addr_filtered,addr) ;
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Own external address is " << sockaddr_storage_iptostring(addr_filtered) << ", as reported by friend " << from << std::endl;
|
|
#endif
|
|
|
|
if(!sockaddr_storage_isExternalNet(addr_filtered))
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << " address is not an external address. Returning false" << std::endl ;
|
|
#endif
|
|
return false ;
|
|
}
|
|
|
|
// Update a list of own IPs:
|
|
// - remove old values for that same peer
|
|
// - remove values for non connected peers
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
mReportedOwnAddresses[from] = addr_filtered ;
|
|
|
|
for(std::map<RsPeerId,sockaddr_storage>::iterator it(mReportedOwnAddresses.begin());it!=mReportedOwnAddresses.end();)
|
|
if(!mLinkMgr->isOnline(it->first))
|
|
{
|
|
std::map<RsPeerId,sockaddr_storage>::iterator tmp(it) ;
|
|
++tmp ;
|
|
mReportedOwnAddresses.erase(it) ;
|
|
it=tmp ;
|
|
}
|
|
else
|
|
++it ;
|
|
|
|
sockaddr_storage current_best_ext_address_guess ;
|
|
uint32_t count ;
|
|
|
|
locked_computeCurrentBestOwnExtAddressCandidate(current_best_ext_address_guess,count) ;
|
|
|
|
std::cerr << "p3PeerMgr:: Current external address is calculated to be: " << sockaddr_storage_iptostring(current_best_ext_address_guess) << " (simultaneously reported by " << count << " peers)." << std::endl;
|
|
}
|
|
|
|
// now current
|
|
|
|
sockaddr_storage own_addr ;
|
|
|
|
if(!mNetMgr->getExtAddress(own_addr))
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << " cannot get current external address. Returning false" << std::endl;
|
|
#endif
|
|
return false ;
|
|
}
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << " current external address is known to be " << sockaddr_storage_iptostring(own_addr) << std::endl;
|
|
#endif
|
|
|
|
// Notify for every friend that has reported a wrong external address, except if that address is in the IP whitelist.
|
|
|
|
if((!rsBanList->isAddressAccepted(addr_filtered,RSBANLIST_CHECKING_FLAGS_WHITELIST)) && (!sockaddr_storage_sameip(own_addr,addr_filtered)))
|
|
{
|
|
std::cerr << " Peer " << from << " reports a connection address (" << sockaddr_storage_iptostring(addr_filtered) <<") that is not your current external address (" << sockaddr_storage_iptostring(own_addr) << "). This is weird." << std::endl;
|
|
|
|
RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, from.toStdString(), sockaddr_storage_iptostring(own_addr), sockaddr_storage_iptostring(addr));
|
|
}
|
|
|
|
// we could also sweep over all connected friends and see if some report a different address.
|
|
|
|
return true ;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::locked_computeCurrentBestOwnExtAddressCandidate(sockaddr_storage& addr, uint32_t& count)
|
|
{
|
|
std::map<sockaddr_storage,ZeroedInt> addr_counts ;
|
|
|
|
for(std::map<RsPeerId,sockaddr_storage>::iterator it(mReportedOwnAddresses.begin());it!=mReportedOwnAddresses.end();++it)
|
|
++addr_counts[it->second].n ;
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Current ext addr statistics:" << std::endl;
|
|
#endif
|
|
|
|
count = 0 ;
|
|
|
|
for(std::map<sockaddr_storage,ZeroedInt>::const_iterator it(addr_counts.begin());it!=addr_counts.end();++it)
|
|
{
|
|
if(uint32_t(it->second.n) > count)
|
|
{
|
|
addr = it->first ;
|
|
count = it->second.n ;
|
|
}
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << sockaddr_storage_iptostring(it->first) << " : " << it->second.n << std::endl;
|
|
#endif
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::getExtAddressReportedByFriends(sockaddr_storage &addr, uint8_t& /*isstable*/)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
uint32_t count ;
|
|
|
|
locked_computeCurrentBestOwnExtAddressCandidate(addr,count) ;
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Estimation count = " << count << ". Trusted? = " << (count>=2) << std::endl;
|
|
#endif
|
|
|
|
return count >= 2 ;// 2 is not conservative enough. 3 should be probably better.
|
|
}
|
|
|
|
static bool cleanIpList(std::list<pqiIpAddress>& lst,const RsPeerId& pid,p3LinkMgr *link_mgr)
|
|
{
|
|
bool changed = false ;
|
|
time_t now = time(NULL) ;
|
|
|
|
for(std::list<pqiIpAddress>::iterator it2(lst.begin());it2 != lst.end();)
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Checking IP address " << sockaddr_storage_iptostring( (*it2).mAddr) << " for peer " << pid << ", age = " << now - (*it2).mSeenTime << std::endl;
|
|
#else
|
|
/* remove unused parameter warnings */
|
|
(void) pid;
|
|
#endif
|
|
if(!link_mgr->checkPotentialAddr( (*it2).mAddr,now - (*it2).mSeenTime))
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << " (SS) Removing Banned/old IP address " << sockaddr_storage_iptostring( (*it2).mAddr) << " from peer " << pid << ", age = " << now - (*it2).mSeenTime << std::endl;
|
|
#endif
|
|
|
|
std::list<pqiIpAddress>::iterator ittmp = it2 ;
|
|
++ittmp ;
|
|
lst.erase(it2) ;
|
|
it2 = ittmp ;
|
|
|
|
changed = true ;
|
|
}
|
|
else
|
|
++it2 ;
|
|
}
|
|
|
|
return changed ;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::updateAddressList(const RsPeerId& id, const pqiIpAddrSet &addrs)
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setAddressList() called for id : " << id << std::endl;
|
|
#endif
|
|
// first clean the list from potentially banned IPs.
|
|
|
|
pqiIpAddrSet clean_set = addrs ;
|
|
|
|
cleanIpList(clean_set.mExt.mAddrs,id,mLinkMgr) ;
|
|
cleanIpList(clean_set.mLocal.mAddrs,id,mLinkMgr) ;
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* check if it is our own ip */
|
|
if (id == getOwnId())
|
|
{
|
|
mOwnState.ipAddrs.updateAddrs(clean_set);
|
|
return true;
|
|
}
|
|
|
|
/* check if it is a friend */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
if (mFriendList.end() == (it = mFriendList.find(id)))
|
|
{
|
|
if (mOthersList.end() == (it = mOthersList.find(id)))
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setLocalAddress() cannot add addres info : peer id not found in friend list. id: " << id << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/* "it" points to peer */
|
|
it->second.ipAddrs.updateAddrs(clean_set);
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setLocalAddress() Updated Address for: " << id;
|
|
std::cerr << std::endl;
|
|
std::string addrstr;
|
|
it->second.ipAddrs.printAddrs(addrstr);
|
|
std::cerr << addrstr;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3PeerMgrIMPL::updateCurrentAddress(const RsPeerId& id, const pqiIpAddress &addr)
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::updateCurrentAddress() called for id : " << id << std::endl;
|
|
#endif
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* cannot be own id */
|
|
|
|
/* check if it is a friend */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
if (mFriendList.end() == (it = mFriendList.find(id)))
|
|
{
|
|
if (mOthersList.end() == (it = mOthersList.find(id)))
|
|
{
|
|
std::cerr << "p3PeerMgrIMPL::updateCurrentAddress() ERROR peer id not found: " << id << std::endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (sockaddr_storage_isPrivateNet(addr.mAddr))
|
|
{
|
|
it->second.ipAddrs.updateLocalAddrs(addr);
|
|
it->second.localaddr = addr.mAddr;
|
|
}
|
|
else
|
|
{
|
|
it->second.ipAddrs.updateExtAddrs(addr);
|
|
it->second.serveraddr = addr.mAddr;
|
|
}
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::updatedCurrentAddress() Updated Address for: " << id;
|
|
std::cerr << std::endl;
|
|
std::string addrstr;
|
|
it->second.ipAddrs.printAddrs(addrstr);
|
|
std::cerr << addrstr;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3PeerMgrIMPL::updateLastContact(const RsPeerId& id)
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::updateLastContact() called for id : " << id << std::endl;
|
|
#endif
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* cannot be own id */
|
|
|
|
/* check if it is a friend */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
if (mFriendList.end() == (it = mFriendList.find(id)))
|
|
{
|
|
if (mOthersList.end() == (it = mOthersList.find(id)))
|
|
{
|
|
std::cerr << "p3PeerMgrIMPL::updateLastContact() ERROR peer id not found: " << id << std::endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
it->second.lastcontact = time(NULL);
|
|
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
|
|
return true;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::setNetworkMode(const RsPeerId &id, uint32_t netMode)
|
|
{
|
|
if (id == AuthSSL::getAuthSSL()->OwnId())
|
|
{
|
|
return setOwnNetworkMode(netMode);
|
|
}
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
/* check if it is a friend */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
if (mFriendList.end() == (it = mFriendList.find(id)))
|
|
{
|
|
if (mOthersList.end() == (it = mOthersList.find(id)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool changed = false;
|
|
|
|
/* "it" points to peer */
|
|
if (it->second.netMode != netMode)
|
|
{
|
|
it->second.netMode = netMode;
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
changed = true;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::setLocation(const RsPeerId &id, const std::string &location)
|
|
{
|
|
bool changed = false;
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setLocation() called for id : " << id << "; with location " << location << std::endl;
|
|
#endif
|
|
if (id == AuthSSL::getAuthSSL()->OwnId())
|
|
{
|
|
if (mOwnState.location.compare(location) != 0) {
|
|
mOwnState.location = location;
|
|
changed = true;
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
/* check if it is a friend */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
if (mFriendList.end() != (it = mFriendList.find(id))) {
|
|
if (it->second.location.compare(location) != 0) {
|
|
it->second.location = location;
|
|
changed = true;
|
|
}
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht)
|
|
{
|
|
{
|
|
std::string out;
|
|
rs_sprintf(out, "p3PeerMgr::setVisState(%s, %u, %u)", id.toStdString().c_str(), vs_disc, vs_dht);
|
|
rslog(RSL_WARNING, p3peermgrzone, out);
|
|
}
|
|
|
|
if (id == AuthSSL::getAuthSSL()->OwnId())
|
|
{
|
|
return setOwnVisState(vs_disc, vs_dht);
|
|
}
|
|
|
|
bool isFriend = false;
|
|
bool changed = false;
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* check if it is a friend */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
if (mFriendList.end() == (it = mFriendList.find(id)))
|
|
{
|
|
if (mOthersList.end() == (it = mOthersList.find(id)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
isFriend = true;
|
|
}
|
|
|
|
/* "it" points to peer */
|
|
if ((it->second.vs_disc != vs_disc) || (it->second.vs_dht = vs_dht))
|
|
{
|
|
it->second.vs_disc = vs_disc;
|
|
it->second.vs_dht = vs_dht;
|
|
changed = true;
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::setVisState(" << id << ", DISC: " << vs_disc << " DHT: " << vs_dht << ") ";
|
|
std::cerr << " NAME: " << it->second.name;
|
|
|
|
switch(it->second.vs_disc)
|
|
{
|
|
default:
|
|
case RS_VS_DISC_OFF:
|
|
std::cerr << " NO-DISC ";
|
|
break;
|
|
case RS_VS_DISC_MINIMAL:
|
|
std::cerr << " MIN-DISC ";
|
|
break;
|
|
case RS_VS_DISC_FULL:
|
|
std::cerr << " FULL-DISC ";
|
|
break;
|
|
}
|
|
switch(it->second.vs_dht)
|
|
{
|
|
default:
|
|
case RS_VS_DHT_OFF:
|
|
std::cerr << " NO-DHT ";
|
|
break;
|
|
case RS_VS_DHT_PASSIVE:
|
|
std::cerr << " PASSIVE-DHT ";
|
|
break;
|
|
case RS_VS_DHT_FULL:
|
|
std::cerr << " FULL-DHT ";
|
|
break;
|
|
}
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
if(isFriend && changed)
|
|
{
|
|
mLinkMgr->setFriendVisibility(id, vs_dht != RS_VS_DHT_OFF);
|
|
}
|
|
|
|
if (changed) {
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************/
|
|
|
|
|
|
/**********************************************************************
|
|
**********************************************************************
|
|
******************** p3Config functions ******************************
|
|
**********************************************************************
|
|
**********************************************************************/
|
|
|
|
/* Key Functions to be overloaded for Full Configuration */
|
|
|
|
RsSerialiser *p3PeerMgrIMPL::setupSerialiser()
|
|
{
|
|
RsSerialiser *rss = new RsSerialiser();
|
|
rss->addSerialType(new RsPeerConfigSerialiser());
|
|
rss->addSerialType(new RsGeneralConfigSerialiser()) ;
|
|
|
|
return rss;
|
|
}
|
|
|
|
|
|
bool p3PeerMgrIMPL::saveList(bool &cleanup, std::list<RsItem *>& saveData)
|
|
{
|
|
/* create a list of current peers */
|
|
cleanup = true;
|
|
bool useExtAddrFinder = mNetMgr->getIPServersEnabled();
|
|
|
|
/* gather these information before mPeerMtx is locked! */
|
|
struct sockaddr_storage proxy_addr_tor, proxy_addr_i2p;
|
|
getProxyServerAddress(RS_HIDDEN_TYPE_TOR, proxy_addr_tor);
|
|
getProxyServerAddress(RS_HIDDEN_TYPE_I2P, proxy_addr_i2p);
|
|
|
|
mPeerMtx.lock(); /****** MUTEX LOCKED *******/
|
|
|
|
RsPeerNetItem *item = new RsPeerNetItem();
|
|
item->clear();
|
|
|
|
item->peerId = getOwnId();
|
|
item->pgpId = mOwnState.gpg_id;
|
|
item->location = mOwnState.location;
|
|
|
|
#if 0
|
|
if (mOwnState.netMode & RS_NET_MODE_TRY_EXT)
|
|
{
|
|
item->netMode = RS_NET_MODE_EXT;
|
|
}
|
|
else if (mOwnState.netMode & RS_NET_MODE_TRY_UPNP)
|
|
{
|
|
item->netMode = RS_NET_MODE_UPNP;
|
|
}
|
|
else
|
|
{
|
|
item->netMode = RS_NET_MODE_UDP;
|
|
}
|
|
#endif
|
|
item->netMode = mOwnState.netMode;
|
|
|
|
item->vs_disc = mOwnState.vs_disc;
|
|
item->vs_dht = mOwnState.vs_dht;
|
|
|
|
item->lastContact = mOwnState.lastcontact;
|
|
|
|
item->localAddrV4.addr = mOwnState.localaddr;
|
|
item->extAddrV4.addr = mOwnState.serveraddr;
|
|
sockaddr_storage_clear(item->localAddrV6.addr);
|
|
sockaddr_storage_clear(item->extAddrV6.addr);
|
|
|
|
item->dyndns = mOwnState.dyndns;
|
|
mOwnState.ipAddrs.mLocal.loadTlv(item->localAddrList);
|
|
mOwnState.ipAddrs.mExt.loadTlv(item->extAddrList);
|
|
item->domain_addr = mOwnState.hiddenDomain;
|
|
item->domain_port = mOwnState.hiddenPort;
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::saveList() Own Config Item:" << std::endl;
|
|
item->print(std::cerr, 10);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
saveData.push_back(item);
|
|
|
|
/* iterate through all friends and save */
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
for(it = mFriendList.begin(); it != mFriendList.end(); ++it)
|
|
{
|
|
item = new RsPeerNetItem();
|
|
item->clear();
|
|
|
|
item->peerId = it->first;
|
|
item->pgpId = (it->second).gpg_id;
|
|
item->location = (it->second).location;
|
|
item->netMode = (it->second).netMode;
|
|
item->vs_disc = (it->second).vs_disc;
|
|
item->vs_dht = (it->second).vs_dht;
|
|
|
|
item->lastContact = (it->second).lastcontact;
|
|
|
|
item->localAddrV4.addr = (it->second).localaddr;
|
|
item->extAddrV4.addr = (it->second).serveraddr;
|
|
sockaddr_storage_clear(item->localAddrV6.addr);
|
|
sockaddr_storage_clear(item->extAddrV6.addr);
|
|
|
|
|
|
item->dyndns = (it->second).dyndns;
|
|
(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);
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::saveList() Peer Config Item:" << std::endl;
|
|
item->print(std::cerr, 10);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
|
|
RsPeerBandwidthLimitsItem *pblitem = new RsPeerBandwidthLimitsItem ;
|
|
pblitem->peers = mPeerBandwidthLimits ;
|
|
saveData.push_back(pblitem) ;
|
|
|
|
RsPeerServicePermissionItem *sitem = new RsPeerServicePermissionItem ;
|
|
|
|
for(std::map<RsPgpId,ServicePermissionFlags>::const_iterator it(mFriendsPermissionFlags.begin());it!=mFriendsPermissionFlags.end();++it)
|
|
{
|
|
sitem->pgp_ids.push_back(it->first) ;
|
|
sitem->service_flags.push_back(it->second) ;
|
|
}
|
|
|
|
saveData.push_back(sitem) ;
|
|
|
|
// Now save config for network digging strategies
|
|
|
|
RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ;
|
|
|
|
RsTlvKeyValue kv;
|
|
kv.key = kConfigKeyExtIpFinder;
|
|
kv.value = (useExtAddrFinder)?"TRUE":"FALSE" ;
|
|
vitem->tlvkvs.pairs.push_back(kv) ;
|
|
|
|
|
|
// Store Proxy Server.
|
|
// Tor
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Saving proxyServerAddress for Tor: " << sockaddr_storage_tostring(proxy_addr_tor);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
kv.key = kConfigKeyProxyServerIpAddrTor;
|
|
kv.value = sockaddr_storage_iptostring(proxy_addr_tor);
|
|
vitem->tlvkvs.pairs.push_back(kv) ;
|
|
|
|
kv.key = kConfigKeyProxyServerPortTor;
|
|
kv.value = sockaddr_storage_porttostring(proxy_addr_tor);
|
|
vitem->tlvkvs.pairs.push_back(kv) ;
|
|
|
|
// I2P
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Saving proxyServerAddress for I2P: " << sockaddr_storage_tostring(proxy_addr_i2p);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
kv.key = kConfigKeyProxyServerIpAddrI2P;
|
|
kv.value = sockaddr_storage_iptostring(proxy_addr_i2p);
|
|
vitem->tlvkvs.pairs.push_back(kv) ;
|
|
|
|
kv.key = kConfigKeyProxyServerPortI2P;
|
|
kv.value = sockaddr_storage_porttostring(proxy_addr_i2p);
|
|
vitem->tlvkvs.pairs.push_back(kv) ;
|
|
|
|
saveData.push_back(vitem);
|
|
|
|
/* save groups */
|
|
|
|
for ( std::map<RsNodeGroupId,RsGroupInfo>::iterator groupIt = groupList.begin(); groupIt != groupList.end(); ++groupIt)
|
|
{
|
|
RsNodeGroupItem *itm = new RsNodeGroupItem(groupIt->second);
|
|
saveData.push_back(itm) ;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::getMaxRates(const RsPeerId& pid,uint32_t& maxUp,uint32_t& maxDn)
|
|
{
|
|
RsPgpId pgp_id ;
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
std::map<RsPeerId, peerState>::const_iterator it = mFriendList.find(pid) ;
|
|
|
|
if(it == mFriendList.end())
|
|
return false ;
|
|
|
|
pgp_id = it->second.gpg_id ;
|
|
}
|
|
return getMaxRates(pgp_id,maxUp,maxDn) ;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::getMaxRates(const RsPgpId& pid,uint32_t& maxUp,uint32_t& maxDn)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
std::map<RsPgpId,PeerBandwidthLimits>::const_iterator it2 = mPeerBandwidthLimits.find(pid) ;
|
|
|
|
if(it2 != mPeerBandwidthLimits.end())
|
|
{
|
|
maxUp = it2->second.max_up_rate_kbs ;
|
|
maxDn = it2->second.max_dl_rate_kbs ;
|
|
return true ;
|
|
}
|
|
else
|
|
{
|
|
maxUp = 0;
|
|
maxDn = 0;
|
|
return false ;
|
|
}
|
|
}
|
|
bool p3PeerMgrIMPL::setMaxRates(const RsPgpId& pid,uint32_t maxUp,uint32_t maxDn)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
PeerBandwidthLimits& p(mPeerBandwidthLimits[pid]) ;
|
|
|
|
if(maxUp == p.max_up_rate_kbs && maxDn == p.max_dl_rate_kbs)
|
|
return true ;
|
|
|
|
std::cerr << "Updating max rates for peer " << pid << " to " << maxUp << " kB/s (up), " << maxDn << " kB/s (dn)" << std::endl;
|
|
|
|
p.max_up_rate_kbs = maxUp ;
|
|
p.max_dl_rate_kbs = maxDn ;
|
|
|
|
IndicateConfigChanged();
|
|
|
|
return true ;
|
|
}
|
|
|
|
void p3PeerMgrIMPL::saveDone()
|
|
{
|
|
/* clean up the save List */
|
|
std::list<RsItem *>::iterator it;
|
|
for(it = saveCleanupList.begin(); it != saveCleanupList.end(); ++it)
|
|
{
|
|
delete (*it);
|
|
}
|
|
|
|
saveCleanupList.clear();
|
|
|
|
/* unlock mutex */
|
|
mPeerMtx.unlock(); /****** MUTEX UNLOCKED *******/
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::loadList(std::list<RsItem *>& load)
|
|
{
|
|
|
|
// DEFAULTS.
|
|
bool useExtAddrFinder = true;
|
|
std::string proxyIpAddressTor = kConfigDefaultProxyServerIpAddr;
|
|
uint16_t proxyPortTor = kConfigDefaultProxyServerPortTor;
|
|
std::string proxyIpAddressI2P = kConfigDefaultProxyServerIpAddr;
|
|
uint16_t proxyPortI2P = kConfigDefaultProxyServerPortI2P;
|
|
|
|
if (load.empty()) {
|
|
std::cerr << "p3PeerMgrIMPL::loadList() list is empty, it may be a configuration problem." << std::endl;
|
|
return false;
|
|
}
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::loadList() Item Count: " << load.size() << std::endl;
|
|
#endif
|
|
|
|
RsPeerId ownId = getOwnId();
|
|
|
|
/* load the list of peers */
|
|
std::list<RsItem *>::iterator it;
|
|
for(it = load.begin(); it != load.end(); ++it)
|
|
{
|
|
RsPeerNetItem *pitem = dynamic_cast<RsPeerNetItem *>(*it);
|
|
if (pitem)
|
|
{
|
|
RsPeerId peer_id = pitem->peerId ;
|
|
RsPgpId peer_pgp_id = pitem->pgpId ;
|
|
|
|
if (peer_id == ownId)
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::loadList() Own Config Item:" << std::endl;
|
|
pitem->print(std::cerr, 10);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
/* add ownConfig */
|
|
setOwnNetworkMode(pitem->netMode);
|
|
setOwnVisState(pitem->vs_disc, pitem->vs_dht);
|
|
|
|
mOwnState.gpg_id = AuthGPG::getAuthGPG()->getGPGOwnId();
|
|
mOwnState.location = AuthSSL::getAuthSSL()->getOwnLocation();
|
|
}
|
|
else
|
|
{
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::loadList() Peer Config Item:" << std::endl;
|
|
pitem->print(std::cerr, 10);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
/* ************* */
|
|
// permission flags is used as a mask for the existing perms, so we set it to 0xffff
|
|
addFriend(peer_id, peer_pgp_id, pitem->netMode, pitem->vs_disc, pitem->vs_dht, pitem->lastContact, RS_NODE_PERM_ALL);
|
|
setLocation(pitem->peerId, pitem->location);
|
|
}
|
|
|
|
if (pitem->netMode == RS_NET_MODE_HIDDEN)
|
|
{
|
|
/* set only the hidden stuff & localAddress */
|
|
setLocalAddress(peer_id, pitem->localAddrV4.addr);
|
|
setHiddenDomainPort(peer_id, pitem->domain_addr, pitem->domain_port);
|
|
|
|
}
|
|
else
|
|
{
|
|
setLocalAddress(peer_id, pitem->localAddrV4.addr);
|
|
setExtAddress(peer_id, pitem->extAddrV4.addr);
|
|
setDynDNS (peer_id, pitem->dyndns);
|
|
|
|
/* convert addresses */
|
|
pqiIpAddrSet addrs;
|
|
addrs.mLocal.extractFromTlv(pitem->localAddrList);
|
|
addrs.mExt.extractFromTlv(pitem->extAddrList);
|
|
|
|
updateAddressList(peer_id, addrs);
|
|
}
|
|
|
|
delete(*it);
|
|
|
|
continue;
|
|
}
|
|
|
|
RsConfigKeyValueSet *vitem = dynamic_cast<RsConfigKeyValueSet *>(*it) ;
|
|
if (vitem)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::loadList() General Variable Config Item:" << std::endl;
|
|
vitem->print(std::cerr, 10);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
std::list<RsTlvKeyValue>::iterator kit;
|
|
for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit)
|
|
{
|
|
if (kit->key == kConfigKeyExtIpFinder)
|
|
{
|
|
useExtAddrFinder = (kit->value == "TRUE");
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "setting use_extr_addr_finder to " << useExtAddrFinder << std::endl ;
|
|
#endif
|
|
}
|
|
// Tor
|
|
else if (kit->key == kConfigKeyProxyServerIpAddrTor)
|
|
{
|
|
proxyIpAddressTor = kit->value;
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Loaded proxyIpAddress for Tor: " << proxyIpAddressTor;
|
|
std::cerr << std::endl ;
|
|
#endif
|
|
|
|
}
|
|
else if (kit->key == kConfigKeyProxyServerPortTor)
|
|
{
|
|
uint16_t p = atoi(kit->value.c_str());
|
|
|
|
if(p >= 1024)
|
|
proxyPortTor = p;
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Loaded proxyPort for Tor: " << proxyPortTor;
|
|
std::cerr << std::endl ;
|
|
#endif
|
|
}
|
|
// I2p
|
|
else if (kit->key == kConfigKeyProxyServerIpAddrI2P)
|
|
{
|
|
proxyIpAddressI2P = kit->value;
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Loaded proxyIpAddress for I2P: " << proxyIpAddressI2P;
|
|
std::cerr << std::endl ;
|
|
#endif
|
|
}
|
|
else if (kit->key == kConfigKeyProxyServerPortI2P)
|
|
{
|
|
uint16_t p = atoi(kit->value.c_str());
|
|
|
|
if(p >= 1024)
|
|
proxyPortI2P = p;
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Loaded proxyPort for I2P: " << proxyPortI2P;
|
|
std::cerr << std::endl ;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
delete(*it);
|
|
|
|
continue;
|
|
}
|
|
|
|
RsNodeGroupItem *gitem2 = dynamic_cast<RsNodeGroupItem*>(*it) ;
|
|
|
|
if (gitem2)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgrIMPL::loadList() Peer group item:" << std::endl;
|
|
gitem->print(std::cerr, 10);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
RsGroupInfo info ;
|
|
info.peerIds = gitem2->pgpList.ids ;
|
|
info.id = gitem2->id ;
|
|
info.name = gitem2->name ;
|
|
info.flag = gitem2->flag ;
|
|
|
|
std::cerr << "(II) Loaded group in new format. ID = " << info.id << std::endl;
|
|
groupList[info.id] = info ;
|
|
|
|
continue;
|
|
}
|
|
RsPeerBandwidthLimitsItem *pblitem = dynamic_cast<RsPeerBandwidthLimitsItem*>(*it) ;
|
|
|
|
if(pblitem)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Loaded service permission item: " << std::endl;
|
|
#endif
|
|
mPeerBandwidthLimits = pblitem->peers ;
|
|
}
|
|
RsPeerServicePermissionItem *sitem = dynamic_cast<RsPeerServicePermissionItem*>(*it) ;
|
|
|
|
if(sitem)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Loaded service permission item: " << std::endl;
|
|
#endif
|
|
|
|
for(uint32_t i=0;i<sitem->pgp_ids.size();++i)
|
|
if(AuthGPG::getAuthGPG()->isGPGAccepted(sitem->pgp_ids[i]) || sitem->pgp_ids[i] == AuthGPG::getAuthGPG()->getGPGOwnId())
|
|
{
|
|
mFriendsPermissionFlags[sitem->pgp_ids[i]] = sitem->service_flags[i] ;
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << " " << sitem->pgp_ids[i] << " - " << sitem->service_flags[i] << std::endl;
|
|
#endif
|
|
}
|
|
#ifdef PEER_DEBUG
|
|
else
|
|
std::cerr << " " << sitem->pgp_ids[i] << " - Not a friend!" << std::endl;
|
|
#endif
|
|
}
|
|
|
|
delete (*it);
|
|
}
|
|
|
|
{
|
|
/* set missing groupIds */
|
|
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* Standard groups */
|
|
const int standardGroupCount = 5;
|
|
const RsNodeGroupId standardGroupIds [standardGroupCount] = { RS_GROUP_ID_FRIENDS, RS_GROUP_ID_FAMILY, RS_GROUP_ID_COWORKERS, RS_GROUP_ID_OTHERS, RS_GROUP_ID_FAVORITES };
|
|
const char *standardGroupNames[standardGroupCount] = { RS_GROUP_DEFAULT_NAME_FRIENDS, RS_GROUP_DEFAULT_NAME_FAMILY, RS_GROUP_DEFAULT_NAME_COWORKERS, RS_GROUP_DEFAULT_NAME_OTHERS, RS_GROUP_DEFAULT_NAME_FAVORITES };
|
|
|
|
for(uint32_t k=0;k<standardGroupCount;++k)
|
|
if(groupList.find(standardGroupIds[k]) == groupList.end())
|
|
{
|
|
RsGroupInfo info ;
|
|
info.id = standardGroupIds[k];
|
|
info.name = standardGroupNames[k];
|
|
info.flag |= RS_GROUP_FLAG_STANDARD;
|
|
|
|
groupList[info.id] = info;
|
|
}
|
|
}
|
|
|
|
// If we are hidden - don't want ExtAddrFinder - ever!
|
|
if (isHidden())
|
|
{
|
|
useExtAddrFinder = false;
|
|
}
|
|
|
|
mNetMgr->setIPServersEnabled(useExtAddrFinder);
|
|
|
|
// Configure Proxy Server.
|
|
struct sockaddr_storage proxy_addr;
|
|
// Tor
|
|
sockaddr_storage_clear(proxy_addr);
|
|
sockaddr_storage_ipv4_aton(proxy_addr, proxyIpAddressTor.c_str());
|
|
sockaddr_storage_ipv4_setport(proxy_addr, proxyPortTor);
|
|
|
|
if (sockaddr_storage_isValidNet(proxy_addr))
|
|
{
|
|
setProxyServerAddress(RS_HIDDEN_TYPE_TOR, proxy_addr);
|
|
}
|
|
|
|
// I2P
|
|
sockaddr_storage_clear(proxy_addr);
|
|
sockaddr_storage_ipv4_aton(proxy_addr, proxyIpAddressI2P.c_str());
|
|
sockaddr_storage_ipv4_setport(proxy_addr, proxyPortI2P);
|
|
|
|
if (sockaddr_storage_isValidNet(proxy_addr))
|
|
{
|
|
setProxyServerAddress(RS_HIDDEN_TYPE_I2P, proxy_addr);
|
|
}
|
|
|
|
load.clear() ;
|
|
return true;
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
|
void printConnectState(std::ostream &out, peerState &peer)
|
|
{
|
|
|
|
out << "Friend: " << peer.name << " Id: " << peer.id << " State: " << peer.state;
|
|
if (peer.state & RS_PEER_S_FRIEND)
|
|
out << " S:RS_PEER_S_FRIEND";
|
|
if (peer.state & RS_PEER_S_ONLINE)
|
|
out << " S:RS_PEER_S_ONLINE";
|
|
if (peer.state & RS_PEER_S_CONNECTED)
|
|
out << " S:RS_PEER_S_CONNECTED";
|
|
out << " Actions: " << peer.actions;
|
|
if (peer.actions & RS_PEER_NEW)
|
|
out << " A:RS_PEER_NEW";
|
|
if (peer.actions & RS_PEER_MOVED)
|
|
out << " A:RS_PEER_MOVED";
|
|
if (peer.actions & RS_PEER_CONNECTED)
|
|
out << " A:RS_PEER_CONNECTED";
|
|
if (peer.actions & RS_PEER_DISCONNECTED)
|
|
out << " A:RS_PEER_DISCONNECTED";
|
|
if (peer.actions & RS_PEER_CONNECT_REQ)
|
|
out << " A:RS_PEER_CONNECT_REQ";
|
|
|
|
out << std::endl;
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/**********************************************************************
|
|
**********************************************************************
|
|
************************** Groups ************************************
|
|
**********************************************************************
|
|
**********************************************************************/
|
|
|
|
bool p3PeerMgrIMPL::addGroup(RsGroupInfo &groupInfo)
|
|
{
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
do { groupInfo.id = RsNodeGroupId::random(); } while(groupList.find(groupInfo.id) != groupList.end()) ;
|
|
|
|
RsGroupInfo groupItem(groupInfo) ;
|
|
|
|
// remove standard flag
|
|
|
|
groupItem.flag &= ~RS_GROUP_FLAG_STANDARD;
|
|
groupList[groupInfo.id] = groupItem;
|
|
|
|
std::cerr << "(II) Added new group with ID " << groupInfo.id << ", name=\"" << groupInfo.name << "\"" << std::endl;
|
|
}
|
|
|
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_ADD);
|
|
|
|
IndicateConfigChanged();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::editGroup(const RsNodeGroupId& groupId, RsGroupInfo &groupInfo)
|
|
{
|
|
if (groupId.isNull())
|
|
return false;
|
|
|
|
bool changed = false;
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
std::map<RsNodeGroupId,RsGroupInfo>::iterator it = groupList.find(groupId) ;
|
|
|
|
if(it == groupList.end())
|
|
{
|
|
std::cerr << "(EE) cannot find local node group with ID " << groupId << std::endl;
|
|
return false ;
|
|
}
|
|
|
|
if (it->second.flag & RS_GROUP_FLAG_STANDARD)
|
|
{
|
|
// can't edit standard groups
|
|
std::cerr << "(EE) cannot edit standard group with ID " << groupId << std::endl;
|
|
return false ;
|
|
}
|
|
else
|
|
{
|
|
changed = true;
|
|
it->second = groupInfo;
|
|
}
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_MOD);
|
|
|
|
IndicateConfigChanged();
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::removeGroup(const RsNodeGroupId& groupId)
|
|
{
|
|
bool changed = false;
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
std::map<RsNodeGroupId,RsGroupInfo>::iterator it = groupList.find(groupId) ;
|
|
|
|
if (it != groupList.end()) {
|
|
if (it->second.flag & RS_GROUP_FLAG_STANDARD)
|
|
{
|
|
// can't remove standard groups
|
|
std::cerr << "(EE) cannot remove standard group with ID " << groupId << std::endl;
|
|
return false ;
|
|
}
|
|
#warning csoler: we need to check that the local group is not used. Otherwise deleting it is going to cause problems!
|
|
// else if(!it->second.used_gxs_groups.empty())
|
|
// {
|
|
// std::cerr << "(EE) cannot remove standard group with ID " << groupId << " because it is used in the following groups: " << std::endl;
|
|
// for(std::set<RsGxsGroupId>::const_iterator it2(it->second.used_gxs_groups.begin());it2!=it->second.used_gxs_groups.end();++it2)
|
|
// std::cerr << " " << *it2 << std::endl;
|
|
//
|
|
// return false ;
|
|
// }
|
|
else
|
|
{
|
|
changed = true;
|
|
groupList.erase(it);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (changed) {
|
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_DEL);
|
|
|
|
IndicateConfigChanged();
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::getGroupInfoByName(const std::string& groupName, RsGroupInfo &groupInfo)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
for(std::map<RsNodeGroupId,RsGroupInfo>::iterator it = groupList.begin();it!=groupList.end();++it)
|
|
if(it->second.name == groupName)
|
|
{
|
|
groupInfo = it->second ;
|
|
return true ;
|
|
}
|
|
|
|
std::cerr << "(EE) getGroupInfoByName: no known group for name " << groupName << std::endl;
|
|
return false ;
|
|
}
|
|
bool p3PeerMgrIMPL::getGroupInfo(const RsNodeGroupId& groupId, RsGroupInfo &groupInfo)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
std::map<RsNodeGroupId,RsGroupInfo>::iterator it = groupList.find(groupId) ;
|
|
|
|
if(it == groupList.end())
|
|
return false ;
|
|
|
|
groupInfo = it->second;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool p3PeerMgrIMPL::getGroupInfoList(std::list<RsGroupInfo>& groupInfoList)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
for(std::map<RsNodeGroupId,RsGroupInfo> ::const_iterator groupIt = groupList.begin(); groupIt != groupList.end(); ++groupIt)
|
|
groupInfoList.push_back(groupIt->second) ;
|
|
|
|
return true;
|
|
}
|
|
|
|
// groupId.isNull() && assign == false -> remove from all groups
|
|
|
|
bool p3PeerMgrIMPL::assignPeersToGroup(const RsNodeGroupId &groupId, const std::list<RsPgpId> &peerIds, bool assign)
|
|
{
|
|
if (groupId.isNull() && assign == true)
|
|
return false;
|
|
|
|
if (peerIds.empty())
|
|
return false;
|
|
|
|
bool changed = false;
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
for (std::map<RsNodeGroupId,RsGroupInfo>::iterator groupIt = groupList.begin(); groupIt != groupList.end(); ++groupIt)
|
|
if (groupId.isNull() || groupIt->first == groupId)
|
|
{
|
|
RsGroupInfo& groupItem = groupIt->second;
|
|
|
|
for (std::list<RsPgpId>::const_iterator peerIt = peerIds.begin(); peerIt != peerIds.end(); ++peerIt)
|
|
{
|
|
std::set<RsPgpId>::iterator peerIt1 = groupItem.peerIds.find(*peerIt);
|
|
|
|
if (assign)
|
|
{
|
|
groupItem.peerIds.insert(*peerIt);
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
groupItem.peerIds.erase(*peerIt);
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (!groupId.isNull())
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (changed) {
|
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_MOD);
|
|
|
|
IndicateConfigChanged();
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
**********************************************************************
|
|
******************** Service permission stuff ************************
|
|
**********************************************************************
|
|
**********************************************************************/
|
|
|
|
ServicePermissionFlags p3PeerMgrIMPL::servicePermissionFlags(const RsPeerId& ssl_id)
|
|
{
|
|
RsPgpId gpg_id ;
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
std::map<RsPeerId, peerState>::const_iterator it = mFriendList.find(ssl_id);
|
|
|
|
if(it == mFriendList.end())
|
|
return RS_NODE_PERM_DEFAULT ;
|
|
|
|
gpg_id = it->second.gpg_id ;
|
|
}
|
|
|
|
return servicePermissionFlags(gpg_id) ;
|
|
}
|
|
|
|
|
|
ServicePermissionFlags p3PeerMgrIMPL::servicePermissionFlags(const RsPgpId& pgp_id)
|
|
{
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
std::map<RsPgpId,ServicePermissionFlags>::const_iterator it = mFriendsPermissionFlags.find( pgp_id ) ;
|
|
|
|
if(it == mFriendsPermissionFlags.end())
|
|
return RS_NODE_PERM_DEFAULT ;
|
|
else
|
|
return it->second ;
|
|
}
|
|
}
|
|
void p3PeerMgrIMPL::setServicePermissionFlags(const RsPgpId& pgp_id, const ServicePermissionFlags& flags)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
// Check that we have a PGP id. This should not be necessary, but because
|
|
// we use std::string, anything can get passed down here.
|
|
//
|
|
|
|
mFriendsPermissionFlags[pgp_id] = flags ;
|
|
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
|
|
}
|
|
|
|
/**********************************************************************
|
|
**********************************************************************
|
|
******************** Stuff moved from p3peers ************************
|
|
**********************************************************************
|
|
**********************************************************************/
|
|
|
|
bool p3PeerMgrIMPL::removeAllFriendLocations(const RsPgpId &gpgid)
|
|
{
|
|
std::list<RsPeerId> sslIds;
|
|
if (!getAssociatedPeers(gpgid, sslIds))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::list<RsPeerId>::iterator it;
|
|
for(it = sslIds.begin(); it != sslIds.end(); ++it)
|
|
{
|
|
removeFriend(*it, true);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3PeerMgrIMPL::getAssociatedPeers(const RsPgpId &gpg_id, std::list<RsPeerId> &ids)
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgr::getAssociatedPeers() for id : " << gpg_id << std::endl;
|
|
#endif
|
|
|
|
int count = 0;
|
|
std::map<RsPeerId, peerState>::iterator it;
|
|
for(it = mFriendList.begin(); it != mFriendList.end(); ++it)
|
|
{
|
|
if (it->second.gpg_id == gpg_id)
|
|
{
|
|
count++;
|
|
ids.push_back(it->first);
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgr::getAssociatedPeers() found ssl id : " << it->first << std::endl;
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
return (count > 0);
|
|
}
|
|
|
|
// goes through the list of known friend IPs and remove the ones that are banned by p3LinkMgr.
|
|
|
|
|
|
bool p3PeerMgrIMPL::removeBannedIps()
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Cleaning known IPs for all peers." << std::endl;
|
|
#endif
|
|
|
|
bool changed = false ;
|
|
for( std::map<RsPeerId, peerState>::iterator it = mFriendList.begin(); it != mFriendList.end(); ++it)
|
|
{
|
|
if(cleanIpList(it->second.ipAddrs.mExt.mAddrs,it->first,mLinkMgr)) changed = true ;
|
|
if(cleanIpList(it->second.ipAddrs.mLocal.mAddrs,it->first,mLinkMgr)) changed = true ;
|
|
|
|
if(!rsBanList->isAddressAccepted(it->second.serveraddr,RSBANLIST_CHECKING_FLAGS_BLACKLIST))
|
|
{
|
|
sockaddr_storage_clear(it->second.serveraddr) ;
|
|
std::cerr << "(SS) Peer " << it->first << " has a banned server address. Wiping it out." << std::endl;
|
|
}
|
|
}
|
|
|
|
if(cleanIpList(mOwnState.ipAddrs.mExt.mAddrs,mOwnState.id,mLinkMgr) ) changed = true ;
|
|
if(cleanIpList(mOwnState.ipAddrs.mLocal.mAddrs,mOwnState.id,mLinkMgr) ) changed = true ;
|
|
|
|
if(changed)
|
|
IndicateConfigChanged();
|
|
|
|
return true ;
|
|
}
|
|
|
|
// /* This only removes SSL certs, that are old... Can end up with no Certs per GPG Id
|
|
// * We are removing the concept of a "DummyId" - There is no need for it.
|
|
// */
|
|
//
|
|
// bool isDummyFriend(RsPeerId id)
|
|
// {
|
|
// bool ret = (id.substr(0,5) == "dummy");
|
|
// return ret;
|
|
// }
|
|
|
|
/**
|
|
* @brief p3PeerMgrIMPL::removeUnusedLocations Removes all location offline for RS_PEER_OFFLINE_DELETE seconds or more. Keeps the most recent location per PGP id.
|
|
* @return true on success
|
|
*
|
|
* This function removes all location that are offline for too long defined by RS_PEER_OFFLINE_DELETE.
|
|
* It also makes sure that at least one location (the most recent) is kept.
|
|
*
|
|
* The idea of the function is the following:
|
|
* - keep track if there is at least one location per PGP id that is not offline for too long
|
|
* -> hasRecentLocation
|
|
* - keep track of most recent location per PGP id that is offline for too long (and its time stamp)
|
|
* -> mostRecentLocation
|
|
* -> mostRecentTime
|
|
*
|
|
* When a location is found that is offline for too long the following points are checked from the top to the bottom:
|
|
* 1) remove it when the PGP id has a location that is not offline for too long
|
|
* 2) remove it when the PGP id has a more recent location
|
|
* 3) keep it when it is the most recent location
|
|
* This location will possibly be removed when a more recent (but still offline for too long) is found
|
|
*/
|
|
bool p3PeerMgrIMPL::removeUnusedLocations()
|
|
{
|
|
std::list<RsPeerId> toRemove;
|
|
std::map<RsPgpId, time_t> mostRecentTime;
|
|
|
|
const time_t now = time(NULL);
|
|
|
|
std::list<RsPgpId> pgpList ;
|
|
|
|
if (!rsPeers->getGPGAcceptedList(pgpList))
|
|
return false ;
|
|
|
|
{
|
|
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
// First put a sensible number in all PGP ids
|
|
|
|
for(std::list<RsPgpId>::const_iterator it = pgpList.begin(); it != pgpList.end(); ++it)
|
|
mostRecentTime[*it] = (time_t)0;
|
|
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "p3PeerMgr::removeUnusedLocations()" << std::endl;
|
|
#endif
|
|
// Then compute the most recently used location for all PGP ids
|
|
|
|
for( std::map<RsPeerId, peerState>::iterator it = mFriendList.begin(); it != mFriendList.end(); ++it)
|
|
{
|
|
time_t& bst(mostRecentTime[it->second.gpg_id]) ;
|
|
bst = std::max(bst,it->second.lastcontact) ;
|
|
}
|
|
|
|
// And remove all locations that are too old and also older than the most recent location. Doing this we're sure to always keep at least one location per PGP id.
|
|
|
|
for( std::map<RsPeerId, peerState>::iterator it = mFriendList.begin(); it != mFriendList.end(); ++it)
|
|
{
|
|
if (now > it->second.lastcontact + RS_PEER_OFFLINE_DELETE && it->second.lastcontact < mostRecentTime[it->second.gpg_id])
|
|
toRemove.push_back(it->first);
|
|
#ifdef PEER_DEBUG
|
|
std::cerr << "Location " << it->first << " PGP id " << it->second.gpg_id << " last contact " << it->second.lastcontact << " remove: " << (now > it->second.lastcontact + RS_PEER_OFFLINE_DELETE) << " most recent: " << mostRecentTime[it->second.gpg_id]
|
|
<< ". Final result remove: " << (it->second.lastcontact < mostRecentTime[it->second.gpg_id] && now > it->second.lastcontact + RS_PEER_OFFLINE_DELETE )<< std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
for (std::list<RsPeerId>::iterator it = toRemove.begin(); it != toRemove.end(); ++it)
|
|
removeFriend(*it, false) ;
|
|
|
|
return true;
|
|
}
|
|
|
|
|