mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-30 17:23:23 -05:00
b1285a5de7
Rename from RsDisc to more descriptive RsGossipDiscovery Keep full retrocompatibility suggesting usage of RsGossipDiscovery Add capability to send and receive full RetroShare invitation Emit event when receiving a full invitation Start using new debug utilities Use enum class instead of defines and constant where appropriate
1336 lines
37 KiB
C++
1336 lines
37 KiB
C++
/*******************************************************************************
|
|
* RetroShare gossip discovery service implementation *
|
|
* *
|
|
* libretroshare: retroshare core library *
|
|
* *
|
|
* Copyright (C) 2004-2013 Robert Fernie <retroshare@lunamutt.com> *
|
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
|
* *
|
|
* This program is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Lesser General Public License as *
|
|
* published by the Free Software Foundation, either version 3 of the *
|
|
* License, or (at your option) any later version. *
|
|
* *
|
|
* This program 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 Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Lesser General Public License *
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
|
* *
|
|
*******************************************************************************/
|
|
|
|
#include "gossipdiscovery/p3gossipdiscovery.h"
|
|
#include "pqi/p3peermgr.h"
|
|
#include "retroshare/rsversion.h"
|
|
#include "retroshare/rsiface.h"
|
|
#include "rsserver/p3face.h"
|
|
#include "util/rsdebug.h"
|
|
|
|
/****
|
|
* #define P3DISC_DEBUG 1
|
|
****/
|
|
|
|
/*extern*/ std::shared_ptr<RsGossipDiscovery> rsGossipDiscovery(nullptr);
|
|
|
|
RsGossipDiscovery::~RsGossipDiscovery() {};
|
|
|
|
|
|
static bool populateContactInfo( const peerState &detail,
|
|
RsDiscContactItem *pkt,
|
|
bool include_ip_information )
|
|
{
|
|
pkt->clear();
|
|
|
|
pkt->pgpId = detail.gpg_id;
|
|
pkt->sslId = detail.id;
|
|
pkt->location = detail.location;
|
|
pkt->version = "";
|
|
pkt->netMode = detail.netMode;
|
|
pkt->vs_disc = detail.vs_disc;
|
|
pkt->vs_dht = detail.vs_dht;
|
|
|
|
pkt->lastContact = time(nullptr);
|
|
|
|
if (detail.hiddenNode)
|
|
{
|
|
pkt->isHidden = true;
|
|
pkt->hiddenAddr = detail.hiddenDomain;
|
|
pkt->hiddenPort = detail.hiddenPort;
|
|
}
|
|
else
|
|
{
|
|
pkt->isHidden = false;
|
|
|
|
if(include_ip_information)
|
|
{
|
|
pkt->localAddrV4.addr = detail.localaddr;
|
|
pkt->extAddrV4.addr = detail.serveraddr;
|
|
sockaddr_storage_clear(pkt->localAddrV6.addr);
|
|
sockaddr_storage_clear(pkt->extAddrV6.addr);
|
|
|
|
pkt->dyndns = detail.dyndns;
|
|
detail.ipAddrs.mLocal.loadTlv(pkt->localAddrList);
|
|
detail.ipAddrs.mExt.loadTlv(pkt->extAddrList);
|
|
}
|
|
else
|
|
{
|
|
sockaddr_storage_clear(pkt->localAddrV6.addr);
|
|
sockaddr_storage_clear(pkt->extAddrV6.addr);
|
|
sockaddr_storage_clear(pkt->localAddrV4.addr);
|
|
sockaddr_storage_clear(pkt->extAddrV4.addr);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void DiscPgpInfo::mergeFriendList(const std::set<PGPID> &friends)
|
|
{
|
|
std::set<PGPID>::const_iterator it;
|
|
for(it = friends.begin(); it != friends.end(); ++it)
|
|
{
|
|
mFriendSet.insert(*it);
|
|
}
|
|
}
|
|
|
|
|
|
p3discovery2::p3discovery2(
|
|
p3PeerMgr* peerMgr, p3LinkMgr* linkMgr, p3NetMgr* netMgr,
|
|
p3ServiceControl* sc, RsGixs* gixs ) :
|
|
p3Service(), mPeerMgr(peerMgr), mLinkMgr(linkMgr), mNetMgr(netMgr),
|
|
mServiceCtrl(sc), mGixs(gixs), mDiscMtx("p3discovery2"), mLastPgpUpdate(0)
|
|
{
|
|
Dbg3() << __PRETTY_FUNCTION__ << std::endl;
|
|
|
|
RS_STACK_MUTEX(mDiscMtx);
|
|
addSerialType(new RsDiscSerialiser());
|
|
|
|
// Add self into PGP FriendList.
|
|
mFriendList[AuthGPG::getAuthGPG()->getGPGOwnId()] = DiscPgpInfo();
|
|
|
|
rsEvents->registerEventsHandler(
|
|
[this](const RsEvent& event){ rsEventsHandler(event); },
|
|
mRsEventsHandle );
|
|
}
|
|
|
|
|
|
const std::string DISCOVERY_APP_NAME = "disc";
|
|
const uint16_t DISCOVERY_APP_MAJOR_VERSION = 1;
|
|
const uint16_t DISCOVERY_APP_MINOR_VERSION = 0;
|
|
const uint16_t DISCOVERY_MIN_MAJOR_VERSION = 1;
|
|
const uint16_t DISCOVERY_MIN_MINOR_VERSION = 0;
|
|
|
|
RsServiceInfo p3discovery2::getServiceInfo()
|
|
{
|
|
return RsServiceInfo(RS_SERVICE_TYPE_DISC,
|
|
DISCOVERY_APP_NAME,
|
|
DISCOVERY_APP_MAJOR_VERSION,
|
|
DISCOVERY_APP_MINOR_VERSION,
|
|
DISCOVERY_MIN_MAJOR_VERSION,
|
|
DISCOVERY_MIN_MINOR_VERSION);
|
|
}
|
|
|
|
p3discovery2::~p3discovery2()
|
|
{ rsEvents->unregisterEventsHandler(mRsEventsHandle); }
|
|
|
|
void p3discovery2::addFriend(const SSLID &sslId)
|
|
{
|
|
PGPID pgpId = getPGPId(sslId);
|
|
|
|
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
std::map<PGPID, DiscPgpInfo>::iterator it;
|
|
it = mFriendList.find(pgpId);
|
|
if (it == mFriendList.end())
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::addFriend() adding pgp entry: " << pgpId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
mFriendList[pgpId] = DiscPgpInfo();
|
|
|
|
it = mFriendList.find(pgpId);
|
|
}
|
|
|
|
|
|
/* now add SSLID */
|
|
|
|
std::map<SSLID, DiscSslInfo>::iterator sit;
|
|
sit = it->second.mSslIds.find(sslId);
|
|
if (sit == it->second.mSslIds.end())
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::addFriend() adding ssl entry: " << sslId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
it->second.mSslIds[sslId] = DiscSslInfo();
|
|
sit = it->second.mSslIds.find(sslId);
|
|
}
|
|
|
|
/* update Settings from peerMgr */
|
|
peerState detail;
|
|
if (mPeerMgr->getFriendNetStatus(sit->first, detail))
|
|
{
|
|
sit->second.mDiscStatus = detail.vs_disc;
|
|
}
|
|
else
|
|
{
|
|
sit->second.mDiscStatus = RS_VS_DISC_OFF;
|
|
}
|
|
}
|
|
|
|
void p3discovery2::removeFriend(const SSLID &sslId)
|
|
{
|
|
PGPID pgpId = getPGPId(sslId);
|
|
|
|
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
std::map<PGPID, DiscPgpInfo>::iterator it;
|
|
it = mFriendList.find(pgpId);
|
|
if (it == mFriendList.end())
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::removeFriend() missing pgp entry: " << pgpId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
std::map<SSLID, DiscSslInfo>::iterator sit;
|
|
sit = it->second.mSslIds.find(sslId);
|
|
if (sit == it->second.mSslIds.end())
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::addFriend() missing ssl entry: " << sslId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::addFriend() removing ssl entry: " << sslId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
it->second.mSslIds.erase(sit);
|
|
|
|
if (it->second.mSslIds.empty())
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::addFriend() pgpId now has no sslIds";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
/* pgp peer without any ssl entries -> check if they are still a real friend */
|
|
if (!(AuthGPG::getAuthGPG()->isGPGAccepted(pgpId)))
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::addFriend() pgpId is no longer a friend, removing";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mFriendList.erase(it);
|
|
}
|
|
}
|
|
}
|
|
|
|
PGPID p3discovery2::getPGPId(const SSLID &id)
|
|
{
|
|
PGPID pgpId;
|
|
mPeerMgr->getGpgId(id, pgpId);
|
|
return pgpId;
|
|
}
|
|
|
|
int p3discovery2::tick()
|
|
{
|
|
return handleIncoming();
|
|
}
|
|
|
|
int p3discovery2::handleIncoming()
|
|
{
|
|
RsItem* item = nullptr;
|
|
|
|
int nhandled = 0;
|
|
// While messages read
|
|
while(nullptr != (item = recvItem()))
|
|
{
|
|
RsDiscPgpListItem* pgplist = nullptr;
|
|
RsDiscPgpCertItem* pgpcert = nullptr;
|
|
RsDiscContactItem* contact = nullptr;
|
|
RsDiscIdentityListItem* gxsidlst = nullptr;
|
|
RsGossipDiscoveryInviteItem* invite = nullptr;
|
|
RsGossipDiscoveryInviteRequestItem* inviteReq = nullptr;
|
|
|
|
++nhandled;
|
|
|
|
Dbg4() << __PRETTY_FUNCTION__ << " Received item: " << std::endl
|
|
<< *item << std::endl;
|
|
|
|
if((contact = dynamic_cast<RsDiscContactItem *>(item)) != nullptr)
|
|
{
|
|
if (item->PeerId() == contact->sslId)
|
|
recvOwnContactInfo(item->PeerId(), contact);
|
|
else processContactInfo(item->PeerId(), contact);
|
|
}
|
|
else if( (gxsidlst = dynamic_cast<RsDiscIdentityListItem *>(item))
|
|
!= nullptr )
|
|
{
|
|
recvIdentityList(item->PeerId(),gxsidlst->ownIdentityList);
|
|
delete item;
|
|
}
|
|
else if((pgpcert = dynamic_cast<RsDiscPgpCertItem *>(item)) != nullptr)
|
|
recvPGPCertificate(item->PeerId(), pgpcert);
|
|
else if((pgplist = dynamic_cast<RsDiscPgpListItem *>(item)) != nullptr)
|
|
{
|
|
if (pgplist->mode == RsGossipDiscoveryPgpListMode::FRIENDS)
|
|
processPGPList(pgplist->PeerId(), pgplist);
|
|
else if (pgplist->mode == RsGossipDiscoveryPgpListMode::GETCERT)
|
|
recvPGPCertificateRequest(pgplist->PeerId(), pgplist);
|
|
else delete item;
|
|
}
|
|
else if( (invite = dynamic_cast<RsGossipDiscoveryInviteItem*>(item))
|
|
!= nullptr )
|
|
recvInvite(std::unique_ptr<RsGossipDiscoveryInviteItem>(invite));
|
|
else if( (inviteReq =
|
|
dynamic_cast<RsGossipDiscoveryInviteRequestItem*>(item))
|
|
!= nullptr )
|
|
{
|
|
sendInvite(inviteReq->mInviteId, item->PeerId());
|
|
delete item;
|
|
}
|
|
else
|
|
{
|
|
RsWarn() << __PRETTY_FUNCTION__ << " Received unknown item type! "
|
|
<< std::endl << item << std::endl;
|
|
delete item;
|
|
}
|
|
}
|
|
|
|
return nhandled;
|
|
}
|
|
|
|
void p3discovery2::sendOwnContactInfo(const SSLID &sslid)
|
|
{
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendOwnContactInfo()";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
peerState detail;
|
|
if (mPeerMgr->getOwnNetStatus(detail))
|
|
{
|
|
RsDiscContactItem *pkt = new RsDiscContactItem();
|
|
/* Cyril: we dont send our own IP to an hidden node. It will not use it
|
|
* anyway. */
|
|
populateContactInfo(detail, pkt, !rsPeers->isHiddenNode(sslid));
|
|
/* G10h4ck: sending IP information also to hidden nodes has proven very
|
|
* helpful in the usecase of non hidden nodes, that share a common
|
|
* hidden trusted node, to discover each other IP.
|
|
* Advanced/corner case non hidden node users that want to hide their
|
|
* IP to a specific hidden ~trusted~ node can do it through the
|
|
* permission matrix. Disabling this instead will make life more
|
|
* difficult for average user, that moreover whould have no way to
|
|
* revert an hardcoded policy. */
|
|
//populateContactInfo(detail, pkt, true);
|
|
|
|
pkt->version = RS_HUMAN_READABLE_VERSION;
|
|
pkt->PeerId(sslid);
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendOwnContactInfo() sending:" << std::endl;
|
|
pkt -> print(std::cerr);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
sendItem(pkt);
|
|
|
|
RsDiscIdentityListItem *pkt2 = new RsDiscIdentityListItem();
|
|
|
|
rsIdentity->getOwnIds(pkt2->ownIdentityList,true);
|
|
pkt2->PeerId(sslid) ;
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendOwnContactInfo() sending own signed identity list:" << std::endl;
|
|
for(auto it(pkt2->ownIdentityList.begin());it!=pkt2->ownIdentityList.end();++it)
|
|
std::cerr << " identity: " << (*it).toStdString() << std::endl;
|
|
#endif
|
|
sendItem(pkt2);
|
|
}
|
|
}
|
|
|
|
void p3discovery2::recvOwnContactInfo(const SSLID &fromId, const RsDiscContactItem *item)
|
|
{
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::recvOwnContactInfo()";
|
|
std::cerr << std::endl;
|
|
|
|
std::cerr << "Info sent by the peer itself -> updating self info:" << std::endl;
|
|
std::cerr << " -> vs_disc : " << item->vs_disc << std::endl;
|
|
std::cerr << " -> vs_dht : " << item->vs_dht << std::endl;
|
|
std::cerr << " -> network mode : " << item->netMode << std::endl;
|
|
std::cerr << " -> location : " << item->location << std::endl;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
// Peer Own Info replaces the existing info, because the
|
|
// peer is the primary source of his own IPs.
|
|
|
|
mPeerMgr->setNetworkMode(fromId, item->netMode);
|
|
mPeerMgr->setLocation(fromId, item->location);
|
|
mPeerMgr->setVisState(fromId, item->vs_disc, item->vs_dht);
|
|
|
|
setPeerVersion(fromId, item->version);
|
|
|
|
updatePeerAddresses(item);
|
|
|
|
// This information will be sent out to online peers, at the receipt of their PGPList.
|
|
// It is important that PGPList is received after the OwnContactItem.
|
|
// This should happen, but is not enforced by the protocol.
|
|
|
|
// start peer list exchange.
|
|
sendPGPList(fromId);
|
|
|
|
// Update mDiscStatus.
|
|
RS_STACK_MUTEX(mDiscMtx);
|
|
|
|
PGPID pgpId = getPGPId(fromId);
|
|
std::map<PGPID, DiscPgpInfo>::iterator it = mFriendList.find(pgpId);
|
|
if (it != mFriendList.end())
|
|
{
|
|
std::map<SSLID, DiscSslInfo>::iterator sit = it->second.mSslIds.find(fromId);
|
|
if (sit != it->second.mSslIds.end())
|
|
{
|
|
sit->second.mDiscStatus = item->vs_disc;
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::recvOwnContactInfo()";
|
|
std::cerr << "updating mDiscStatus to: " << sit->second.mDiscStatus;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::recvOwnContactInfo()";
|
|
std::cerr << " ERROR missing SSL Entry: " << fromId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::recvOwnContactInfo()";
|
|
std::cerr << " ERROR missing PGP Entry: " << pgpId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
|
|
// cleanup.
|
|
delete item;
|
|
}
|
|
|
|
void p3discovery2::recvIdentityList(const RsPeerId& pid,const std::list<RsGxsId>& ids)
|
|
{
|
|
std::list<RsPeerId> peers;
|
|
peers.push_back(pid);
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::recvIdentityList(): from peer " << pid << ": " << ids.size() << " identities" << std::endl;
|
|
#endif
|
|
|
|
RsIdentityUsage use_info(RS_SERVICE_TYPE_DISC,RsIdentityUsage::IDENTITY_DATA_UPDATE);
|
|
|
|
for(auto it(ids.begin());it!=ids.end();++it)
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << " identity: " << (*it).toStdString() << std::endl;
|
|
#endif
|
|
mGixs->requestKey(*it,peers,use_info) ;
|
|
}
|
|
}
|
|
|
|
void p3discovery2::updatePeerAddresses(const RsDiscContactItem *item)
|
|
{
|
|
if (item->isHidden)
|
|
mPeerMgr->setHiddenDomainPort(item->sslId, item->hiddenAddr,
|
|
item->hiddenPort);
|
|
else
|
|
{
|
|
mPeerMgr->setDynDNS(item->sslId, item->dyndns);
|
|
updatePeerAddressList(item);
|
|
}
|
|
}
|
|
|
|
void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item)
|
|
{
|
|
if (item->isHidden)
|
|
{
|
|
}
|
|
else if(!mPeerMgr->isHiddenNode(rsPeers->getOwnId()))
|
|
{
|
|
/* Cyril: we don't store IP addresses if we're a hidden node.
|
|
* Normally they should not be sent to us, except for old peers. */
|
|
/* G10h4ck: sending IP information also to hidden nodes has proven very
|
|
* helpful in the usecase of non hidden nodes, that share a common
|
|
* hidden trusted node, to discover each other IP.
|
|
* Advanced/corner case non hidden node users that want to hide their
|
|
* IP to a specific hidden ~trusted~ node can do it through the
|
|
* permission matrix. Disabling this instead will make life more
|
|
* difficult for average user, that moreover whould have no way to
|
|
* revert an hardcoded policy. */
|
|
pqiIpAddrSet addrsFromPeer;
|
|
addrsFromPeer.mLocal.extractFromTlv(item->localAddrList);
|
|
addrsFromPeer.mExt.extractFromTlv(item->extAddrList);
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "Setting address list to peer " << item->sslId
|
|
<< ", to be:" << std::endl ;
|
|
|
|
std::string addrstr;
|
|
addrsFromPeer.printAddrs(addrstr);
|
|
std::cerr << addrstr;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mPeerMgr->updateAddressList(item->sslId, addrsFromPeer);
|
|
}
|
|
}
|
|
|
|
// Starts the Discovery process.
|
|
// should only be called it DISC2_STATUS_NOT_HIDDEN(OwnInfo.status).
|
|
void p3discovery2::sendPGPList(const SSLID &toId)
|
|
{
|
|
updatePgpFriendList();
|
|
|
|
RS_STACK_MUTEX(mDiscMtx);
|
|
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendPGPList() to " << toId << std::endl;
|
|
#endif
|
|
|
|
RsDiscPgpListItem *pkt = new RsDiscPgpListItem();
|
|
|
|
pkt->mode = RsGossipDiscoveryPgpListMode::FRIENDS;
|
|
|
|
std::map<PGPID, DiscPgpInfo>::const_iterator it;
|
|
for(it = mFriendList.begin(); it != mFriendList.end(); ++it)
|
|
{
|
|
pkt->pgpIdSet.ids.insert(it->first);
|
|
}
|
|
|
|
pkt->PeerId(toId);
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendPGPList() sending:" << std::endl;
|
|
pkt->print(std::cerr);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
sendItem(pkt);
|
|
}
|
|
|
|
void p3discovery2::updatePgpFriendList()
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePgpFriendList()";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
RS_STACK_MUTEX(mDiscMtx);
|
|
|
|
#define PGP_MAX_UPDATE_PERIOD 300
|
|
|
|
if (time(NULL) < mLastPgpUpdate + PGP_MAX_UPDATE_PERIOD )
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePgpFriendList() Already uptodate";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
mLastPgpUpdate = time(NULL);
|
|
|
|
std::list<PGPID> pgpList;
|
|
std::set<PGPID> pgpSet;
|
|
|
|
std::set<PGPID>::iterator sit;
|
|
std::list<PGPID>::iterator lit;
|
|
std::map<PGPID, DiscPgpInfo>::iterator it;
|
|
|
|
PGPID ownPgpId = AuthGPG::getAuthGPG()->getGPGOwnId();
|
|
AuthGPG::getAuthGPG()->getGPGAcceptedList(pgpList);
|
|
pgpList.push_back(ownPgpId);
|
|
|
|
// convert to set for ordering.
|
|
for(lit = pgpList.begin(); lit != pgpList.end(); ++lit)
|
|
{
|
|
pgpSet.insert(*lit);
|
|
}
|
|
|
|
std::list<PGPID> pgpToAdd;
|
|
std::list<PGPID> pgpToRemove;
|
|
|
|
|
|
sit = pgpSet.begin();
|
|
it = mFriendList.begin();
|
|
while (sit != pgpSet.end() && it != mFriendList.end())
|
|
{
|
|
if (*sit < it->first)
|
|
{
|
|
/* to add */
|
|
pgpToAdd.push_back(*sit);
|
|
++sit;
|
|
}
|
|
else if (it->first < *sit)
|
|
{
|
|
/* to remove */
|
|
pgpToRemove.push_back(it->first);
|
|
++it;
|
|
}
|
|
else
|
|
{
|
|
/* same - okay */
|
|
++sit;
|
|
++it;
|
|
}
|
|
}
|
|
|
|
/* more to add? */
|
|
for(; sit != pgpSet.end(); ++sit)
|
|
{
|
|
pgpToAdd.push_back(*sit);
|
|
}
|
|
|
|
for(; it != mFriendList.end(); ++it)
|
|
{
|
|
/* more to remove */
|
|
pgpToRemove.push_back(it->first);
|
|
}
|
|
|
|
for(lit = pgpToRemove.begin(); lit != pgpToRemove.end(); ++lit)
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePgpFriendList() Removing pgpId: " << *lit;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
it = mFriendList.find(*lit);
|
|
mFriendList.erase(it);
|
|
}
|
|
|
|
for(lit = pgpToAdd.begin(); lit != pgpToAdd.end(); ++lit)
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePgpFriendList() Adding pgpId: " << *lit;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
mFriendList[*lit] = DiscPgpInfo();
|
|
}
|
|
|
|
/* finally install the pgpList on our own entry */
|
|
DiscPgpInfo &ownInfo = mFriendList[ownPgpId];
|
|
ownInfo.mergeFriendList(pgpSet);
|
|
|
|
}
|
|
|
|
void p3discovery2::processPGPList(const SSLID &fromId, const RsDiscPgpListItem *item)
|
|
{
|
|
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::processPGPList() from " << fromId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
std::map<PGPID, DiscPgpInfo>::iterator it;
|
|
PGPID fromPgpId = getPGPId(fromId);
|
|
it = mFriendList.find(fromPgpId);
|
|
if (it == mFriendList.end())
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::processPGPList() is not friend: " << fromId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
// cleanup.
|
|
delete item;
|
|
return;
|
|
}
|
|
|
|
bool requestUnknownPgpCerts = true;
|
|
peerState pstate;
|
|
mPeerMgr->getOwnNetStatus(pstate);
|
|
if (pstate.vs_disc != RS_VS_DISC_FULL)
|
|
{
|
|
requestUnknownPgpCerts = false;
|
|
}
|
|
|
|
uint32_t linkType = mLinkMgr->getLinkType(fromId);
|
|
if ((linkType & RS_NET_CONN_SPEED_TRICKLE) ||
|
|
(linkType & RS_NET_CONN_SPEED_LOW))
|
|
{
|
|
std::cerr << "p3discovery2::processPGPList() Not requesting Certificates from: " << fromId;
|
|
std::cerr << " (low bandwidth)" << std::endl;
|
|
requestUnknownPgpCerts = false;
|
|
}
|
|
|
|
if (requestUnknownPgpCerts)
|
|
{
|
|
std::set<PGPID>::const_iterator fit;
|
|
for(fit = item->pgpIdSet.ids.begin(); fit != item->pgpIdSet.ids.end(); ++fit)
|
|
{
|
|
if (!AuthGPG::getAuthGPG()->isGPGId(*fit))
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::processPGPList() requesting PgpId: " << *fit;
|
|
std::cerr << " from SslId: " << fromId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
requestPGPCertificate(*fit, fromId);
|
|
}
|
|
}
|
|
}
|
|
|
|
it->second.mergeFriendList(item->pgpIdSet.ids);
|
|
updatePeers_locked(fromId);
|
|
|
|
// cleanup.
|
|
delete item;
|
|
}
|
|
|
|
|
|
/*
|
|
* -> Update Other Peers about B.
|
|
* -> Update B about Other Peers.
|
|
*/
|
|
void p3discovery2::updatePeers_locked(const SSLID &aboutId)
|
|
{
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePeers_locked() about " << aboutId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
PGPID aboutPgpId = getPGPId(aboutId);
|
|
|
|
std::map<PGPID, DiscPgpInfo>::const_iterator ait;
|
|
ait = mFriendList.find(aboutPgpId);
|
|
if (ait == mFriendList.end())
|
|
{
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePeers_locked() PgpId is not a friend: " << aboutPgpId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
std::set<PGPID> mutualFriends;
|
|
std::set<SSLID> onlineFriends;
|
|
std::set<SSLID>::const_iterator sit;
|
|
|
|
const std::set<PGPID> &friendSet = ait->second.mFriendSet;
|
|
std::set<PGPID>::const_iterator fit;
|
|
for(fit = friendSet.begin(); fit != friendSet.end(); ++fit)
|
|
{
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePeer_locked() checking their friend: " << *fit;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
std::map<PGPID, DiscPgpInfo>::const_iterator ffit;
|
|
ffit = mFriendList.find(*fit);
|
|
if (ffit == mFriendList.end())
|
|
{
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePeer_locked() Ignoring not our friend";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
// Not our friend, or we have no Locations (SSL) for this PGPID (same difference)
|
|
continue;
|
|
}
|
|
|
|
if (ffit->second.mFriendSet.find(aboutPgpId) != ffit->second.mFriendSet.end())
|
|
{
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePeer_locked() Adding as Mutual Friend";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mutualFriends.insert(*fit);
|
|
|
|
std::map<SSLID, DiscSslInfo>::const_iterator mit;
|
|
for(mit = ffit->second.mSslIds.begin();
|
|
mit != ffit->second.mSslIds.end(); ++mit)
|
|
{
|
|
SSLID sslid = mit->first;
|
|
if (mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, sslid))
|
|
{
|
|
// TODO IGNORE if sslid == aboutId, or sslid == ownId.
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePeer_locked() Adding Online SSLID: " << sslid;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
onlineFriends.insert(sslid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePeer_locked() Updating " << aboutId << " about Mutual Friends";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
// update aboutId about Other Peers.
|
|
for(fit = mutualFriends.begin(); fit != mutualFriends.end(); ++fit)
|
|
{
|
|
sendContactInfo_locked(*fit, aboutId);
|
|
}
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::updatePeer_locked() Updating Online Peers about " << aboutId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
// update Other Peers about aboutPgpId.
|
|
for(sit = onlineFriends.begin(); sit != onlineFriends.end(); ++sit)
|
|
{
|
|
// This could be more efficient, and only be specific about aboutId.
|
|
// but we'll leave it like this for the moment.
|
|
sendContactInfo_locked(aboutPgpId, *sit);
|
|
}
|
|
}
|
|
|
|
void p3discovery2::sendContactInfo_locked(const PGPID &aboutId, const SSLID &toId)
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendContactInfo_locked() aboutPGPId: " << aboutId << " toId: " << toId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
std::map<PGPID, DiscPgpInfo>::const_iterator it;
|
|
it = mFriendList.find(aboutId);
|
|
if (it == mFriendList.end())
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendContactInfo_locked() ERROR aboutId is not a friend";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
std::map<SSLID, DiscSslInfo>::const_iterator sit;
|
|
for(sit = it->second.mSslIds.begin(); sit != it->second.mSslIds.end(); ++sit)
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendContactInfo_locked() related sslId: " << sit->first;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (sit->first == rsPeers->getOwnId())
|
|
{
|
|
// sending info of toId to himself will be used by toId to check that the IP it is connected as is the same
|
|
// as its external IP.
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::processContactInfo() not sending info on self";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
continue;
|
|
}
|
|
|
|
if (sit->second.mDiscStatus != RS_VS_DISC_OFF)
|
|
{
|
|
peerState detail;
|
|
peerConnectState detail2;
|
|
|
|
if (mPeerMgr->getFriendNetStatus(sit->first, detail))
|
|
{
|
|
RsDiscContactItem *pkt = new RsDiscContactItem();
|
|
populateContactInfo(detail, pkt,!mPeerMgr->isHiddenNode(toId));// never send IPs to an hidden node. The node will not use them anyway.
|
|
pkt->PeerId(toId);
|
|
|
|
// send to each peer its own connection address.
|
|
|
|
if(sit->first == toId && mLinkMgr->getFriendNetStatus(sit->first,detail2))
|
|
pkt->currentConnectAddress.addr = detail2.connectaddr;
|
|
else
|
|
sockaddr_storage_clear(pkt->currentConnectAddress.addr) ;
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendContactInfo_locked() Sending";
|
|
std::cerr << std::endl;
|
|
pkt->print(std::cerr);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
sendItem(pkt);
|
|
}
|
|
else
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendContactInfo_locked() No Net Status";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::sendContactInfo_locked() SSLID Hidden";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
void p3discovery2::processContactInfo(const SSLID &fromId, const RsDiscContactItem *item)
|
|
{
|
|
(void) fromId; // remove unused parameter warnings, debug only
|
|
|
|
RS_STACK_MUTEX(mDiscMtx);
|
|
|
|
if (item->sslId == rsPeers->getOwnId())
|
|
{
|
|
if(sockaddr_storage_isExternalNet(item->currentConnectAddress.addr))
|
|
mPeerMgr->addCandidateForOwnExternalAddress(
|
|
item->PeerId(), item->currentConnectAddress.addr);
|
|
|
|
delete item;
|
|
return;
|
|
}
|
|
|
|
std::map<PGPID, DiscPgpInfo>::iterator it;
|
|
it = mFriendList.find(item->pgpId);
|
|
if (it == mFriendList.end())
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::processContactInfo(" << fromId << ") PGPID: ";
|
|
std::cerr << item->pgpId << " Not Friend.";
|
|
std::cerr << std::endl;
|
|
std::cerr << "p3discovery2::processContactInfo(" << fromId << ") THIS SHOULD NEVER HAPPEN!";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* THESE ARE OUR FRIEND OF FRIENDS ... pass this information along to
|
|
* NetMgr & DHT...
|
|
* as we can track FOF and use them as potential Proxies / Relays
|
|
*/
|
|
|
|
if (!item->isHidden)
|
|
{
|
|
/* add into NetMgr and non-search, so we can detect connect attempts */
|
|
mNetMgr->netAssistFriend(item->sslId,false);
|
|
|
|
/* inform NetMgr that we know this peer */
|
|
mNetMgr->netAssistKnownPeer(item->sslId, item->extAddrV4.addr,
|
|
NETASSIST_KNOWN_PEER_FOF | NETASSIST_KNOWN_PEER_OFFLINE);
|
|
}
|
|
delete item;
|
|
return;
|
|
}
|
|
|
|
bool should_notify_discovery = false;
|
|
std::map<SSLID, DiscSslInfo>::iterator sit;
|
|
sit = it->second.mSslIds.find(item->sslId);
|
|
if (sit == it->second.mSslIds.end())
|
|
{
|
|
/* insert! */
|
|
DiscSslInfo sslInfo;
|
|
it->second.mSslIds[item->sslId] = sslInfo;
|
|
//sit = it->second.mSslIds.find(item->sslId);
|
|
|
|
should_notify_discovery = true;
|
|
|
|
if (!mPeerMgr->isFriend(item->sslId))
|
|
{
|
|
// Add with no disc by default. If friend already exists, it will do nothing
|
|
// NO DISC is important - otherwise, we'll just enter a nasty loop,
|
|
// where every addition triggers requests, then they are cleaned up, and readded...
|
|
|
|
// This way we get their addresses, but don't advertise them until we get a
|
|
// connection.
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "--> Adding to friends list " << item->sslId << " - " << item->pgpId << std::endl;
|
|
#endif
|
|
// We pass RS_NODE_PERM_ALL because the PGP id is already a friend, so we should keep the existing
|
|
// permission flags. Therefore the mask needs to be 0xffff.
|
|
|
|
// set last seen to RS_PEER_OFFLINE_NO_DISC minus 1 so that it won't be shared with other friends
|
|
// until a first connection is established
|
|
|
|
mPeerMgr->addFriend( item->sslId, item->pgpId, item->netMode,
|
|
RS_VS_DISC_OFF, RS_VS_DHT_FULL,
|
|
time(NULL) - RS_PEER_OFFLINE_NO_DISC - 1,
|
|
RS_NODE_PERM_ALL );
|
|
updatePeerAddresses(item);
|
|
}
|
|
}
|
|
|
|
updatePeerAddressList(item);
|
|
|
|
|
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_NEIGHBOURS, NOTIFY_TYPE_MOD);
|
|
|
|
if(should_notify_discovery)
|
|
RsServer::notify()->notifyDiscInfoChanged();
|
|
|
|
delete item;
|
|
}
|
|
|
|
/* we explictly request certificates, instead of getting them all the time
|
|
*/
|
|
void p3discovery2::requestPGPCertificate(const PGPID &aboutId, const SSLID &toId)
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::requestPGPCertificate() aboutId: " << aboutId << " to: " << toId;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
RsDiscPgpListItem *pkt = new RsDiscPgpListItem();
|
|
|
|
pkt->mode = RsGossipDiscoveryPgpListMode::GETCERT;
|
|
pkt->pgpIdSet.ids.insert(aboutId);
|
|
pkt->PeerId(toId);
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::requestPGPCertificate() sending:" << std::endl;
|
|
pkt->print(std::cerr);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
sendItem(pkt);
|
|
}
|
|
|
|
void p3discovery2::recvPGPCertificateRequest(
|
|
const RsPeerId& fromId, const RsDiscPgpListItem* item )
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << __PRETTY_FUNCTION__ << " from " << fromId << std::endl;
|
|
#endif
|
|
|
|
RsPgpId ownPgpId = AuthGPG::getAuthGPG()->getGPGOwnId();
|
|
for(const RsPgpId& pgpId : item->pgpIdSet.ids)
|
|
if (pgpId == ownPgpId || AuthGPG::getAuthGPG()->isGPGAccepted(pgpId))
|
|
sendPGPCertificate(pgpId, fromId);
|
|
delete item;
|
|
}
|
|
|
|
|
|
void p3discovery2::sendPGPCertificate(const PGPID &aboutId, const SSLID &toId)
|
|
{
|
|
RsDiscPgpCertItem* item = new RsDiscPgpCertItem();
|
|
item->pgpId = aboutId;
|
|
item->PeerId(toId);
|
|
|
|
Dbg4() << __PRETTY_FUNCTION__ << " queuing for Cert generation: "
|
|
<< std::endl << *item << std::endl;
|
|
|
|
{
|
|
RS_STACK_MUTEX(mDiscMtx);
|
|
mPendingDiscPgpCertOutList.push_back(item);
|
|
}
|
|
}
|
|
|
|
void p3discovery2::recvPGPCertificate(
|
|
const SSLID& /*fromId*/, RsDiscPgpCertItem* item )
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << __PRETTY_FUNCTION__ << " queuing for Cert loading" << std::endl;
|
|
#endif
|
|
/* push this back to be processed by pgp when possible */
|
|
RS_STACK_MUTEX(mDiscMtx);
|
|
mPendingDiscPgpCertInList.push_back(item);
|
|
}
|
|
|
|
/************* from pqiServiceMonitor *******************/
|
|
void p3discovery2::statusChange(const std::list<pqiServicePeer> &plist)
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::statusChange()" << std::endl;
|
|
#endif
|
|
|
|
std::list<pqiServicePeer>::const_iterator pit;
|
|
for(pit = plist.begin(); pit != plist.end(); ++pit)
|
|
{
|
|
if (pit->actions & RS_SERVICE_PEER_CONNECTED)
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::statusChange() Starting Disc with: " << pit->id << std::endl;
|
|
#endif
|
|
sendOwnContactInfo(pit->id);
|
|
}
|
|
else if (pit->actions & RS_SERVICE_PEER_DISCONNECTED)
|
|
{
|
|
std::cerr << "p3discovery2::statusChange() Disconnected: " << pit->id << std::endl;
|
|
}
|
|
|
|
if (pit->actions & RS_SERVICE_PEER_NEW)
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::statusChange() Adding Friend: " << pit->id << std::endl;
|
|
#endif
|
|
addFriend(pit->id);
|
|
}
|
|
else if (pit->actions & RS_SERVICE_PEER_REMOVED)
|
|
{
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::statusChange() Removing Friend: " << pit->id << std::endl;
|
|
#endif
|
|
removeFriend(pit->id);
|
|
}
|
|
}
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::statusChange() finished." << std::endl;
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
|
|
/*************************************************************************************/
|
|
/* Extracting Network Graph Details */
|
|
/*************************************************************************************/
|
|
bool p3discovery2::getDiscFriends(const RsPeerId& id, std::list<RsPeerId> &proxyIds)
|
|
{
|
|
// This is treated appart, because otherwise we don't receive any disc info about us
|
|
if(id == rsPeers->getOwnId()) // SSL id
|
|
return rsPeers->getFriendList(proxyIds) ;
|
|
|
|
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
std::map<PGPID, DiscPgpInfo>::const_iterator it;
|
|
PGPID pgp_id = getPGPId(id);
|
|
|
|
it = mFriendList.find(pgp_id);
|
|
if (it == mFriendList.end())
|
|
{
|
|
// ERROR.
|
|
return false;
|
|
}
|
|
|
|
// For each of their friends that we know, grab that set of SSLIDs.
|
|
const std::set<PGPID> &friendSet = it->second.mFriendSet;
|
|
std::set<PGPID>::const_iterator fit;
|
|
for(fit = friendSet.begin(); fit != friendSet.end(); ++fit)
|
|
{
|
|
it = mFriendList.find(*fit);
|
|
if (it == mFriendList.end())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
std::map<SSLID, DiscSslInfo>::const_iterator sit;
|
|
for(sit = it->second.mSslIds.begin();
|
|
sit != it->second.mSslIds.end(); ++sit)
|
|
{
|
|
proxyIds.push_back(sit->first);
|
|
}
|
|
}
|
|
return true;
|
|
|
|
}
|
|
|
|
bool p3discovery2::getWaitingDiscCount(size_t &sendCount, size_t &recvCount)
|
|
{
|
|
RS_STACK_MUTEX(mDiscMtx);
|
|
sendCount = mPendingDiscPgpCertOutList.size();
|
|
recvCount = mPendingDiscPgpCertInList.size();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool p3discovery2::sendInvite(
|
|
const RsPeerId& inviteId, const RsPeerId& toSslId,
|
|
std::string& errorMsg )
|
|
{
|
|
RsPeers& mPeers = *rsPeers;
|
|
|
|
std::string&& invite = mPeers.GetRetroshareInvite(inviteId);
|
|
|
|
if(invite.empty())
|
|
{
|
|
errorMsg = "Failure generating invite for peer: " +
|
|
inviteId.toStdString() + " are you sure is a friend?";
|
|
RsErr() << __PRETTY_FUNCTION__ << " " << errorMsg << std::endl;
|
|
return false;
|
|
}
|
|
|
|
RsGossipDiscoveryInviteItem* item = new RsGossipDiscoveryInviteItem;
|
|
item->PeerId(toSslId);
|
|
item->mInvite = mPeers.GetRetroshareInvite(inviteId, true, true);
|
|
|
|
return sendItem(item);
|
|
}
|
|
|
|
bool p3discovery2::requestInvite(
|
|
const RsPeerId& inviteId, const RsPeerId& toSslId,
|
|
std::string& /*errorMsg*/ )
|
|
{
|
|
Dbg2() << __PRETTY_FUNCTION__ << " inviteId: " << inviteId
|
|
<< " toSslId: " << toSslId << std::endl;
|
|
|
|
RsGossipDiscoveryInviteRequestItem* item =
|
|
new RsGossipDiscoveryInviteRequestItem;
|
|
item->PeerId(toSslId);
|
|
item->mInviteId = inviteId;
|
|
|
|
return sendItem(item);
|
|
}
|
|
|
|
bool p3discovery2::getDiscPgpFriends(const PGPID &pgp_id, std::list<PGPID> &proxyPgpIds)
|
|
{
|
|
/* find id -> and extract the neighbour_of ids */
|
|
|
|
if(pgp_id == rsPeers->getGPGOwnId()) // SSL id // This is treated appart, because otherwise we don't receive any disc info about us
|
|
return rsPeers->getGPGAcceptedList(proxyPgpIds) ;
|
|
|
|
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
std::map<PGPID, DiscPgpInfo>::const_iterator it;
|
|
it = mFriendList.find(pgp_id);
|
|
if (it == mFriendList.end())
|
|
{
|
|
// ERROR.
|
|
return false;
|
|
}
|
|
|
|
std::set<PGPID>::const_iterator fit;
|
|
for(fit = it->second.mFriendSet.begin(); fit != it->second.mFriendSet.end(); ++fit)
|
|
{
|
|
proxyPgpIds.push_back(*fit);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool p3discovery2::getPeerVersion(const SSLID &peerId, std::string &version)
|
|
{
|
|
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
std::map<SSLID, DiscPeerInfo>::const_iterator it;
|
|
it = mLocationMap.find(peerId);
|
|
if (it == mLocationMap.end())
|
|
{
|
|
// MISSING.
|
|
return false;
|
|
}
|
|
|
|
version = it->second.mVersion;
|
|
return true;
|
|
}
|
|
|
|
bool p3discovery2::setPeerVersion(const SSLID &peerId, const std::string &version)
|
|
{
|
|
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
std::map<SSLID, DiscPeerInfo>::iterator it;
|
|
it = mLocationMap.find(peerId);
|
|
if (it == mLocationMap.end())
|
|
{
|
|
mLocationMap[peerId] = DiscPeerInfo();
|
|
it = mLocationMap.find(peerId);
|
|
}
|
|
|
|
it->second.mVersion = version;
|
|
return true;
|
|
}
|
|
|
|
void p3discovery2::recvInvite(
|
|
std::unique_ptr<RsGossipDiscoveryInviteItem> inviteItem )
|
|
{
|
|
typedef RsGossipDiscoveryFriendInviteReceivedEvent Evt_t;
|
|
|
|
// Ensure rsEvents is not deleted while we use it
|
|
std::shared_ptr<RsEvents> lockedRsEvents = rsEvents;
|
|
if(lockedRsEvents)
|
|
lockedRsEvents->postEvent(
|
|
std::unique_ptr<Evt_t>(new Evt_t(inviteItem->mInvite)) );
|
|
}
|
|
|
|
void p3discovery2::rsEventsHandler(const RsEvent& event)
|
|
{
|
|
switch(event.mType)
|
|
{
|
|
// TODO: When an SSL-only friend become online requestInvite(...)
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
|
|
/*************************************************************************************/
|
|
/* AuthGPGService */
|
|
/*************************************************************************************/
|
|
AuthGPGOperation *p3discovery2::getGPGOperation()
|
|
{
|
|
{
|
|
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
/* process disc reply in list */
|
|
if (!mPendingDiscPgpCertInList.empty()) {
|
|
RsDiscPgpCertItem *item = mPendingDiscPgpCertInList.front();
|
|
mPendingDiscPgpCertInList.pop_front();
|
|
|
|
return new AuthGPGOperationLoadOrSave(true, item->pgpId, item->pgpCert, item);
|
|
}
|
|
}
|
|
|
|
{
|
|
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
/* process disc reply in list */
|
|
if (!mPendingDiscPgpCertOutList.empty()) {
|
|
RsDiscPgpCertItem *item = mPendingDiscPgpCertOutList.front();
|
|
mPendingDiscPgpCertOutList.pop_front();
|
|
|
|
return new AuthGPGOperationLoadOrSave(false, item->pgpId, "", item);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void p3discovery2::setGPGOperation(AuthGPGOperation *operation)
|
|
{
|
|
AuthGPGOperationLoadOrSave *loadOrSave = dynamic_cast<AuthGPGOperationLoadOrSave*>(operation);
|
|
if (loadOrSave)
|
|
{
|
|
RsDiscPgpCertItem *item = (RsDiscPgpCertItem *) loadOrSave->m_userdata;
|
|
if (!item)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (loadOrSave->m_load)
|
|
{
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::setGPGOperation() Loaded Cert" << std::endl;
|
|
item->print(std::cerr, 5);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
// It has already been processed by PGP.
|
|
delete item;
|
|
}
|
|
else
|
|
{
|
|
// Attaching Certificate.
|
|
item->pgpCert = loadOrSave->m_certGpg;
|
|
|
|
#ifdef P3DISC_DEBUG
|
|
std::cerr << "p3discovery2::setGPGOperation() Sending Message:" << std::endl;
|
|
item->print(std::cerr, 5);
|
|
#endif
|
|
|
|
// Send off message
|
|
sendItem(item);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* ignore other operations */
|
|
}
|
|
|
|
RsGossipDiscoveryFriendInviteReceivedEvent::
|
|
RsGossipDiscoveryFriendInviteReceivedEvent(const std::string& invite) :
|
|
RsEvent(RsEventType::GOSSIP_DISCOVERY_INVITE_RECEIVED),
|
|
mInvite(invite) {}
|