diff --git a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc b/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc index e50073945..0c2a8fb0d 100644 --- a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc +++ b/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc @@ -27,6 +27,7 @@ #include "retroshare/rsiface.h" #include "rsserver/p3face.h" #include "util/rsdebug.h" +#include "retroshare/rspeers.h" /**** * #define P3DISC_DEBUG 1 @@ -1249,9 +1250,25 @@ void p3discovery2::recvInvite( void p3discovery2::rsEventsHandler(const RsEvent& event) { + Dbg3() << __PRETTY_FUNCTION__ << " " << static_cast(event.mType) + << std::endl; + switch(event.mType) { - // TODO: When an SSL-only friend become online requestInvite(...) + case RsEventType::PEER_STATE_CHANGED: + { + const RsPeerId& sslId = + static_cast(event).mSslId; + if( rsPeers && rsPeers->isSslOnlyFriend(sslId) && + mServiceCtrl->isPeerConnected( + getServiceInfo().mServiceType, sslId ) ) + { + if(!requestInvite(sslId, sslId)) + RsErr() << __PRETTY_FUNCTION__ << " requestInvite to peer " + << sslId << " failed" << std::endl; + } + break; + } default: break; } } diff --git a/libretroshare/src/pqi/authssl.cc b/libretroshare/src/pqi/authssl.cc index 5d56b3843..1a9648300 100644 --- a/libretroshare/src/pqi/authssl.cc +++ b/libretroshare/src/pqi/authssl.cc @@ -1196,6 +1196,7 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) std::string sslCn = RsX509Cert::getCertIssuerString(*x509Cert); RsPgpId pgpId(sslCn); + if(sslId.isNull()) { std::string errMsg = "x509Cert has invalid sslId!"; @@ -1231,8 +1232,10 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) return verificationFailed; } + bool isSslOnlyFriend = rsPeers->isSslOnlyFriend(sslId); + uint32_t auth_diagnostic; - if(!AuthX509WithGPG(x509Cert, auth_diagnostic)) + if(!isSslOnlyFriend && !AuthX509WithGPG(x509Cert, auth_diagnostic)) { std::string errMsg = "Certificate was rejected because PGP " "signature verification failed with diagnostic: " @@ -1255,7 +1258,7 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) return verificationFailed; } - if ( pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() && + if ( !isSslOnlyFriend && pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() && !AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) ) { std::string errMsg = "Connection attempt signed by PGP key id: " + @@ -1279,7 +1282,9 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) setCurrentConnectionAttemptInfo(pgpId, sslId, sslCn); LocalStoreCert(x509Cert); - Dbg1() << __PRETTY_FUNCTION__ << " authentication successfull!" << std::endl; + RsInfo() << __PRETTY_FUNCTION__ << " authentication successfull for " + << "sslId: " << sslId << " isSslOnlyFriend: " << isSslOnlyFriend + << std::endl; if(rsEvents) { diff --git a/libretroshare/src/pqi/p3peermgr.cc b/libretroshare/src/pqi/p3peermgr.cc index f3d8b08f2..a4960f7c4 100644 --- a/libretroshare/src/pqi/p3peermgr.cc +++ b/libretroshare/src/pqi/p3peermgr.cc @@ -1029,6 +1029,73 @@ bool p3PeerMgrIMPL::addFriend(const RsPeerId& input_id, const RsPgpId& input_gpg return true; } + +bool p3PeerMgrIMPL::addSslOnlyFriend( + const RsPeerId& sslId, const RsPeerDetails& dt ) +{ + if(sslId.isNull() || sslId == getOwnId()) return false; + + peerState pstate; + + { RS_STACK_MUTEX(mPeerMtx); + + /* If in mOthersList -> move over */ + auto it = mOthersList.find(sslId); + if (it != mOthersList.end()) + { + pstate = it->second; + mOthersList.erase(it); + } + + } // RS_STACK_MUTEX(mPeerMtx); + + pstate.id = sslId; + + if(!dt.name.empty()) pstate.name = dt.name; + if(!dt.dyndns.empty()) pstate.dyndns = dt.dyndns; + pstate.hiddenNode = dt.isHiddenNode; + if(!dt.hiddenNodeAddress.empty()) + pstate.hiddenDomain = dt.hiddenNodeAddress; + if(dt.hiddenNodePort) pstate.hiddenPort = dt.hiddenNodePort; + if(dt.hiddenType) pstate.hiddenType = dt.hiddenType; + if(!dt.location.empty()) pstate.location = dt.location; + + { RS_STACK_MUTEX(mPeerMtx); + + mFriendList[sslId] = pstate; + mStatusChanged = true; + + } // RS_STACK_MUTEX(mPeerMtx); + + IndicateConfigChanged(); + mLinkMgr->addFriend(sslId, dt.vs_dht != RS_VS_DHT_OFF); + + // To update IP addresses is much more confortable to use locators + if(!dt.isHiddenNode) + { + for(const std::string& locator : dt.ipAddressList) + addPeerLocator(sslId, locator); + + if(dt.extPort && !dt.extAddr.empty()) + { + RsUrl locator; + locator.setScheme("ipv4").setHost(dt.extAddr) + .setPort(dt.extPort); + addPeerLocator(sslId, locator); + } + + if(dt.localPort && !dt.localAddr.empty()) + { + RsUrl locator; + locator.setScheme("ipv4").setHost(dt.localAddr) + .setPort(dt.localPort); + addPeerLocator(sslId, locator); + } + } + + return true; +} + bool p3PeerMgrIMPL::removeFriend(const RsPgpId &id) { #ifdef PEER_DEBUG @@ -2344,7 +2411,15 @@ bool p3PeerMgrIMPL::loadList(std::list& load) #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); + if(!addFriend( peer_id, peer_pgp_id, pitem->netMode, + pitem->vs_disc, pitem->vs_dht, + pitem->lastContact, RS_NODE_PERM_ALL )) + { + RsInfo() << __PRETTY_FUNCTION__ << " loading SSL-only " + << "friend: " << peer_id << " " << pitem->location + << std::endl; + addSslOnlyFriend(peer_id); + } setLocation(pitem->nodePeerId, pitem->location); } diff --git a/libretroshare/src/pqi/p3peermgr.h b/libretroshare/src/pqi/p3peermgr.h index 781dd6115..260864cd6 100644 --- a/libretroshare/src/pqi/p3peermgr.h +++ b/libretroshare/src/pqi/p3peermgr.h @@ -127,6 +127,10 @@ public: rstime_t lastContact = 0, ServicePermissionFlags = ServicePermissionFlags(RS_NODE_PERM_DEFAULT) ) = 0; + virtual bool addSslOnlyFriend( + const RsPeerId& sslId, + const RsPeerDetails& details = RsPeerDetails() ) = 0; + virtual bool removeFriend(const RsPeerId &ssl_id, bool removePgpId) = 0; virtual bool isFriend(const RsPeerId& ssl_id) = 0; @@ -242,6 +246,11 @@ public: virtual bool addFriend(const RsPeerId&ssl_id, const RsPgpId&gpg_id, uint32_t netMode = RS_NET_MODE_UDP, uint16_t vsDisc = RS_VS_DISC_FULL, uint16_t vsDht = RS_VS_DHT_FULL, rstime_t lastContact = 0,ServicePermissionFlags = ServicePermissionFlags(RS_NODE_PERM_DEFAULT)); + + bool addSslOnlyFriend( + const RsPeerId& sslId, + const RsPeerDetails& details = RsPeerDetails() ) override; + virtual bool removeFriend(const RsPeerId &ssl_id, bool removePgpId); virtual bool removeFriend(const RsPgpId &pgp_id); diff --git a/libretroshare/src/pqi/p3servicecontrol.cc b/libretroshare/src/pqi/p3servicecontrol.cc index 23dcaf747..d361f25bd 100644 --- a/libretroshare/src/pqi/p3servicecontrol.cc +++ b/libretroshare/src/pqi/p3servicecontrol.cc @@ -28,6 +28,8 @@ #include "rsitems/rsnxsitems.h" #include "pqi/p3cfgmgr.h" #include "pqi/pqiservice.h" +#include "retroshare/rspeers.h" +#include "retroshare/rsevents.h" /*******************************/ // #define SERVICECONTROL_DEBUG 1 @@ -756,6 +758,12 @@ bool p3ServiceControl::updateFilterByPeer_locked(const RsPeerId &peerId) mPeerFilterMap[peerId] = peerFilter; } recordFilterChanges_locked(peerId, originalFilter, peerFilter); + + using Evt_t = RsPeerStateChangedEvent; + std::shared_ptr lockedRsEvents = rsEvents; + if(lockedRsEvents) + lockedRsEvents->postEvent(std::unique_ptr(new Evt_t(peerId))); + return true; } diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc index 16fd78cc9..8a3d49901 100644 --- a/libretroshare/src/pqi/pqissl.cc +++ b/libretroshare/src/pqi/pqissl.cc @@ -35,7 +35,7 @@ #include "pqi/pqissllistener.h" #include "pqi/p3linkmgr.h" -#include +#include "retroshare/rspeers.h" #include #include @@ -1180,10 +1180,13 @@ int pqissl::Authorise_SSL_Connection() /* At this point the actual connection authentication has already been * performed in AuthSSL::VerifyX509Callback, any furter authentication check - * like the following two are redundant. */ + * like the followings are redundant. */ + + bool isSslOnlyFriend = rsPeers->isSslOnlyFriend(certPeerId); uint32_t authErrCode = 0; - if(!AuthSSL::instance().AuthX509WithGPG(peercert, authErrCode)) + if( !isSslOnlyFriend && + !AuthSSL::instance().AuthX509WithGPG(peercert, authErrCode) ) { RsFatal() << __PRETTY_FUNCTION__ << " failure verifying peer " << "certificate signature. This should never happen at this " @@ -1195,7 +1198,7 @@ int pqissl::Authorise_SSL_Connection() } RsPgpId pgpId = RsX509Cert::getCertIssuer(*peercert); - if( pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() && + if( !isSslOnlyFriend && pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() && !AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) ) { RsFatal() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId diff --git a/libretroshare/src/pqi/pqissllistener.cc b/libretroshare/src/pqi/pqissllistener.cc index d1a9e31a9..e295a7784 100644 --- a/libretroshare/src/pqi/pqissllistener.cc +++ b/libretroshare/src/pqi/pqissllistener.cc @@ -784,10 +784,13 @@ int pqissllistener::completeConnection(int fd, IncomingSSLInfo& info) #ifdef RS_PQISSL_AUTH_DOUBLE_CHECK /* At this point the actual connection authentication has already been * performed in AuthSSL::VerifyX509Callback, any furter authentication check - * like the following two are redundant. */ + * like the followings are redundant. */ + + bool isSslOnlyFriend = rsPeers->isSslOnlyFriend(newPeerId); uint32_t authErrCode = 0; - if(!AuthSSL::instance().AuthX509WithGPG(peercert, authErrCode)) + if( !isSslOnlyFriend && + !AuthSSL::instance().AuthX509WithGPG(peercert, authErrCode) ) { RsFatal() << __PRETTY_FUNCTION__ << " failure verifying peer " << "certificate signature. This should never happen at this " @@ -798,7 +801,7 @@ int pqissllistener::completeConnection(int fd, IncomingSSLInfo& info) exit(failure); } - if( pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() && + if( !isSslOnlyFriend && pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() && !AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) ) { RsFatal() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId @@ -822,7 +825,7 @@ int pqissllistener::completeConnection(int fd, IncomingSSLInfo& info) else ++it; } - if (found == false) + if (!found) { Dbg1() << __PRETTY_FUNCTION__ << " got secure connection from address: " << info.addr << " with previously unknown SSL certificate: " diff --git a/libretroshare/src/retroshare/rsevents.h b/libretroshare/src/retroshare/rsevents.h index 94ae866f8..869e5d2d6 100644 --- a/libretroshare/src/retroshare/rsevents.h +++ b/libretroshare/src/retroshare/rsevents.h @@ -63,6 +63,9 @@ enum class RsEventType : uint32_t /// @see RsGxsChanges GXS_CHANGES = 5, + /// Emitted when a peer state changes, @see RsPeers + PEER_STATE_CHANGED = 6, + MAX /// Used to detect invalid event type passed }; diff --git a/libretroshare/src/retroshare/rspeers.h b/libretroshare/src/retroshare/rspeers.h index ab5404859..7f1551f69 100644 --- a/libretroshare/src/retroshare/rspeers.h +++ b/libretroshare/src/retroshare/rspeers.h @@ -31,6 +31,7 @@ #include "util/rsurl.h" #include "util/rsdeprecate.h" #include "util/rstime.h" +#include "retroshare/rsevents.h" class RsPeers; @@ -358,6 +359,23 @@ struct RsGroupInfo : RsSerializable } }; +/** Event emitted when a peer change state */ +struct RsPeerStateChangedEvent : RsEvent +{ + /// @param[in] sslId is of the peer which changed state + RsPeerStateChangedEvent(RsPeerId sslId); + + /// Storage fot the id of the peer that changed state + RsPeerId mSslId; + + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) override + { + RsEvent::serial_process(j, ctx); + RS_SERIAL_PROCESS(mSslId); + } +}; + /** The Main Interface Class - for information about your Peers * A peer is another RS instance, means associated with an SSL certificate * A same GPG person can have multiple peer running with different SSL certs @@ -434,6 +452,16 @@ public: */ virtual bool isPgpFriend(const RsPgpId& pgpId) = 0; + /** + * @brief Check if given peer is a trusted SSL node pending PGP approval + * Peers added through short invite remain in this state as long as their + * PGP key is not received and verified/approved by the user. + * @jsonapi{development} + * @param[in] sslId id of the peer to check + * @return true if the node is trusted, false otherwise + */ + virtual bool isSslOnlyFriend(const RsPeerId& sslId) = 0; + virtual std::string getPeerName(const RsPeerId &ssl_id) = 0; virtual std::string getGPGName(const RsPgpId& gpg_id) = 0; @@ -474,8 +502,24 @@ public: * @param[in] flags service permissions flag * @return false if error occurred, true otherwise */ - virtual bool addFriend( const RsPeerId &sslId, const RsPgpId& gpgId, - ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT ) = 0; + virtual bool addFriend( + const RsPeerId& sslId, const RsPgpId& gpgId, + ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT ) = 0; + + /** + * @brief Add SSL-only trusted node + * When adding an SSL-only node, it is authorized to connect. Every time a + * connection is established the user is notified about the need to verify + * the PGP fingerprint, until she does, at that point the node become a full + * SSL+PGP friend. + * @jsonapi{development} + * @param[in] sslId SSL id of the node to add + * @param[in] details Optional extra details known about the node to add + * @return false if error occurred, true otherwise + */ + virtual bool addSslOnlyFriend( + const RsPeerId& sslId, + const RsPeerDetails& details = RsPeerDetails() ) = 0; /** * @brief Revoke connection trust from to node @@ -597,6 +641,38 @@ public: bool includeSignatures = false, bool includeExtraLocators = true ) = 0; + /** + * @brief Get RetroShare short invite of the given peer + * @jsonapi{development} + * @param[out] invite storage for the generated invite + * @param[in] sslId Id of the peer of which we want to generate an invite, + * a null id (all 0) is passed, an invite for own node is returned. + * @param[in] formatRadix true to get in base64 format false to get URL. + * @param[in] bareBones true to get smallest invite, which miss also + * the information necessary to attempt an outgoing connection, but still + * enough to accept an incoming one. + * @param[in] baseUrl URL into which to sneak in the RetroShare invite + * radix, this is primarly useful to trick other applications into making + * the invite clickable, or to disguise the RetroShare invite into a + * "normal" looking web link. Used only if formatRadix is false. + * @return false if error occurred, true otherwise + */ + virtual bool getShortInvite( + std::string& invite, const RsPeerId& sslId = RsPeerId(), + bool formatRadix = false, bool bareBones = false, + const std::string& baseUrl = "https://retroshare.me/" ) = 0; + + /** + * @brief Parse the give short invite to extract contained information + * @jsonapi{development} + * @param[in] invite string containing the short invite to parse + * @param[out] details storage for the extracted information, consider it + * valid only if the function return true + * @return false if error occurred, true otherwise + */ + virtual bool parseShortInvite( + const std::string& invite, RsPeerDetails& details ) = 0; + /** * @brief Add trusted node from invite * @jsonapi{development} @@ -749,6 +825,3 @@ public: RS_DEPRECATED_FOR(isPgpFriend) virtual bool isGPGAccepted(const RsPgpId &gpg_id_is_friend) = 0; }; - - - diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc index ddab5fabf..64e94d973 100644 --- a/libretroshare/src/rsserver/p3peers.cc +++ b/libretroshare/src/rsserver/p3peers.cc @@ -570,6 +570,9 @@ std::string p3Peers::getGPGName(const RsPgpId &gpg_id) bool p3Peers::isPgpFriend(const RsPgpId& pgpId) { return AuthGPG::getAuthGPG()->isGPGAccepted(pgpId); } +bool p3Peers::isSslOnlyFriend(const RsPeerId& sslId) +{ return isFriend(sslId) && !isPgpFriend(getGPGId(sslId)); } + bool p3Peers::isGPGAccepted(const RsPgpId &gpg_id_is_friend) { return isPgpFriend(gpg_id_is_friend); } @@ -749,6 +752,10 @@ bool p3Peers::addFriend(const RsPeerId &ssl_id, const RsPgpId &gpg_id,ServicePe return mPeerMgr->addFriend(ssl_id, gpg_id, RS_NET_MODE_UDP, RS_VS_DISC_FULL, RS_VS_DHT_FULL, now, perm_flags); } +bool p3Peers::addSslOnlyFriend( + const RsPeerId& sslId, const RsPeerDetails& details ) +{ return mPeerMgr->addSslOnlyFriend(sslId, details); } + bool p3Peers::removeKeysFromPGPKeyring(const std::set& pgp_ids,std::string& backup_file,uint32_t& error_code) { return AuthGPG::getAuthGPG()->removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ; @@ -1104,6 +1111,221 @@ bool p3Peers::GetPGPBase64StringAndCheckSum( const RsPgpId& gpg_id, return true ; } +enum class RsShortInviteFieldType : uint8_t +{ + SSL_ID = 0x00, + PEER_NAME = 0x01, + LOCATOR = 0x02, + + /* The following will be deprecated, and ported to LOCATOR when generic + * trasport layer will be implemented */ + HIDDEN_LOCATOR = 0x90, + DNS_LOCATOR = 0x91, + EXT4_LOCATOR = 0x92, +}; + +bool p3Peers::getShortInvite( + std::string& invite, const RsPeerId& _sslId, bool formatRadix, + bool bareBones, const std::string& baseUrl ) +{ + RsPeerId sslId = _sslId; + if(sslId.isNull()) sslId = getOwnId(); + + RsPeerDetails tDetails; + if(!getPeerDetails(sslId, tDetails)) return false; + + std::vector inviteBuf(1000, 0); + RsGenericSerializer::SerializeContext ctx( + inviteBuf.data(), static_cast(inviteBuf.size())); + RsGenericSerializer::SerializeJob j = RsGenericSerializer::SERIALIZE; + + RsShortInviteFieldType tType = RsShortInviteFieldType::SSL_ID; + RS_SERIAL_PROCESS(tType); + RS_SERIAL_PROCESS(sslId); + + tType = RsShortInviteFieldType::PEER_NAME; + RS_SERIAL_PROCESS(tType); + RS_SERIAL_PROCESS(tDetails.name); + + if(!bareBones) + { + /* If is hidden use hidden address and port as locator, else if we have + * a valid dyndns and extPort use that as locator, else if we have a + * valid extAddr and extPort use that as locator, otherwise use most + * recently known locator */ + sockaddr_storage tExt; + if(tDetails.isHiddenNode) + { + tType = RsShortInviteFieldType::HIDDEN_LOCATOR; + RS_SERIAL_PROCESS(tType); + RS_SERIAL_PROCESS(tDetails.hiddenType); + RS_SERIAL_PROCESS(tDetails.hiddenNodeAddress); + RS_SERIAL_PROCESS(tDetails.hiddenNodePort); + } + else if( !tDetails.dyndns.empty() && + (tDetails.extPort || tDetails.localPort) ) + { + uint16_t tPort = tDetails.extPort ? + tDetails.extPort : tDetails.localPort; + tType = RsShortInviteFieldType::DNS_LOCATOR; + RS_SERIAL_PROCESS(tType); + RS_SERIAL_PROCESS(tDetails.dyndns); + RS_SERIAL_PROCESS(tPort); + } + else if( sockaddr_storage_inet_pton(tExt, tDetails.extAddr) && + sockaddr_storage_isValidNet(tExt) && + sockaddr_storage_ipv6_to_ipv4(tExt) && + tDetails.extPort ) + { + uint32_t t4Addr = + reinterpret_cast(tExt).sin_addr.s_addr; + + tType = RsShortInviteFieldType::EXT4_LOCATOR; + RS_SERIAL_PROCESS(tType); + RS_SERIAL_PROCESS(t4Addr); + RS_SERIAL_PROCESS(tDetails.extPort); + } + else if(!tDetails.ipAddressList.empty()) + { + const std::string& tLc = tDetails.ipAddressList.front(); + std::string tLocator = tLc.substr(0, tLc.find_first_of(" ")-1); + tType = RsShortInviteFieldType::LOCATOR; + RS_SERIAL_PROCESS(tType); + RS_SERIAL_PROCESS(tLocator); + } + } + + Radix64::encode(ctx.mData, static_cast(ctx.mOffset), invite); + + if(!formatRadix) + { + RsUrl inviteUrl(baseUrl); + inviteUrl.setQueryKV("rsInvite", invite); + invite = inviteUrl.toString(); + } + + return ctx.mOk; +} + +bool p3Peers::parseShortInvite( + const std::string& inviteStrUrl, RsPeerDetails& details ) +{ + if(inviteStrUrl.empty()) + { + RsErr() << __PRETTY_FUNCTION__ << " can't parse empty invite" + << std::endl; + return false; + } + + const std::string* rsInvite = &inviteStrUrl; + + RsUrl inviteUrl(inviteStrUrl); + if(inviteUrl.hasQueryK("rsInvite")) + rsInvite = inviteUrl.getQueryV("rsInvite"); + + std::vector inviteBuf = Radix64::decode(*rsInvite); + RsGenericSerializer::SerializeContext ctx( + inviteBuf.data(), static_cast(inviteBuf.size())); + RsGenericSerializer::SerializeJob j = RsGenericSerializer::DESERIALIZE; + + while(ctx.mOk && ctx.mOffset < ctx.mSize) + { + RsShortInviteFieldType fieldType; + RS_SERIAL_PROCESS(fieldType); + + if(!ctx.mOk) + { + RsWarn() << __PRETTY_FUNCTION__ << " failed to parse fieldType" + << std::endl; + break; + } + + switch (fieldType) + { + case RsShortInviteFieldType::SSL_ID: + RS_SERIAL_PROCESS(details.id); + break; + case RsShortInviteFieldType::PEER_NAME: + RS_SERIAL_PROCESS(details.name); + break; + case RsShortInviteFieldType::LOCATOR: + { + std::string locatorStr; + RS_SERIAL_PROCESS(locatorStr); + if(ctx.mOk) details.ipAddressList.push_back(locatorStr); + else RsWarn() << __PRETTY_FUNCTION__ << " failed to parse locator" + << std::endl; + break; + } + case RsShortInviteFieldType::DNS_LOCATOR: + RS_SERIAL_PROCESS(details.dyndns); + if(!ctx.mOk) + { + RsWarn() << __PRETTY_FUNCTION__ << " failed to parse DNS " + << "locator host" << std::endl; + break; + } + + RS_SERIAL_PROCESS(details.extPort); + if(!ctx.mOk) RsWarn() << __PRETTY_FUNCTION__ << " failed to parse " + << "DNS locator port" << std::endl; + + break; + + case RsShortInviteFieldType::EXT4_LOCATOR: + { + sockaddr_in tExtAddr; + RS_SERIAL_PROCESS(tExtAddr.sin_addr.s_addr); + if(!ctx.mOk) + { + RsWarn() << __PRETTY_FUNCTION__ << " failed to parse IPv4" + << std::endl; + break; + } + details.extAddr = rs_inet_ntoa(tExtAddr.sin_addr); + + RS_SERIAL_PROCESS(details.extPort); + if(!ctx.mOk) + RsWarn() << __PRETTY_FUNCTION__ << " failed to parse extPort" + << std::endl; + + break; + } + + case RsShortInviteFieldType::HIDDEN_LOCATOR: + RS_SERIAL_PROCESS(details.hiddenType); + if(!ctx.mOk) + { + RsWarn() << __PRETTY_FUNCTION__ << " failed to parse hiddenType" + << std::endl; + break; + } + + RS_SERIAL_PROCESS(details.hiddenNodeAddress); + if(!ctx.mOk) + { + RsWarn() << __PRETTY_FUNCTION__ << " failed to parse " + << "hiddenNodeAddress" << std::endl; + break; + } + + RS_SERIAL_PROCESS(details.hiddenNodePort); + if(!ctx.mOk) RsWarn() << __PRETTY_FUNCTION__ << " failed to parse " + << "hiddenNodePort" << std::endl; + + break; + + default: + RsWarn() << __PRETTY_FUNCTION__ << " got unkown field type: " + << static_cast(fieldType) << std::endl; + break; + } + } + + + return ctx.mOk; +} + bool p3Peers::acceptInvite( const std::string& invite, ServicePermissionFlags flags ) { @@ -1503,4 +1725,5 @@ void p3Peers::setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermi mPeerMgr->setServicePermissionFlags(gpg_id,flags) ; } - +RsPeerStateChangedEvent::RsPeerStateChangedEvent(RsPeerId sslId) : + RsEvent(RsEventType::PEER_STATE_CHANGED), mSslId(sslId) {} diff --git a/libretroshare/src/rsserver/p3peers.h b/libretroshare/src/rsserver/p3peers.h index a44fb4142..c6bc82704 100644 --- a/libretroshare/src/rsserver/p3peers.h +++ b/libretroshare/src/rsserver/p3peers.h @@ -69,6 +69,9 @@ public: virtual bool isFriend(const RsPeerId &id); virtual bool isPgpFriend(const RsPgpId& pgpId); + /// @see RsPeers + bool isSslOnlyFriend(const RsPeerId& sslId) override; + RS_DEPRECATED_FOR(isPgpFriend) virtual bool isGPGAccepted(const RsPgpId &gpg_id_is_friend); @@ -90,6 +93,12 @@ public: /* Add/Remove Friends */ virtual bool addFriend(const RsPeerId &ssl_id, const RsPgpId &gpg_id,ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT); + + /// @see RsPeers + bool addSslOnlyFriend( + const RsPeerId& sslId, + const RsPeerDetails& details = RsPeerDetails() ) override; + virtual bool removeFriend(const RsPgpId& gpgid); virtual bool removeFriendLocation(const RsPeerId& sslId); @@ -128,6 +137,16 @@ public: virtual bool GetPGPBase64StringAndCheckSum(const RsPgpId& gpg_id,std::string& gpg_base64_string,std::string& gpg_base64_checksum); + /// @see RsPeers + bool getShortInvite( + std::string& invite, const RsPeerId& sslId = RsPeerId(), + bool formatRadix = false, bool bareBones = false, + const std::string& baseUrl = "https://retroshare.me/" ) override; + + /// @see RsPeers + bool parseShortInvite( + const std::string& invite, RsPeerDetails& details ) override; + /// @see RsPeers::acceptInvite virtual bool acceptInvite( const std::string& invite,