diff --git a/src/chat/p3chatservice.cc b/src/chat/p3chatservice.cc index e585327402..bf99d687e2 100644 --- a/src/chat/p3chatservice.cc +++ b/src/chat/p3chatservice.cc @@ -1501,6 +1501,27 @@ std::string p3ChatService::getCustomStateString(const RsPeerId& peer_id) return std::string() ; } +void p3ChatService::locked_requestAvatar(const RsPeerId& peer_id) +{ + /* Create placeholder to store request time */ + std::map::const_iterator it = _avatars.find(peer_id) ; + + if(it == _avatars.end()) + { + _avatars[peer_id] = new AvatarInfo(); + it = _avatars.find(peer_id); + } + + time_t now = time(NULL); + if (now - it->second->_last_request_time > 60) { +#ifdef AVATAR_DEBUG + RsDbg() << "AVATAR p3ChatService::locked_requestAvatar: No avatar for peer " << peer_id << ". Requesting it (throttled)."; +#endif + it->second->_last_request_time = now; + sendAvatarRequest(peer_id); + } +} + void p3ChatService::getAvatarData(const RsPeerId& peer_id,unsigned char *& data,int& size) { { @@ -1525,24 +1546,60 @@ void p3ChatService::getAvatarData(const RsPeerId& peer_id,unsigned char *& data, #endif return ; } else { - /* Create placeholder to store request time */ - if (it == _avatars.end()) { - _avatars[peer_id] = new AvatarInfo(); - it = _avatars.find(peer_id); - } + data = NULL ; + size = 0 ; - time_t now = time(NULL); - if (now - it->second->_last_request_time > 60) { -#ifdef AVATAR_DEBUG - RsDbg() << "AVATAR p3ChatService::getAvatarData: No avatar for peer " << peer_id << ". Requesting it (throttled)."; -#endif - it->second->_last_request_time = now; - sendAvatarRequest(peer_id); - } + locked_requestAvatar(peer_id); } } } +bool p3ChatService::getAvatar(const RsPeerId& pid, RsGxsImage& avatar) +{ + RS_STACK_MUTEX(mChatMtx); + + avatar.clear(); + + std::map::const_iterator it = _avatars.find(pid) ; + + if(it != _avatars.end() && it->second->_image_size > 0) + { + unsigned char* data = NULL ; + uint32_t size = 0 ; + it->second->toUnsignedChar(data,size) ; + + /* AvatarInfo::toUnsignedChar allocates with rs_malloc, and RsGxsImage + * releases with free, so the buffer ownership can be handed over + * without an extra copy. */ + avatar.take(data,size); + + it->second->_peer_is_new = false ; + return true; + } + + /* Not available (yet): ask the peer for it, so that a later call may + * succeed. */ + locked_requestAvatar(pid); + return false; +} + +bool p3ChatService::getOwnAvatar(RsGxsImage& avatar) +{ + RS_STACK_MUTEX(mChatMtx); + + avatar.clear(); + + if(_own_avatar == NULL || _own_avatar->_image_size == 0) + return false; + + unsigned char* data = NULL ; + uint32_t size = 0 ; + _own_avatar->toUnsignedChar(data,size) ; + avatar.take(data,size); + + return true; +} + void p3ChatService::sendAvatarRequest(const RsPeerId& peer_id) { if(!isOnline(peer_id)) diff --git a/src/chat/p3chatservice.h b/src/chat/p3chatservice.h index ac0be8f50f..4e12add0b6 100644 --- a/src/chat/p3chatservice.h +++ b/src/chat/p3chatservice.h @@ -174,6 +174,12 @@ class p3ChatService : */ void getAvatarData(const RsPeerId& peer_id,unsigned char *& data,int& size) override; + /// @see RsChats + bool getAvatar(const RsPeerId& pid, RsGxsImage& avatar) override; + + /// @see RsChats + bool getOwnAvatar(RsGxsImage& avatar) override; + /*! * Sets the avatar data and size for client's account * @param data is copied, so should be destroyed by the caller @@ -276,6 +282,11 @@ class p3ChatService : /// Sends a request for an avatar to the peer of given id void sendAvatarRequest(const RsPeerId& peer_id) ; + /*! Create the avatar bookkeeping entry for the given peer if needed, then + * ask the peer for its avatar, at most once per minute. + * The caller MUST hold mChatMtx before calling this. */ + void locked_requestAvatar(const RsPeerId& peer_id) ; + /// Send a request for custom status string void sendCustomStateRequest(const RsPeerId& peer_id); diff --git a/src/retroshare/rschats.h b/src/retroshare/rschats.h index f15efc5133..109c2f2195 100644 --- a/src/retroshare/rschats.h +++ b/src/retroshare/rschats.h @@ -25,6 +25,7 @@ #include "retroshare/rstypes.h" #include "retroshare/rsevents.h" +#include "retroshare/rsgxscommon.h" #define RS_CHAT_LOBBY_EVENT_PEER_LEFT 0x01 #define RS_CHAT_LOBBY_EVENT_PEER_STATUS 0x02 @@ -464,6 +465,25 @@ class RsChats virtual void setOwnNodeAvatarData(const unsigned char *data,int size) = 0 ; virtual void getOwnNodeAvatarData(unsigned char *& data,int& size) = 0 ; + /** + * @brief getAvatar get the avatar of the given peer, in JPEG format + * @jsonapi{development} + * When the avatar of the peer is not known yet, this returns false and + * asks the peer to send it, so calling this again a bit later may succeed. + * @param[in] pid peer id + * @param[out] avatar peer avatar, left empty when not available + * @return true if an avatar was available, false otherwise + */ + virtual bool getAvatar(const RsPeerId& pid, RsGxsImage& avatar) = 0; + + /** + * @brief getOwnAvatar get the avatar of our own node, in JPEG format + * @jsonapi{development} + * @param[out] avatar own avatar, left empty when none has been set + * @return true if an avatar was set, false otherwise + */ + virtual bool getOwnAvatar(RsGxsImage& avatar) = 0; + /****************************************/ /* Chat lobbies */ /****************************************/