From 140205108a098f05718e4b33a6b19fc905044f18 Mon Sep 17 00:00:00 2001 From: csoler Date: Fri, 25 Dec 2015 22:37:06 -0500 Subject: [PATCH] added backend for distant message and distant chat filtering based on contact list --- libretroshare/src/chat/distantchat.cc | 89 +++++++- libretroshare/src/chat/distantchat.h | 25 ++- libretroshare/src/chat/distributedchat.cc | 20 +- libretroshare/src/chat/p3chatservice.cc | 8 +- libretroshare/src/chat/p3chatservice.h | 192 +++++++++--------- .../src/grouter/grouterclientservice.h | 62 +++--- libretroshare/src/grouter/p3grouter.cc | 11 +- libretroshare/src/gxstunnel/p3gxstunnel.cc | 8 +- libretroshare/src/retroshare/rsgxstunnel.h | 4 + libretroshare/src/retroshare/rsidentity.h | 1 + libretroshare/src/retroshare/rsmsgs.h | 11 +- libretroshare/src/rsserver/p3msgs.cc | 8 + libretroshare/src/rsserver/p3msgs.h | 3 + libretroshare/src/services/p3idservice.cc | 7 + libretroshare/src/services/p3idservice.h | 1 + libretroshare/src/services/p3msgservice.cc | 75 +++++-- libretroshare/src/services/p3msgservice.h | 7 +- libretroshare/src/util/rsprint.cc | 10 + libretroshare/src/util/rsprint.h | 1 + .../src/gui/settings/MessagePage.cpp | 10 +- 20 files changed, 373 insertions(+), 180 deletions(-) diff --git a/libretroshare/src/chat/distantchat.cc b/libretroshare/src/chat/distantchat.cc index e311b9233..cd2da7440 100644 --- a/libretroshare/src/chat/distantchat.cc +++ b/libretroshare/src/chat/distantchat.cc @@ -25,6 +25,7 @@ #include +#include #include "openssl/rand.h" #include "openssl/dh.h" @@ -108,6 +109,17 @@ void DistantChatService::handleRecvChatStatusItem(RsChatStatusItem *cs) std::cerr << "DistantChatService::handleRecvChatStatusItem(): received keep alive packet for inactive chat! peerId=" << cs->PeerId() << std::endl; } +bool DistantChatService::acceptDataFromPeer(const RsGxsId& gxs_id) +{ + if(mDistantChatPermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS) + return (rsIdentity!=NULL) && rsIdentity->isARegularContact(gxs_id) ; + + if(mDistantChatPermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY) + return false ; + + return true ; +} + void DistantChatService::notifyTunnelStatus(const RsGxsTunnelService::RsGxsTunnelId &tunnel_id, uint32_t tunnel_status) { std::cerr << "DistantChatService::notifyTunnelStatus(): got notification " << std::hex << tunnel_status << std::dec << " for tunnel " << tunnel_id << std::endl; @@ -137,9 +149,7 @@ void DistantChatService::receiveData(const RsGxsTunnelService::RsGxsTunnelId &tu std::cerr << "DistantChatService::receiveData(): got data of size " << data_size << " for tunnel " << tunnel_id << std::endl; std::cerr << " received: " << RsUtil::BinToHex(data,data_size) << std::endl; std::cerr << " deserialising..." << std::endl; - - RsItem *item = RsChatSerialiser().deserialise(data,&data_size) ; - + // always make the contact up to date. This is useful for server side, which doesn't know about the chat until it // receives the first item. { @@ -149,21 +159,26 @@ void DistantChatService::receiveData(const RsGxsTunnelService::RsGxsTunnelId &tu if(!mGxsTunnels->getTunnelInfo(tunnel_id,tinfo)) return ; + // Check if the data is accepted. We cannot prevent the creation of tunnels at the level of p3GxsTunnels, since tunnels are shared between services. + // however, + DistantChatContact& contact(mDistantChatContacts[DistantChatPeerId(tunnel_id)]) ; - + contact.to_id = tinfo.destination_gxs_id ; contact.from_id = tinfo.source_gxs_id ; } - + + RsItem *item = RsChatSerialiser().deserialise(data,&data_size) ; + if(item != NULL) { - item->PeerId(RsPeerId(tunnel_id)) ; // just in case, but normally this is already done. - + item->PeerId(RsPeerId(tunnel_id)) ; // just in case, but normally this is already done. + handleIncomingItem(item) ; RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD); } else - std::cerr << " (EE) item could not be deserialised!" << std::endl; + std::cerr << " (EE) item could not be deserialised!" << std::endl; } void DistantChatService::markDistantChatAsClosed(const DistantChatPeerId& dcpid) @@ -243,4 +258,62 @@ bool DistantChatService::closeDistantChatConnexion(const DistantChatPeerId &tunn return true ; } +uint32_t DistantChatService::getDistantChatPermissionFlags() +{ + return mDistantChatPermissions ; +} +bool DistantChatService::setDistantChatPermissionFlags(uint32_t flags) +{ + if(mDistantChatPermissions != flags) + { + mDistantChatPermissions = flags ; + std::cerr << "(II) Changing distant chat permissions to " << flags << ". Existing openned chats will however remain active until closed" << std::endl; + triggerConfigSave() ; + } + + return true ; +} + +void DistantChatService::addToSaveList(std::list& list) const +{ + /* Save permission flags */ + + RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; + RsTlvKeyValue kv; + kv.key = "DISTANT_CHAT_PERMISSION_FLAGS" ; + kv.value = RsUtil::NumberToString(mDistantChatPermissions) ; + + vitem->tlvkvs.pairs.push_back(kv) ; + + list.push_back(vitem) ; +} +bool DistantChatService::processLoadListItem(const RsItem *item) +{ + const RsConfigKeyValueSet *vitem = NULL ; + + if(NULL != (vitem = dynamic_cast(item))) + for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) + if(kit->key == "DISTANT_CHAT_PERMISSION_FLAGS") + { +#ifdef DEBUG_DISTANT_CHAT + std::cerr << "Loaded distant chat permission flags: " << kit->value << std::endl ; +#endif + if (!kit->value.empty()) + { + std::istringstream is(kit->value) ; + + uint32_t tmp ; + is >> tmp ; + + if(tmp < 3) + mDistantChatPermissions = tmp ; + else + std::cerr << "(EE) Invalid value read for DistantChatPermission flags in config: " << tmp << std::endl; + } + + return true; + } + + return false ; +} diff --git a/libretroshare/src/chat/distantchat.h b/libretroshare/src/chat/distantchat.h index 20435dc63..a2937148a 100644 --- a/libretroshare/src/chat/distantchat.h +++ b/libretroshare/src/chat/distantchat.h @@ -42,18 +42,27 @@ public: DistantChatService() : mDistantChatMtx("distant chat") { mGxsTunnels = NULL ; + mDistantChatPermissions = RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE ; // default: accept everyone } - // Overloaded methods from RsGxsTunnelClientService + virtual void triggerConfigSave()=0 ; + bool processLoadListItem(const RsItem *item) ; + void addToSaveList(std::list& list) const; - virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) ; - // Creates the invite if the public key of the distant peer is available. // Om success, stores the invite in the map above, so that we can respond to tunnel requests. // bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id, const RsGxsId &from_gxs_id, DistantChatPeerId& dcpid, uint32_t &error_code) ; bool closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) ; + // Sets flags to only allow connexion from some people. + + uint32_t getDistantChatPermissionFlags() ; + bool setDistantChatPermissionFlags(uint32_t flags) ; + + // Returns the status of a distant chat contact. The contact is defined by the tunnel id (turned into a DistantChatPeerId) because + // each pair of talking GXS id needs to be treated separately + virtual bool getDistantChatStatus(const DistantChatPeerId &tunnel_id, DistantChatPeerInfo& cinfo) ; // derived in p3ChatService, so as to pass down some info @@ -74,8 +83,17 @@ private: // std::map mDistantChatContacts ; // current peers we can talk to + // Permission handling + + uint32_t mDistantChatPermissions ; + // Overloaded from RsGxsTunnelClientService +public: + virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) ; + +private: + virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) ; virtual void notifyTunnelStatus(const RsGxsTunnelService::RsGxsTunnelId& tunnel_id,uint32_t tunnel_status) ; virtual void receiveData(const RsGxsTunnelService::RsGxsTunnelId& id,unsigned char *data,uint32_t data_size) ; @@ -84,6 +102,5 @@ private: void markDistantChatAsClosed(const DistantChatPeerId& dcpid) ; RsGxsTunnelService *mGxsTunnels ; - RsMutex mDistantChatMtx ; }; diff --git a/libretroshare/src/chat/distributedchat.cc b/libretroshare/src/chat/distributedchat.cc index dbecf3346..5d1ddfff0 100644 --- a/libretroshare/src/chat/distributedchat.cc +++ b/libretroshare/src/chat/distributedchat.cc @@ -1903,19 +1903,19 @@ bool DistributedChatService::processLoadListItem(const RsItem *item) if(NULL != (vitem = dynamic_cast(item))) for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) if(kit->key == "DEFAULT_IDENTITY") - { + { #ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Loaded config default nick name for distributed chat: " << kit->value << std::endl ; + std::cerr << "Loaded config default nick name for distributed chat: " << kit->value << std::endl ; #endif - if (!kit->value.empty()) - { - _default_identity = RsGxsId(kit->value) ; - if(_default_identity.isNull()) - std::cerr << "ERROR: default identity is malformed." << std::endl; - } + if (!kit->value.empty()) + { + _default_identity = RsGxsId(kit->value) ; + if(_default_identity.isNull()) + std::cerr << "ERROR: default identity is malformed." << std::endl; + } - return true; - } + return true; + } const RsChatLobbyConfigItem *clci = NULL ; diff --git a/libretroshare/src/chat/p3chatservice.cc b/libretroshare/src/chat/p3chatservice.cc index 9aa02b0e0..60894684a 100644 --- a/libretroshare/src/chat/p3chatservice.cc +++ b/libretroshare/src/chat/p3chatservice.cc @@ -1192,11 +1192,8 @@ bool p3ChatService::loadList(std::list& load) continue; } - if(DistributedChatService::processLoadListItem(*it)) - { - delete *it; - continue; - } + DistributedChatService::processLoadListItem(*it) ; + DistantChatService::processLoadListItem(*it) ; // delete unknown items delete *it; @@ -1238,6 +1235,7 @@ bool p3ChatService::saveList(bool& cleanup, std::list& list) } DistributedChatService::addToSaveList(list) ; + DistantChatService::addToSaveList(list) ; return true; } diff --git a/libretroshare/src/chat/p3chatservice.h b/libretroshare/src/chat/p3chatservice.h index 76b1c4e18..f476c61aa 100644 --- a/libretroshare/src/chat/p3chatservice.h +++ b/libretroshare/src/chat/p3chatservice.h @@ -53,186 +53,186 @@ typedef RsPeerId ChatLobbyVirtualPeerId ; */ class p3ChatService: public p3Service, public DistantChatService, public DistributedChatService, public p3Config, public pqiServiceMonitor { - public: - p3ChatService(p3ServiceControl *cs, p3IdService *pids,p3LinkMgr *cm, p3HistoryMgr *historyMgr); +public: + p3ChatService(p3ServiceControl *cs, p3IdService *pids,p3LinkMgr *cm, p3HistoryMgr *historyMgr); - virtual RsServiceInfo getServiceInfo(); + virtual RsServiceInfo getServiceInfo(); - /***** overloaded from p3Service *****/ - /*! + /***** overloaded from p3Service *****/ + /*! * This retrieves all chat msg items and also (important!) * processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned * (important! also) notifications sent to notify base on receipt avatar, immediate status and custom status * : notifyCustomState, notifyChatStatus, notifyPeerHasNewAvatar * @see NotifyBase */ - virtual int tick(); + virtual int tick(); - /*************** pqiMonitor callback ***********************/ - virtual void statusChange(const std::list &plist); + /*************** pqiMonitor callback ***********************/ + virtual void statusChange(const std::list &plist); - /*! + /*! * public chat sent to all peers */ - void sendPublicChat(const std::string &msg); + void sendPublicChat(const std::string &msg); - /********* RsMsgs ***********/ - /*! - * Send a chat message. - * @param destination where to send the chat message - * @param msg the message - * @see ChatId - */ - bool sendChat(ChatId destination, std::string msg); + /********* RsMsgs ***********/ + /*! + * Send a chat message. + * @param destination where to send the chat message + * @param msg the message + * @see ChatId + */ + bool sendChat(ChatId destination, std::string msg); - /*! + /*! * chat is sent to specifc peer * @param id peer to send chat msg to */ - bool sendPrivateChat(const RsPeerId &id, const std::string &msg); + bool sendPrivateChat(const RsPeerId &id, const std::string &msg); - /*! + /*! * can be used to send 'immediate' status msgs, these status updates are meant for immediate use by peer (not saved by rs) * e.g currently used to update user when a peer 'is typing' during a chat */ - void sendStatusString(const ChatId& peer_id,const std::string& status_str) ; + void sendStatusString(const ChatId& peer_id,const std::string& status_str) ; - /*! + /*! * send to all peers online *@see sendStatusString() */ - void sendGroupChatStatusString(const std::string& status_str) ; + void sendGroupChatStatusString(const std::string& status_str) ; - /*! + /*! * this retrieves custom status for a peers, generate a requests to the peer * @param peer_id the id of the peer you want status string for */ - std::string getCustomStateString(const RsPeerId& peer_id) ; + std::string getCustomStateString(const RsPeerId& peer_id) ; - /*! + /*! * sets the client's custom status, generates 'status available' item sent to all online peers */ - void setOwnCustomStateString(const std::string&) ; + void setOwnCustomStateString(const std::string&) ; - /*! + /*! * @return client's custom string */ - std::string getOwnCustomStateString() ; + std::string getOwnCustomStateString() ; - /*! gets the peer's avatar in jpeg format, if available. Null otherwise. Also asks the peer to send + /*! gets the peer's avatar in jpeg format, if available. Null otherwise. Also asks the peer to send * its avatar, if not already available. Creates a new unsigned char array. It's the caller's * responsibility to delete this ones used. */ - void getAvatarJpegData(const RsPeerId& peer_id,unsigned char *& data,int& size) ; + void getAvatarJpegData(const RsPeerId& peer_id,unsigned char *& data,int& size) ; - /*! + /*! * Sets the avatar data and size for client's account * @param data is copied, so should be destroyed by the caller */ - void setOwnAvatarJpegData(const unsigned char *data,int size) ; + void setOwnAvatarJpegData(const unsigned char *data,int size) ; - /*! + /*! * Gets the avatar data for clients account * data is in jpeg format */ - void getOwnAvatarJpegData(unsigned char *& data,int& size) ; + void getOwnAvatarJpegData(unsigned char *& data,int& size) ; - /*! + /*! * Return the max message size for security forwarding * @param type RS_CHAT_TYPE_... * return 0 unlimited */ - static uint32_t getMaxMessageSecuritySize(int type); + static uint32_t getMaxMessageSecuritySize(int type); - /*! + /*! * Checks message security, especially remove billion laughs attacks */ - static bool checkForMessageSecurity(RsChatMsgItem *) ; + static bool checkForMessageSecurity(RsChatMsgItem *) ; - /*! + /*! * @param clear private chat queue */ - bool clearPrivateChatQueue(bool incoming, const RsPeerId &id); + bool clearPrivateChatQueue(bool incoming, const RsPeerId &id); - protected: - /************* from p3Config *******************/ - virtual RsSerialiser *setupSerialiser() ; +protected: + /************* from p3Config *******************/ + virtual RsSerialiser *setupSerialiser() ; - /*! + /*! * chat msg items and custom status are saved */ - virtual bool saveList(bool& cleanup, std::list&) ; - virtual void saveDone(); - virtual bool loadList(std::list& load) ; + virtual bool saveList(bool& cleanup, std::list&) ; + virtual void saveDone(); + virtual bool loadList(std::list& load) ; - // accepts virtual peer id - bool isOnline(const RsPeerId &pid) ; + // accepts virtual peer id + bool isOnline(const RsPeerId &pid) ; - /// This is to be used by subclasses/parents to call IndicateConfigChanged() - virtual void triggerConfigSave() { IndicateConfigChanged() ; } - /// Same, for storing messages in incoming list - virtual void locked_storeIncomingMsg(RsChatMsgItem *) ; + /// This is to be used by subclasses/parents to call IndicateConfigChanged() + virtual void triggerConfigSave() { IndicateConfigChanged() ; } + /// Same, for storing messages in incoming list + virtual void locked_storeIncomingMsg(RsChatMsgItem *) ; - private: - RsMutex mChatMtx; +private: + RsMutex mChatMtx; - class AvatarInfo ; - class StateStringInfo ; + class AvatarInfo ; + class StateStringInfo ; - // Receive chat queue - void receiveChatQueue(); - void handleIncomingItem(RsItem *); // called by the former, and turtle handler for incoming encrypted items + // Receive chat queue + void receiveChatQueue(); + void handleIncomingItem(RsItem *); // called by the former, and turtle handler for incoming encrypted items - virtual void sendChatItem(RsChatItem *) ; + virtual void sendChatItem(RsChatItem *) ; - void initChatMessage(RsChatMsgItem *c, ChatMessage& msg); + void initChatMessage(RsChatMsgItem *c, ChatMessage& msg); - /// Send avatar info to peer in jpeg format. - void sendAvatarJpegData(const RsPeerId& peer_id) ; + /// Send avatar info to peer in jpeg format. + void sendAvatarJpegData(const RsPeerId& peer_id) ; - /// Send custom state info to peer - void sendCustomState(const RsPeerId& peer_id); + /// Send custom state info to peer + void sendCustomState(const RsPeerId& peer_id); - /// Receive the avatar in a chat item, with RS_CHAT_RECEIVE_AVATAR flag. - void receiveAvatarJpegData(RsChatAvatarItem *ci) ; // new method - void receiveStateString(const RsPeerId& id,const std::string& s) ; + /// Receive the avatar in a chat item, with RS_CHAT_RECEIVE_AVATAR flag. + void receiveAvatarJpegData(RsChatAvatarItem *ci) ; // new method + void receiveStateString(const RsPeerId& id,const std::string& s) ; - /// methods for handling various Chat items. - bool handleRecvChatMsgItem(RsChatMsgItem *item) ; // returns false if the item should be deleted. - void handleRecvChatStatusItem(RsChatStatusItem *item) ; - void handleRecvChatAvatarItem(RsChatAvatarItem *item) ; + /// methods for handling various Chat items. + bool handleRecvChatMsgItem(RsChatMsgItem *item) ; // returns false if the item should be deleted. + void handleRecvChatStatusItem(RsChatStatusItem *item) ; + void handleRecvChatAvatarItem(RsChatAvatarItem *item) ; - /// Sends a request for an avatar to the peer of given id - void sendAvatarRequest(const RsPeerId& peer_id) ; + /// Sends a request for an avatar to the peer of given id + void sendAvatarRequest(const RsPeerId& peer_id) ; - /// Send a request for custom status string - void sendCustomStateRequest(const RsPeerId& peer_id); + /// Send a request for custom status string + void sendCustomStateRequest(const RsPeerId& peer_id); - /// called as a proxy to sendItem(). Possibly splits item into multiple items of size lower than the maximum item size. - //void checkSizeAndSendMessage(RsChatLobbyMsgItem *item) ; - void checkSizeAndSendMessage(RsChatMsgItem *item) ; // keep for compatibility for a few weeks. + /// called as a proxy to sendItem(). Possibly splits item into multiple items of size lower than the maximum item size. + //void checkSizeAndSendMessage(RsChatLobbyMsgItem *item) ; + void checkSizeAndSendMessage(RsChatMsgItem *item) ; // keep for compatibility for a few weeks. - /// Called when a RsChatMsgItem is received. The item may be collapsed with any waiting partial chat item from the same peer. - bool locked_checkAndRebuildPartialMessage(RsChatMsgItem *) ; + /// Called when a RsChatMsgItem is received. The item may be collapsed with any waiting partial chat item from the same peer. + bool locked_checkAndRebuildPartialMessage(RsChatMsgItem *) ; - RsChatAvatarItem *makeOwnAvatarItem() ; - RsChatStatusItem *makeOwnCustomStateStringItem() ; + RsChatAvatarItem *makeOwnAvatarItem() ; + RsChatStatusItem *makeOwnCustomStateStringItem() ; - p3ServiceControl *mServiceCtrl; - p3LinkMgr *mLinkMgr; - p3HistoryMgr *mHistoryMgr; + p3ServiceControl *mServiceCtrl; + p3LinkMgr *mLinkMgr; + p3HistoryMgr *mHistoryMgr; - std::list privateOutgoingList; // messages waiting to be send when peer comes online + std::list privateOutgoingList; // messages waiting to be send when peer comes online - AvatarInfo *_own_avatar ; - std::map _avatars ; - std::map _pendingPartialMessages ; + AvatarInfo *_own_avatar ; + std::map _avatars ; + std::map _pendingPartialMessages ; - std::string _custom_status_string ; - std::map _state_strings ; + std::string _custom_status_string ; + std::map _state_strings ; - RsChatSerialiser *_serializer ; + RsChatSerialiser *_serializer ; }; class p3ChatService::StateStringInfo diff --git a/libretroshare/src/grouter/grouterclientservice.h b/libretroshare/src/grouter/grouterclientservice.h index 00d9e546b..99be9d564 100644 --- a/libretroshare/src/grouter/grouterclientservice.h +++ b/libretroshare/src/grouter/grouterclientservice.h @@ -42,37 +42,41 @@ static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_FAILED = 0x0002 ; // class GRouterClientService { - public: - // This method is called by the turtle router to send data that comes out of a turtle tunnel. - // The turtle router stays responsible for the memory management of data. Most of the time the - // data chunk is a serialized item to be de-serialized by the client service. - // - // Parameters: - // item : global router item. Handled by the client service. - // destination_key : key that is associated with this item. Can be useful for the client. - // - // GRouter stays owner of the item, so the client should not delete it! - // - virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& /*signing_key*/, GRouterServiceId &/*client_id*/, uint8_t */*data*/, uint32_t /*data_size*/) - { - std::cerr << "!!!!!! Received Data from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; - std::cerr << " destination key_id = " << destination_key.toStdString() << std::endl; - } +public: + // This method is called by the turtle router to send data that comes out of a turtle tunnel. + // The turtle router stays responsible for the memory management of data. Most of the time the + // data chunk is a serialized item to be de-serialized by the client service. + // + // Parameters: + // item : global router item. Handled by the client service. + // destination_key : key that is associated with this item. Can be useful for the client. + // + // GRouter stays owner of the item, so the client should not delete it! + // + virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& /*signing_key*/, GRouterServiceId &/*client_id*/, uint8_t */*data*/, uint32_t /*data_size*/) + { + std::cerr << "!!!!!! Received Data from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; + std::cerr << " destination key_id = " << destination_key.toStdString() << std::endl; + } - // This method is called by the global router when a message has been received, or cannot be sent, etc. - // - virtual void notifyDataStatus(const GRouterMsgPropagationId& received_id,uint32_t data_status) - { - std::cerr << "!!!!!! Received Data status from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; - std::cerr << " message ID = " << received_id << std::endl; - std::cerr << " data status = " << data_status << std::endl; - } + // This method is called by the global router when a message has been received, or cannot be sent, etc. + // + virtual void notifyDataStatus(const GRouterMsgPropagationId& received_id,uint32_t data_status) + { + std::cerr << "!!!!!! Received Data status from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; + std::cerr << " message ID = " << received_id << std::endl; + std::cerr << " data status = " << data_status << std::endl; + } - // This function is mandatory. It should do two things: - // 1 - keep a pointer to the global router, so as to be able to send data (e.g. copy pt into a local variable) - // 2 - call pt->registerTunnelService(this), so that the TR knows that service and can send back information to it. - // - virtual void connectToGlobalRouter(p3GRouter *pt) = 0 ; + // This function is mandatory. It should do two things: + // 1 - keep a pointer to the global router, so as to be able to send data (e.g. copy pt into a local variable) + // 2 - call pt->registerTunnelService(this), so that the TR knows that service and can send back information to it. + // + virtual void connectToGlobalRouter(p3GRouter *pt) = 0 ; + + // should be derived to determine wether the client accepts data from this peer or not. If not, the data is dropped. + + virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) =0; }; diff --git a/libretroshare/src/grouter/p3grouter.cc b/libretroshare/src/grouter/p3grouter.cc index ddb6dd004..17e03735d 100644 --- a/libretroshare/src/grouter/p3grouter.cc +++ b/libretroshare/src/grouter/p3grouter.cc @@ -1661,10 +1661,13 @@ void p3GRouter::handleIncomingDataItem(RsGRouterGenericDataItem *data_item) std::cerr << " notyfying client." << std::endl; #endif - client->receiveGRouterData(decrypted_item->destination_key,decrypted_item->signature.keyId,service_id,decrypted_item->data_bytes,decrypted_item->data_size); - - decrypted_item->data_bytes = NULL ; - decrypted_item->data_size = 0 ; + if(client->acceptDataFromPeer(decrypted_item->signature.keyId)) + { + client->receiveGRouterData(decrypted_item->destination_key,decrypted_item->signature.keyId,service_id,decrypted_item->data_bytes,decrypted_item->data_size); + + decrypted_item->data_bytes = NULL ; + decrypted_item->data_size = 0 ; + } delete decrypted_item ; } diff --git a/libretroshare/src/gxstunnel/p3gxstunnel.cc b/libretroshare/src/gxstunnel/p3gxstunnel.cc index f7be21db7..5982f7b59 100644 --- a/libretroshare/src/gxstunnel/p3gxstunnel.cc +++ b/libretroshare/src/gxstunnel/p3gxstunnel.cc @@ -327,6 +327,8 @@ void p3GxsTunnelService::handleRecvTunnelDataItem(const RsGxsTunnelId& tunnel_id #endif RsGxsTunnelClientService *service = NULL ; + RsGxsId peer_from ; + { RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ std::map::const_iterator it = mRegisteredServices.find(item->service_id) ; @@ -341,10 +343,14 @@ void p3GxsTunnelService::handleRecvTunnelDataItem(const RsGxsTunnelId& tunnel_id std::map::iterator it2 = _gxs_tunnel_contacts.find(tunnel_id) ; if(it2 != _gxs_tunnel_contacts.end()) + { it2->second.client_services.insert(item->service_id) ; + peer_from = it2->second.to_gxs_id ; + } } - service->receiveData(tunnel_id,item->data,item->data_size) ; + if(service->acceptDataFromPeer(peer_from)) + service->receiveData(tunnel_id,item->data,item->data_size) ; item->data = NULL ; // avoids deletion, since the client has the memory now item->data_size = 0 ; diff --git a/libretroshare/src/retroshare/rsgxstunnel.h b/libretroshare/src/retroshare/rsgxstunnel.h index 671441920..49bb9eca4 100644 --- a/libretroshare/src/retroshare/rsgxstunnel.h +++ b/libretroshare/src/retroshare/rsgxstunnel.h @@ -63,6 +63,10 @@ public: // Used by the creator of the service to supply a pointer to the GXS tunnel service for it to be able to send data etc. virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) =0; + + // Gives feedback about type of data that is allowed in. For security reasons, this always needs to be re-derived (Clients can return true on default) + + virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) = 0 ; }; class GxsTunnelInfo diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index 965555917..b37af3845 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -250,6 +250,7 @@ virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment, uint16_t tag_class, uint16_t tag_type, std::string &tag) = 0; virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) = 0 ; + virtual bool isARegularContact(const RsGxsId& id) = 0 ; // Specific RsIdentity Functions.... /* Specific Service Data */ diff --git a/libretroshare/src/retroshare/rsmsgs.h b/libretroshare/src/retroshare/rsmsgs.h index 949494efb..262e0cfe0 100644 --- a/libretroshare/src/retroshare/rsmsgs.h +++ b/libretroshare/src/retroshare/rsmsgs.h @@ -264,11 +264,11 @@ public: #define RS_DISTANT_CHAT_FLAG_SIGNED 0x0001 #define RS_DISTANT_CHAT_FLAG_SIGNATURE_OK 0x0002 -// flags to define who we accept to talk to +// flags to define who we accept to talk to. Each flag *removes* some people. -#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_NONE 0x0000 -#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_EVERYBODY 0x0001 -#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST 0x0002 +#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE 0x0000 +#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS 0x0001 +#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY 0x0002 struct DistantChatPeerInfo { @@ -482,6 +482,9 @@ virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId& /* Distant chat */ /****************************************/ + virtual uint32_t getDistantChatPermissionFlags()=0 ; + virtual bool setDistantChatPermissionFlags(uint32_t flags)=0 ; + virtual bool initiateDistantChatConnexion(const RsGxsId& to_pid,const RsGxsId& from_pid,DistantChatPeerId& pid,uint32_t& error_code) = 0; virtual bool getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info)=0; virtual bool closeDistantChatConnexion(const DistantChatPeerId& pid)=0; diff --git a/libretroshare/src/rsserver/p3msgs.cc b/libretroshare/src/rsserver/p3msgs.cc index 6503bcc16..64c5b0179 100644 --- a/libretroshare/src/rsserver/p3msgs.cc +++ b/libretroshare/src/rsserver/p3msgs.cc @@ -537,4 +537,12 @@ bool p3Msgs::closeDistantChatConnexion(const DistantChatPeerId &pid) { return mChatSrv->closeDistantChatConnexion(pid) ; } +bool p3Msgs::setDistantChatPermissionFlags(uint32_t flags) +{ + return mChatSrv->setDistantChatPermissionFlags(flags) ; +} +uint32_t p3Msgs::getDistantChatPermissionFlags() +{ + return mChatSrv->getDistantChatPermissionFlags() ; +} diff --git a/libretroshare/src/rsserver/p3msgs.h b/libretroshare/src/rsserver/p3msgs.h index 13211a161..ecef61b30 100644 --- a/libretroshare/src/rsserver/p3msgs.h +++ b/libretroshare/src/rsserver/p3msgs.h @@ -159,6 +159,9 @@ class p3Msgs: public RsMsgs virtual bool getDistantChatStatus(const DistantChatPeerId& gxs_id,DistantChatPeerInfo& info); virtual bool closeDistantChatConnexion(const DistantChatPeerId &pid) ; + virtual uint32_t getDistantChatPermissionFlags() ; + virtual bool setDistantChatPermissionFlags(uint32_t flags) ; + private: p3MsgService *mMsgSrv; diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 469015702..37fddb5db 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -212,6 +212,13 @@ uint32_t p3IdService::idAuthenPolicy() return policy; } + +bool p3IdService::isARegularContact(const RsGxsId& id) +{ + RsStackMutex stack(mIdMtx); + return mContacts.find(id) != mContacts.end() ; +} + bool p3IdService::setAsRegularContact(const RsGxsId& id,bool b) { std::set::iterator it = mContacts.find(id) ; diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h index 93db5ccd8..4d90c3a5a 100644 --- a/libretroshare/src/services/p3idservice.h +++ b/libretroshare/src/services/p3idservice.h @@ -266,6 +266,7 @@ virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment, uint16_t tag_class, uint16_t tag_type, std::string &tag); virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) ; + virtual bool isARegularContact(const RsGxsId& id) ; /**************** RsGixs Implementation ***************/ diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc index 2b69cd205..bc7e34317 100644 --- a/libretroshare/src/services/p3msgservice.cc +++ b/libretroshare/src/services/p3msgservice.cc @@ -87,6 +87,7 @@ p3MsgService::p3MsgService(p3ServiceControl *sc, p3IdService *id_serv) mShouldEnableDistantMessaging = true ; mDistantMessagingEnabled = false ; + mDistantMessagePermissions = RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE ; /* Initialize standard tag types */ if(sc) @@ -468,6 +469,10 @@ bool p3MsgService::saveList(bool& cleanup, std::list& itemList) kv.key = "DISTANT_MESSAGES_ENABLED" ; kv.value = mShouldEnableDistantMessaging?"YES":"NO" ; vitem->tlvkvs.pairs.push_back(kv) ; + + kv.key = "DISTANT_MESSAGE_PERMISSION_FLAGS" ; + kv.value = RsUtil::NumberToString(mDistantMessagePermissions) ; + vitem->tlvkvs.pairs.push_back(kv) ; itemList.push_back(vitem) ; @@ -558,13 +563,13 @@ bool p3MsgService::loadList(std::list& load) mMsgUniqueId = mitem->msgId + 1; } items.push_back(mitem); - } - else if (NULL != (grm = dynamic_cast(*it))) - { - // merge. - for(std::map::const_iterator it(grm->ongoing_msgs.begin());it!=grm->ongoing_msgs.end();++it) - _ongoing_messages.insert(*it) ; - } + } + else if (NULL != (grm = dynamic_cast(*it))) + { + // merge. + for(std::map::const_iterator it(grm->ongoing_msgs.begin());it!=grm->ongoing_msgs.end();++it) + _ongoing_messages.insert(*it) ; + } else if(NULL != (mtt = dynamic_cast(*it))) { // delete standard tags as they are now save in config @@ -574,7 +579,7 @@ bool p3MsgService::loadList(std::list& load) } else { - delete mTags[mtt->tagId]; + delete mTags[mtt->tagId]; mTags.erase(tagIt); mTags.insert(std::pair(mtt->tagId, mtt)); } @@ -586,7 +591,7 @@ bool p3MsgService::loadList(std::list& load) } else if(NULL != (msi = dynamic_cast(*it))) { - srcIdMsgMap.insert(std::pair(msi->msgId, msi->srcId)); + srcIdMsgMap.insert(std::pair(msi->msgId, msi->srcId)); mSrcIds.insert(std::pair(msi->msgId, msi)); // does not need to be kept } else if(NULL != (msp = dynamic_cast(*it))) @@ -598,13 +603,33 @@ bool p3MsgService::loadList(std::list& load) if(NULL != (vitem = dynamic_cast(*it))) for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - if(kit->key == "DISTANT_MESSAGES_ENABLED") + { + if(kit->key == "DISTANT_MESSAGES_ENABLED") { #ifdef MSG_DEBUG std::cerr << "Loaded config default nick name for distant chat: " << kit->value << std::endl ; #endif - mShouldEnableDistantMessaging = (kit->value == "YES") ; - } + mShouldEnableDistantMessaging = (kit->value == "YES") ; + } + if(kit->key == "DISTANT_MESSAGE_PERMISSION_FLAGS") + { +#ifdef MSG_DEBUG + std::cerr << "Loaded distant message permission flags: " << kit->value << std::endl ; +#endif + if (!kit->value.empty()) + { + std::istringstream is(kit->value) ; + + uint32_t tmp ; + is >> tmp ; + + if(tmp < 3) + mDistantMessagePermissions = tmp ; + else + std::cerr << "(EE) Invalid value read for DistantMessagePermission flags in config: " << tmp << std::endl; + } + } + } } @@ -1791,6 +1816,32 @@ void p3MsgService::notifyDataStatus(const GRouterMsgPropagationId& id,uint32_t d RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_ADD); IndicateConfigChanged() ; } +bool p3MsgService::acceptDataFromPeer(const RsGxsId& to_gxs_id) +{ + if(mDistantMessagePermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS) + return (rsIdentity!=NULL) && rsIdentity->isARegularContact(to_gxs_id) ; + + if(mDistantMessagePermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY) + return false ; + + return true ; +} + +void p3MsgService::setDistantMessagingPermissionFlags(uint32_t flags) +{ + if(flags != mDistantMessagePermissions) + { + mDistantMessagePermissions = flags ; + + IndicateConfigChanged() ; + } +} + +uint32_t p3MsgService::getDistantMessagingPermissionFlags() +{ + return mDistantMessagePermissions ; +} + void p3MsgService::receiveGRouterData(const RsGxsId& destination_key, const RsGxsId& signing_key,GRouterServiceId& client_id,uint8_t *data,uint32_t data_size) { std::cerr << "p3MsgService::receiveGRouterData(): received message item of size " << data_size << ", for key " << destination_key << std::endl; diff --git a/libretroshare/src/services/p3msgservice.h b/libretroshare/src/services/p3msgservice.h index 66c14e209..74f47cf26 100644 --- a/libretroshare/src/services/p3msgservice.h +++ b/libretroshare/src/services/p3msgservice.h @@ -126,8 +126,9 @@ class p3MsgService: public p3Service, public p3Config, public pqiServiceMonitor, }; void enableDistantMessaging(bool b) ; bool distantMessagingEnabled() ; - void setDistantMessagingPermissionFlags(uint32_t flags) {} - uint32_t getDistantMessagingPermissionFlags() { return 0 ;} + + void setDistantMessagingPermissionFlags(uint32_t flags) ; + uint32_t getDistantMessagingPermissionFlags() ; private: void sendDistantMsgItem(RsMsgItem *msgitem) ; @@ -139,6 +140,7 @@ class p3MsgService: public p3Service, public p3Config, public pqiServiceMonitor, // Overloaded from GRouterClientService + virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) ; virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& signing_key, GRouterServiceId &client_id, uint8_t *data, uint32_t data_size) ; virtual void notifyDataStatus(const GRouterMsgPropagationId& msg_id,uint32_t data_status) ; @@ -205,6 +207,7 @@ class p3MsgService: public p3Service, public p3Config, public pqiServiceMonitor, std::string config_dir; bool mDistantMessagingEnabled ; + uint32_t mDistantMessagePermissions ; bool mShouldEnableDistantMessaging ; }; diff --git a/libretroshare/src/util/rsprint.cc b/libretroshare/src/util/rsprint.cc index 0d0ec5a04..5735088f4 100644 --- a/libretroshare/src/util/rsprint.cc +++ b/libretroshare/src/util/rsprint.cc @@ -27,6 +27,7 @@ #include "util/rsprint.h" #include "util/rsstring.h" #include +#include #include #include @@ -35,6 +36,15 @@ #include #endif +std::string RsUtil::NumberToString(uint64_t n) +{ + std::ostringstream os ; + os << n ; + os.flush() ; + + return os.str(); +} + std::string RsUtil::BinToHex(const std::string &bin) { return BinToHex(bin.c_str(), bin.length()); diff --git a/libretroshare/src/util/rsprint.h b/libretroshare/src/util/rsprint.h index 9a1dbe7c3..ebcccb8ef 100644 --- a/libretroshare/src/util/rsprint.h +++ b/libretroshare/src/util/rsprint.h @@ -36,6 +36,7 @@ namespace RsUtil { std::string BinToHex(const std::string &bin); std::string BinToHex(const char *arr, const uint32_t len); std::string BinToHex(const unsigned char *arr, const uint32_t len); +std::string NumberToString(uint64_t n); std::string HashId(const std::string &id, bool reverse = false); //std::string AccurateTimeString(); diff --git a/retroshare-gui/src/gui/settings/MessagePage.cpp b/retroshare-gui/src/gui/settings/MessagePage.cpp index 3211300b1..89dcaa0ac 100644 --- a/retroshare-gui/src/gui/settings/MessagePage.cpp +++ b/retroshare-gui/src/gui/settings/MessagePage.cpp @@ -64,13 +64,13 @@ void MessagePage::distantMsgsComboBoxChanged(int i) { switch(i) { - case 0: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_EVERYBODY |RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST) ; + case 0: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE) ; break ; - case 1: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST) ; + case 1: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS) ; break ; - case 2: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_NONE) ; + case 2: rsMail->setDistantMessagingPermissionFlags(RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY) ; break ; @@ -123,9 +123,9 @@ MessagePage::load() uint32_t flags = rsMail->getDistantMessagingPermissionFlags() ; - if(flags == (RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST | RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_EVERYBODY)) + if(flags & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY) ui.comboBox->setCurrentIndex(2); - else if(flags == RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST) + else if(flags & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS) ui.comboBox->setCurrentIndex(1); else ui.comboBox->setCurrentIndex(0);