From 0e933a55d1ef24433048e61f770438e24df7e8e6 Mon Sep 17 00:00:00 2001 From: "vinh@unseen.is" Date: Fri, 13 Mar 2020 11:53:59 -0700 Subject: [PATCH] adding the ability to request/accept friend through DistantChatService. --- libretroshare/src/chat/distantchat.cc | 4 +- libretroshare/src/chat/rschatitems.h | 8 +- libretroshare/src/retroshare/rsidentity.h | 21 +- libretroshare/src/services/p3idservice.cc | 280 +++++++++++++++++- libretroshare/src/services/p3idservice.h | 36 ++- retroshare-gui/src/gui/Identity/IdDialog.cpp | 56 ++-- .../common/UnseenFriendSelectionWidget.cpp | 2 +- .../src/gui/gxs/UnseenGxsGroupFrameDialog.cpp | 4 +- .../gui/gxschats/UnseenGxsChatLobbyDialog.cpp | 6 +- 9 files changed, 378 insertions(+), 39 deletions(-) diff --git a/libretroshare/src/chat/distantchat.cc b/libretroshare/src/chat/distantchat.cc index 60b11b0b31..67685d5e96 100644 --- a/libretroshare/src/chat/distantchat.cc +++ b/libretroshare/src/chat/distantchat.cc @@ -44,7 +44,7 @@ #include "retroshare/rsids.h" #include "distantchat.h" -//#define DEBUG_DISTANT_CHAT +#define DEBUG_DISTANT_CHAT #ifdef DEBUG_DISTANT_CHAT @@ -143,7 +143,7 @@ bool DistantChatService::acceptDataFromPeer(const RsGxsId& gxs_id,const RsGxsTun return true ; if(mDistantChatPermissions & RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS) - res = (rsIdentity!=NULL) && rsIdentity->isARegularContact(gxs_id) ; + res = (rsIdentity!=NULL) && (rsIdentity->isARegularContact(gxs_id) || rsIdentity->acceptFriendContact(gxs_id)); if(mDistantChatPermissions & RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY) res = false ; diff --git a/libretroshare/src/chat/rschatitems.h b/libretroshare/src/chat/rschatitems.h index d143150d0e..2bba07cd14 100644 --- a/libretroshare/src/chat/rschatitems.h +++ b/libretroshare/src/chat/rschatitems.h @@ -82,9 +82,15 @@ const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INFO = 0x1D ; //meiyousixin const uint8_t RS_PKT_SUBTYPE_GXSCHAT_ACCEPT = 0x30 ; //unseenp2pdev - for lobby Inviation/Accept const uint8_t RS_PKT_SUBTYPE_GXSCHAT_INVITE = 0x31 ; //unseenp2pdev - for lobby Inviation/Accept const uint8_t RS_PKT_SUBTYPE_GXSCHAT_MSG = 0x32 ; //unseenp2pdev - gxschat message -const uint8_t RS_PKT_SUBTYPE_GXSCHAT_PUBLISH_KEY = 0x33 ; //unseenp2pdev - gxschat shared publish key +const uint8_t RS_PKT_SUBTYPE_GXSCHAT_PUBLISH_KEY = 0x33 ; //unseenp2pdev - gxschat shared publish key const uint8_t RS_PKT_SUBTYPE_GXSCHAT_GROUP = 0x34 ; //unseenp2pdev - gxschat shared publish key +const uint8_t RS_PKT_SUBTYPE_GXSCHAT_REQUEST = 0x35 ; //unseenp2pdev - for lobby Inviation/Accept +const uint8_t RS_PKT_SUBTYPE_GXSCHAT_APPROVED = 0x36 ; //unseenp2pdev - for lobby Inviation/Accept +const uint8_t RS_PKT_SUBTYPE_GXSCHAT_REJECT = 0x37 ; //unseenp2pdev - for lobby Inviation/Accept +const uint8_t RS_PKT_SUBTYPE_GXSCHAT_ACTKN = 0x38 ; //unseenp2pdev - for lobby Inviation/Accept + + RS_DEPRECATED_FOR(RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE) \ const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPRECATED = 0x1A ; // to be removed (deprecated since May 2017) diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index 2fd95e66b2..8730864136 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -31,6 +31,7 @@ #include "retroshare/rsgxsifacehelper.h" #include "retroshare/rsreputations.h" #include "retroshare/rsids.h" +//#include #include "serialiser/rstlvimage.h" #include "retroshare/rsgxscommon.h" #include "serialiser/rsserializable.h" @@ -163,7 +164,16 @@ std::ostream &operator<<(std::ostream &out, const RsGxsIdGroup &group); class RsGxsMyContact: RsSerializable { public: - enum STATUS {UNKNOWN,PENDING,REQUEST,APPROVED, TRUSTED, BANNED}; + enum STATUS {UNKNOWN,PENDING,PENDING_REQ, PENDING_ACCEPT, REQUEST,ACCEPT, APPROVE, TRUSTED, BANNED, ACK}; + /* PENDING=NOT READY, PENDING_REQ=ALREADY SENT REQUEST, PENDING_ACCEPT=ALREADY RECEIVE REQ + * ACCEPT= APPROVE already add Friend. + * BANNED = REJECT TO BE FRIEND + * TRUST = CONNECTION ESTABLISHED + * Example: A add B: A Add Contact step: Pending, Send Request/ack: PENDING_REQ, + * B: PENDING_ACCEPT, B's Approved/Accept, Sending Approved to A. + * A: Validate B's Cert and Accept. A send ACK to B. + * A connects to B: Online, A->Trust, B->Trust. + **/ RsGxsId gxsId; RsPgpId mPgpId; RsPeerId peerId; @@ -446,6 +456,15 @@ struct RsIdentity : RsGxsIfaceHelper virtual bool removeMyContact(const RsGxsMyContact& contact) =0; virtual void getMyContacts(std::set& contactList) =0; + virtual bool acceptFriendContact(const RsGxsId &id) =0; + virtual bool addFriendContact(RsGxsMyContact &contact)=0; + virtual bool addFriendContact(RsGxsId &id)=0; + virtual bool approveFriendContact(RsGxsId &id, bool denied=false)=0; + virtual bool approveFriendContact(RsGxsMyContact &contact, bool denied=false)=0; + virtual void processContactPendingRequest()=0; + virtual void processContactPendingApproval()=0; + + virtual bool serialiseIdentityToMemory( const RsGxsId& id, std::string& radix_string ) = 0; virtual bool deserialiseIdentityFromMemory( const std::string& radix_string, diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 867a362266..7a2b0f98af 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -46,11 +46,13 @@ /**** * #define DEBUG_IDS 1 + * #define DEBUG_DISTANT_CHAT 1 * #define DEBUG_RECOGN 1 * #define DEBUG_OPINION 1 * #define GXSID_GEN_DUMMY_DATA 1 ****/ #define DEBUG_IDS 1 +#define DEBUG_DISTANT_CHAT 1 #define ID_REQUEST_LIST 0x0001 #define ID_REQUEST_IDENTITY 0x0002 @@ -160,7 +162,7 @@ p3IdService::p3IdService( RS_SERVICE_GXS_TYPE_GXSID, idAuthenPolicy() ), RsIdentity(static_cast(*this)), GxsTokenQueue(this), RsTickEvent(), mKeyCache(GXSID_MAX_CACHE_SIZE, "GxsIdKeyCache"), - mIdMtx("p3IdService"), mNes(nes), mPgpUtils(pgpUtils) + mIdMtx("p3IdService"), mNes(nes), mPgpUtils(pgpUtils), mRsGxsMyChatMtx("P3IdService-DistantChat - mutex") { mBgSchedule_Mode = 0; mBgSchedule_Active = false; @@ -246,13 +248,18 @@ bool p3IdService::setAsRegularContact(const RsGxsId& id,bool b) RsGxsMyContact newContact(id); RsIdentityDetails details; if(getIdDetails(id, details)){ - newContact.status = RsGxsMyContact::PENDING; //waiting for approval. + newContact.status = RsGxsMyContact::REQUEST; //waiting for approval. newContact.mPgpId = details.mPgpId; newContact.name = details.mNickname; newContact.mContactInfo = details.mProfileInfo; //if u want to take the friend profile store local. } mContacts.insert(newContact) ; + slowIndicateConfigChanged() ; + + //adding to request friend queue + contactRequestPending.insert(newContact); + } if( (!b) &&(it != mContacts.end())) @@ -588,6 +595,8 @@ void p3IdService::service_tick() cleanUnusedKeys() ; mLastKeyCleaningTime = now ; } + //contact sending process. + processContactPendingRequest(); return; } @@ -4647,3 +4656,270 @@ RsIdentityUsage::RsIdentityUsage( RsIdentityUsage::RsIdentityUsage() : mServiceId(0), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0) {} + +/******* Distant Chat Support for Invite/Request/Approve Friends ****************** + ** Overload DistantChatService ** +*/ +void p3IdService::handleIncomingItem(RsItem *item){ + +#ifdef DEBUG_DISTANT_CHAT + std::cerr << "p3IdService::handleIncomingItem() Item:" << (void*)item + << std::endl ; +#endif + RsStackMutex stack(mRsGxsMyChatMtx); + + // RsChatMsgItems needs dynamic_cast, since they have derived siblings. + RsChatMsgItem* ci = dynamic_cast(item); + DistantChatPeerInfo cinfo; + DistantChatPeerId distPeerId(ci->PeerId()); + + if(ci) + { + if(!DistantChatService::getDistantChatStatus(distPeerId,cinfo)) + return; + + } + + + + //state machine of Request/Invite Friend + //state machine {Request, Pending, Approved, Reject, Acknowledge} + switch(item->PacketSubType()) + { + case RS_PKT_SUBTYPE_GXSCHAT_REQUEST:{ + //lock the cache to insert new record. + std::cerr <<"Received: REQUEST from="<message += " to be established]"; + item->chatFlags = RS_CHAT_FLAG_PRIVATE; + item->sendTime = time(NULL); + //item->PeerId(RsPeerId(tunnel_id)); + item->PeerId(RsPeerId(distPeerId)); + //handleRecvChatMsgItem(item); + DistantChatService::handleOutgoingItem(item); + delete item ; + + return true; +} +bool p3IdService::addFriendContact(RsGxsId &id){ + RsGxsMyContact contact(id); + return this->addFriendContact(contact); +} +bool p3IdService::approveFriendContact(RsGxsId &id, bool is_denied){ + return true; +} +bool p3IdService::approveFriendContact(RsGxsMyContact &approvedContact, bool denied){ + return true; +} +void p3IdService::processContactPendingRequest(){ + + //RsStackMutex stack(mRsGxsMyChatMtx); + if(contactRequestPending.empty()) + return; + +#ifdef DEBUG_DISTANT_CHAT + std::cerr << "p3IdService::processContactPendingRequest(): Sending Requestor GxsId" <GetRetroshareInvite(); + std::list myGxsId; + getOwnIds(myGxsId); //first gxsId from the list. + + for(auto it =contactRequestPending.begin(); it !=contactRequestPending.end(); it++ ){ + RsGxsMyContact contact = *it; + DistantChatPeerId distPeerId; + + std::map::iterator myIt = distantPendingConn.find(contact); + if(myIt !=distantPendingConn.end()){ + distPeerId = myIt->second; + }else{ + uint32_t error_code; + RsGxsId from_gxsid = myGxsId.front(); + RsGxsId to_gxsid = contact.gxsId; + std::cerr <<"From_gxsId:"<PeerId(RsPeerId(distPeerId)); + }else if(contact.status==RsGxsMyContact::APPROVE){ + std::cerr <<"Sending Approve: from="<PeerId(RsPeerId(distPeerId)); + } + + if(item !=NULL) + DistantChatService::handleOutgoingItem(item); + + + } + contactRequestPending.clear(); //empty the queue +} +void p3IdService::processContactPendingApproval(){ + RsStackMutex stack(mRsGxsMyChatMtx); + if(contactApprovalPending.empty()) + return; + +#ifdef DEBUG_DISTANT_CHAT + std::cerr << "p3IdService::processContactPendingApproval() Item:" <first; + DistantChatPeerInfo distPeerInfo = it->second.first; + RsChatMsgItem *item = it->second.second; + + //validate incoming message is a ssl certificate. + std::string cert = item->message; + RsPeerId sslId; + RsPgpId pgpId; + std::string errorString; + + if( rsPeers->loadCertificateFromString(cert, sslId, pgpId, errorString)){ + //valid certificate send by requestor. + //adding to RsMyContactList and waiting for approval. + contact.status = RsGxsMyContact::PENDING; + contact.mPgpId = pgpId; + contact.peerId = sslId; + contact.mContactInfo["cert_url"]=cert; + this->setMyContact(contact); + //need to send notification to GUI to change state of contact status. + //response your own certifcate to the requestor as the acknowledgement. + contactApprovalAcknowleged[contact] = it->second; + } + + } + contactApprovalPending.clear(); + +} diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h index 88c95f7567..9268dfa970 100644 --- a/libretroshare/src/services/p3idservice.h +++ b/libretroshare/src/services/p3idservice.h @@ -41,6 +41,10 @@ #include "rsitems/rsgxsrecognitems.h" +#include "chat/distantchat.h" +#include "chat/rschatitems.h" + + class PgpAuxUtils; /* @@ -218,7 +222,7 @@ struct SerialisedIdentityStruct // Not sure exactly what should be inherited here? // Chris - please correct as necessary. -class p3IdService: public RsGxsIdExchange, public RsIdentity, public GxsTokenQueue, public RsTickEvent, public p3Config +class p3IdService: public RsGxsIdExchange, public RsIdentity, public GxsTokenQueue, public RsTickEvent, public DistantChatService, public p3Config { public: p3IdService(RsGeneralDataService* gds, RsNetworkExchangeService* nes, PgpAuxUtils *pgpUtils); @@ -282,12 +286,26 @@ class p3IdService: public RsGxsIdExchange, public RsIdentity, public GxsTokenQu virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) ; virtual bool isARegularContact(const RsGxsId& id) ; + //unseen my contacts design & architect data structure virtual bool setMyContact(const RsGxsMyContact & contact); virtual bool isMyContact(const RsGxsMyContact& contact) ; virtual bool updateMyContact(const RsGxsMyContact & contact); virtual void getMyContacts(std::set& contactList) ; virtual bool removeMyContact(const RsGxsMyContact& contact); + //unseen distant chat service for extend real-time invite/requestfriend/approved/acknowledgement. + // derived in DistantChatService, so as to pass down some info + virtual void handleIncomingItem(RsItem *); + virtual bool handleRecvChatMsgItem(RsChatMsgItem *& ci); + virtual void triggerConfigSave(); + + virtual bool acceptFriendContact(const RsGxsId &id) ; + virtual bool addFriendContact(RsGxsMyContact &contact); + virtual bool addFriendContact(RsGxsId &id); + virtual bool approveFriendContact(RsGxsId &id, bool denied=false); + virtual bool approveFriendContact(RsGxsMyContact &contact, bool denied=false); + virtual void processContactPendingRequest(); + virtual void processContactPendingApproval(); virtual uint32_t nbRegularContacts() ; virtual rstime_t getLastUsageTS(const RsGxsId &id) ; @@ -607,6 +625,22 @@ class p3IdService: public RsGxsIdExchange, public RsIdentity, public GxsTokenQu bool mOwnIdsLoaded ; uint32_t mMaxKeepKeysBanned ; + + /***************Unseen Add Friend Service********* + * DistantChatService *** + * Processing all pending request friends.** + * Processing all pending approval friends. ** + * Publishing Invite/Add friend through distant chat friend. ** + */ + typedef std::map > ContactInfo; + std::map distantPendingConn; + std::set contactRequestPending; //invite or adding contact + ContactInfo contactApprovalPending; //waiting to approve on adding contact request + ContactInfo contactApprovalAcknowleged; + + RsMutex mRsGxsMyChatMtx ; + + }; #endif // P3_IDENTITY_SERVICE_HEADER diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index 131de19c53..445aa10cd4 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -1661,12 +1661,11 @@ void IdDialog::insertIdList(uint32_t token) return; } - // turn that vector into a std::set, to avoid a linear search - - std::map ids_set ; - - for(uint32_t i=0;i ids_set ; + + for(uint32_t i=0;isetActive(IDDIALOG_IDLIST, true); @@ -1683,29 +1682,28 @@ void IdDialog::insertIdList(uint32_t token) ++itemIterator; std::map::iterator it = ids_set.find(RsGxsGroupId(item->text(RSID_COL_KEYID).toStdString())) ; - if(it == ids_set.end()) - { - if(item != allItem && item != contactsItem && item != ownItem) - delete(item); - - continue ; - } - - QTreeWidgetItem *parent_item = item->parent() ; - - if( (parent_item == allItem && it->second.mIsAContact) || (parent_item == contactsItem && !it->second.mIsAContact)) - { - delete item ; // do not remove from the list, so that it is added again in the correct place. - continue ; - } - - if (!fillIdListItem(it->second, item, ownPgpId, accept)) + if(it == ids_set.end()) + { + if(item != allItem && item != contactsItem && item != ownItem) + delete(item); + + continue ; + } + + QTreeWidgetItem *parent_item = item->parent() ; + + if( (parent_item == allItem && it->second.mIsAContact) || (parent_item == contactsItem && !it->second.mIsAContact)) + { + delete item ; // do not remove from the list, so that it is added again in the correct place. + continue ; + } + + if (!fillIdListItem(it->second, item, ownPgpId, accept)) delete(item); ids_set.erase(it); // erase, so it is not considered to be a new item } - int count =0; /* Insert new items */ for (std::map::const_iterator vit = ids_set.begin(); vit != ids_set.end(); ++vit) { @@ -1733,10 +1731,16 @@ void IdDialog::insertIdList(uint32_t token) contactsItem->addChild(item); allItem->addChild(item); - count++; - std::cerr << "Contact Info: " << item->text(RSID_COL_NICKNAME).toStdString() << " index: " << count < contactList; + rsIdentity->getMyContacts(contactList); + for(auto it = contactList.begin(); it != contactList.end(); it++){ + std::cerr <<"Name : "<< it->name << " and GxsId: " << it->gxsId << std::endl; + std::cerr <<"Status: " << it->status << " and PgPId: "<< std::endl; } //meiyousixin - show again the friend list here diff --git a/retroshare-gui/src/gui/common/UnseenFriendSelectionWidget.cpp b/retroshare-gui/src/gui/common/UnseenFriendSelectionWidget.cpp index d5668f5b34..29e62e8260 100644 --- a/retroshare-gui/src/gui/common/UnseenFriendSelectionWidget.cpp +++ b/retroshare-gui/src/gui/common/UnseenFriendSelectionWidget.cpp @@ -41,7 +41,7 @@ #include //unseenp2p #include "gui/common/UnseenContactSmartListView.h" -#include "gui/UnseenContactItemdelegate.h" +#include "gui/UnseenContactItemDelegate.h" #define COLUMN_NAME 0 diff --git a/retroshare-gui/src/gui/gxs/UnseenGxsGroupFrameDialog.cpp b/retroshare-gui/src/gui/gxs/UnseenGxsGroupFrameDialog.cpp index fec345f61c..0641feaaf4 100644 --- a/retroshare-gui/src/gui/gxs/UnseenGxsGroupFrameDialog.cpp +++ b/retroshare-gui/src/gui/gxs/UnseenGxsGroupFrameDialog.cpp @@ -44,7 +44,7 @@ #include "gui/gxschats/UnseenGxsSmartlistview.h" #include "gui/UnseenGxsConversationitemdelegate.h" -#define DEBUG_GROUPFRAMEDIALOG 1 +//#define DEBUG_GROUPFRAMEDIALOG 1 /* Images for TreeWidget */ #define IMAGE_SUBSCRIBE ":/images/edit_add24.png" @@ -1408,7 +1408,7 @@ void UnseenGxsGroupFrameDialog::selectConversation(const QModelIndex& index) UnseenGroupItemInfo gxsGroupItem = list.at(index.row()); - std::cerr << " gxsGroupItem info, name : " << gxsGroupItem.name.toStdString() << std::endl; + //std::cerr << " gxsGroupItem info, name : " << gxsGroupItem.name.toStdString() << std::endl; mGroupId = RsGxsGroupId(gxsGroupItem.id.toStdString()); diff --git a/retroshare-gui/src/gui/gxschats/UnseenGxsChatLobbyDialog.cpp b/retroshare-gui/src/gui/gxschats/UnseenGxsChatLobbyDialog.cpp index 8603b8b137..c898d79d82 100644 --- a/retroshare-gui/src/gui/gxschats/UnseenGxsChatLobbyDialog.cpp +++ b/retroshare-gui/src/gui/gxschats/UnseenGxsChatLobbyDialog.cpp @@ -672,9 +672,9 @@ void UnseenGxsChatLobbyDialog::updateParticipantsList() uint32_t token; rsGxsChats->updateGroup(token, thisGroup); - std::cerr << " Participating friends: " << std::endl; - std::cerr << " groupchat name: " << chatsInfo[0].mDescription<< std::endl; - std::cerr << " Participating nick names (sslId): " << std::endl; +// std::cerr << " Participating friends: " << std::endl; +// std::cerr << " groupchat name: " << chatsInfo[0].mDescription<< std::endl; +// std::cerr << " Participating nick names (sslId): " << std::endl; for (auto it2(thisGroup.members.begin()); it2 != thisGroup.members.end(); ++it2)