Expose libresapi for distant chat

Added macro to deprecate symbols usage in a crossplatform way.
Deprecated Request::mMethod and related stuff that make implementation
 more complex without advantage.
Added /chat/{initiate_distant_chat, distant_chat_status,
 close_distant_chat} to libresapi.
Solved subtle bug in ChatId::ChatId(std::string str) that caused zeroed
 DistantChatPeerId being created.
This commit is contained in:
Gio 2016-12-07 20:09:14 +01:00
parent f8de12d3d3
commit 9eef412b44
9 changed files with 179 additions and 82 deletions

View file

@ -6,6 +6,8 @@
#include <stdint.h> #include <stdint.h>
#include <ostream> #include <ostream>
#include "util/rsdeprecate.h"
namespace resource_api namespace resource_api
{ {
// things to clean up: // things to clean up:
@ -181,18 +183,20 @@ private:
class Request class Request
{ {
public: public:
Request(StreamBase& stream): mStream(stream), mMethod(GET){} Request(StreamBase& stream) : mStream(stream), mMethod(GET){}
bool isGet(){ return mMethod == GET;} RS_DEPRECATED bool isGet(){ return mMethod == GET;}
bool isPut(){ return mMethod == PUT;} RS_DEPRECATED bool isPut(){ return mMethod == PUT;}
bool isDelete(){ return mMethod == DELETE_AA;} RS_DEPRECATED bool isDelete(){ return mMethod == DELETE_AA;}
bool isExec(){ return mMethod == EXEC;} RS_DEPRECATED bool isExec(){ return mMethod == EXEC;}
// path is the adress to the resource /**
// if the path has multiple parts which get handled by different handlers, * Path is the adress to the resource if the path has multiple parts which
// then each handler should pop the top element * get handled by different handlers, then each handler should pop the top
std::stack<std::string> mPath; * element
std::string mFullPath; */
std::stack<std::string> mPath;
std::string mFullPath;
bool setPath(const std::string &reqPath) bool setPath(const std::string &reqPath)
{ {
std::string str; std::string str;
@ -213,19 +217,16 @@ public:
return true; return true;
} }
// parameters should be used to influence the result /// Contains data for new resources
// for example include or exclude some information StreamBase& mStream;
// question: when to use parameters, and when to use the data field?
// it would be easier to have only one thing...
// UNUSED: was never implemented
//std::vector<std::pair<std::string, std::string> > mParameters;
// contains data for new resources /**
StreamBase& mStream; * @deprecated
* Method and derivated stuff usage is deprecated as it make implementation
// use the is*() methods to query the method type: * more complex and less readable without advantage
enum Method { GET, PUT, DELETE_AA, EXEC};// something is wrong with DELETE, it won't compile with it */
Method mMethod; enum Method { GET, PUT, DELETE_AA, EXEC};
RS_DEPRECATED Method mMethod;
}; };
// new notes on responses // new notes on responses

View file

@ -155,6 +155,9 @@ ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs,
addResourceHandler("receive_status", this, &ChatHandler::handleReceiveStatus); addResourceHandler("receive_status", this, &ChatHandler::handleReceiveStatus);
addResourceHandler("send_status", this, &ChatHandler::handleSendStatus); addResourceHandler("send_status", this, &ChatHandler::handleSendStatus);
addResourceHandler("unread_msgs", this, &ChatHandler::handleUnreadMsgs); addResourceHandler("unread_msgs", this, &ChatHandler::handleUnreadMsgs);
addResourceHandler("initiate_distant_chat", this, &ChatHandler::handleInitiateDistantChatConnexion);
addResourceHandler("distant_chat_status", this, &ChatHandler::handleDistantChatStatus);
addResourceHandler("close_distant_chat", this, &ChatHandler::handleCloseDistantChatConnexion);
} }
ChatHandler::~ChatHandler() ChatHandler::~ChatHandler()
@ -928,12 +931,14 @@ void ChatHandler::handleMessages(Request &req, Response &resp)
return; return;
} }
std::map<ChatId, std::list<Msg> >::iterator mit = mMsgs.find(id); std::map<ChatId, std::list<Msg> >::iterator mit = mMsgs.find(id);
if(mit == mMsgs.end()) if(mit == mMsgs.end())
{ {
resp.mStateToken = mMsgStateToken; // even set state token, if not found yet, maybe later messages arrive and then the chat id will be found /* set state token, even if not found yet, maybe later messages arrive
resp.setFail("chat with id=\""+req.mPath.top()+"\" not found"); * and then the chat id will be found */
return; resp.mStateToken = mMsgStateToken;
} resp.setFail("chat with id=\""+req.mPath.top()+"\" not found");
return;
}
resp.mStateToken = mMsgStateToken; resp.mStateToken = mMsgStateToken;
handlePaginationRequest(req, resp, mit->second); handlePaginationRequest(req, resp, mit->second);
} }
@ -954,7 +959,6 @@ void ChatHandler::handleSendMessage(Request &req, Response &resp)
resp.setOk(); resp.setOk();
else else
resp.setFail("failed to send message"); resp.setFail("failed to send message");
} }
void ChatHandler::handleMarkChatAsRead(Request &req, Response &resp) void ChatHandler::handleMarkChatAsRead(Request &req, Response &resp)
@ -1125,4 +1129,63 @@ void ChatHandler::handleUnreadMsgs(Request &/*req*/, Response &resp)
resp.mStateToken = mUnreadMsgsStateToken; resp.mStateToken = mUnreadMsgsStateToken;
} }
void ChatHandler::handleInitiateDistantChatConnexion(Request& req, Response& resp)
{
std::string own_gxs_hex, remote_gxs_hex;
req.mStream << makeKeyValueReference("own_gxs_hex", own_gxs_hex)
<< makeKeyValueReference("remote_gxs_hex", remote_gxs_hex);
RsGxsId sender_id(own_gxs_hex);
if(sender_id.isNull())
{
resp.setFail("own_gxs_hex is invalid");
return;
}
RsGxsId receiver_id(remote_gxs_hex);
if(receiver_id.isNull())
{
resp.setFail("remote_gxs_hex is invalid");
return;
}
DistantChatPeerId distant_chat_id;
uint32_t error_code;
if(mRsMsgs->initiateDistantChatConnexion(receiver_id, sender_id, distant_chat_id, error_code))
resp.setOk();
else resp.setFail("Failed to initiate distant chat");
ChatId chat_id(distant_chat_id);
resp.mDataStream << makeKeyValue("chat_id", chat_id.toStdString())
<< makeKeyValueReference("error_code", error_code);
}
void ChatHandler::handleDistantChatStatus(Request& req, Response& resp)
{
std::string distant_chat_hex;
req.mStream << makeKeyValueReference("chat_id", distant_chat_hex);
ChatId id(distant_chat_hex);
DistantChatPeerInfo info;
if(mRsMsgs->getDistantChatStatus(id.toDistantChatId(), info)) resp.setOk();
else resp.setFail("Failed to get status for distant chat");
resp.mDataStream << makeKeyValue("own_gxs_hex", info.own_id.toStdString())
<< makeKeyValue("remote_gxs_hex", info.to_id.toStdString())
<< makeKeyValue("chat_id", info.peer_id.toStdString())
<< makeKeyValue("status", info.status);
}
void ChatHandler::handleCloseDistantChatConnexion(Request& req, Response& resp)
{
std::string distant_chat_hex;
req.mStream << makeKeyValueReference("distant_chat_hex", distant_chat_hex);
DistantChatPeerId chat_id(distant_chat_hex);
if (mRsMsgs->closeDistantChatConnexion(chat_id)) resp.setOk();
else resp.setFail("Failed to close distant chat");
}
} // namespace resource_api } // namespace resource_api

View file

@ -11,9 +11,10 @@ class RsIdentity;
namespace resource_api namespace resource_api
{ {
class UnreadMsgNotify{ class UnreadMsgNotify
{
public: public:
virtual void notifyUnreadMsgCountChanged(const RsPeerId& peer, uint32_t count) = 0; virtual void notifyUnreadMsgCountChanged(const RsPeerId& peer, uint32_t count) = 0;
}; };
class ChatHandler: public ResourceRouter, NotifyClient, Tickable class ChatHandler: public ResourceRouter, NotifyClient, Tickable
@ -128,6 +129,9 @@ private:
ResponseTask *handleReceiveStatus(Request& req, Response& resp); ResponseTask *handleReceiveStatus(Request& req, Response& resp);
void handleSendStatus(Request& req, Response& resp); void handleSendStatus(Request& req, Response& resp);
void handleUnreadMsgs(Request& req, Response& resp); void handleUnreadMsgs(Request& req, Response& resp);
void handleInitiateDistantChatConnexion(Request& req, Response& resp);
void handleDistantChatStatus(Request& req, Response& resp);
void handleCloseDistantChatConnexion(Request& req, Response& resp);
void getPlainText(const std::string& in, std::string &out, std::vector<Triple> &links); void getPlainText(const std::string& in, std::string &out, std::vector<Triple> &links);
// last parameter is only used for lobbies! // last parameter is only used for lobbies!

View file

@ -275,31 +275,30 @@ bool DistantChatService::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,
bool DistantChatService::getDistantChatStatus(const DistantChatPeerId& tunnel_id, DistantChatPeerInfo& cinfo) bool DistantChatService::getDistantChatStatus(const DistantChatPeerId& tunnel_id, DistantChatPeerInfo& cinfo)
{ {
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/ RS_STACK_MUTEX(mDistantChatMtx);
RsGxsTunnelService::GxsTunnelInfo tinfo ; RsGxsTunnelService::GxsTunnelInfo tinfo;
if(!mGxsTunnels->getTunnelInfo(RsGxsTunnelId(tunnel_id),tinfo)) if(!mGxsTunnels->getTunnelInfo(RsGxsTunnelId(tunnel_id),tinfo)) return false;
return false;
cinfo.to_id = tinfo.destination_gxs_id; cinfo.to_id = tinfo.destination_gxs_id;
cinfo.own_id = tinfo.source_gxs_id; cinfo.own_id = tinfo.source_gxs_id;
cinfo.peer_id = tunnel_id; cinfo.peer_id = tunnel_id;
switch(tinfo.tunnel_status) switch(tinfo.tunnel_status)
{ {
case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_CAN_TALK : cinfo.status = RS_DISTANT_CHAT_STATUS_CAN_TALK; case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_CAN_TALK :
break ; cinfo.status = RS_DISTANT_CHAT_STATUS_CAN_TALK; break;
case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_TUNNEL_DN: cinfo.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN ; case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_TUNNEL_DN:
break ; cinfo.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN; break;
case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED: cinfo.status = RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED ; case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED:
break ; cinfo.status = RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED; break;
default: case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_UNKNOWN:
case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_UNKNOWN: cinfo.status = RS_DISTANT_CHAT_STATUS_UNKNOWN; default:
break ; cinfo.status = RS_DISTANT_CHAT_STATUS_UNKNOWN; break;
} }
return true ; return true;
} }
bool DistantChatService::closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) bool DistantChatService::closeDistantChatConnexion(const DistantChatPeerId &tunnel_id)

View file

@ -292,14 +292,11 @@ void p3ChatService::checkSizeAndSendMessage(RsChatMsgItem *msg)
bool p3ChatService::isOnline(const RsPeerId& pid) bool p3ChatService::isOnline(const RsPeerId& pid)
{ {
// check if the id is a tunnel id or a peer id. // check if the id is a tunnel id or a peer id.
DistantChatPeerInfo dcpinfo;
DistantChatPeerInfo dcpinfo; if(getDistantChatStatus(DistantChatPeerId(pid),dcpinfo))
return dcpinfo.status == RS_DISTANT_CHAT_STATUS_CAN_TALK;
if(getDistantChatStatus(DistantChatPeerId(pid),dcpinfo)) else return mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid);
return dcpinfo.status == RS_DISTANT_CHAT_STATUS_CAN_TALK ;
else
return mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid);
} }
bool p3ChatService::sendChat(ChatId destination, std::string msg) bool p3ChatService::sendChat(ChatId destination, std::string msg)
@ -318,8 +315,7 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
} }
// destination is peer or distant // destination is peer or distant
#ifdef CHAT_DEBUG #ifdef CHAT_DEBUG
std::cerr << "p3ChatService::sendChat()"; std::cerr << "p3ChatService::sendChat()" << std::endl;
std::cerr << std::endl;
#endif #endif
RsPeerId vpid; RsPeerId vpid;
@ -341,12 +337,12 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
message.online = true; message.online = true;
if(!isOnline(vpid)) if(!isOnline(vpid))
{ {
/* peer is offline, add to outgoing list */ /* peer is offline, add to outgoing list */
{ {
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ RS_STACK_MUTEX(mChatMtx);
privateOutgoingList.push_back(ci); privateOutgoingList.push_back(ci);
} }
message.online = false; message.online = false;
RsServer::notify()->notifyChatMessage(message); RsServer::notify()->notifyChatMessage(message);

View file

@ -1464,7 +1464,7 @@ RsGxsId p3GxsTunnelService::destinationGxsIdFromHash(const TurtleFileHash& sum)
bool p3GxsTunnelService::getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info) bool p3GxsTunnelService::getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info)
{ {
RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ RS_STACK_MUTEX(mGxsTunnelMtx);
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(tunnel_id) ;

View file

@ -527,7 +527,8 @@ HEADERS += util/folderiterator.h \
util/rstickevent.h \ util/rstickevent.h \
util/rsrecogn.h \ util/rsrecogn.h \
util/rsscopetimer.h \ util/rsscopetimer.h \
util/stacktrace.h util/stacktrace.h \
util/rsdeprecate.h
SOURCES += ft/ftchunkmap.cc \ SOURCES += ft/ftchunkmap.cc \
ft/ftcontroller.cc \ ft/ftcontroller.cc \

View file

@ -79,22 +79,21 @@ ChatId::ChatId(ChatLobbyId id):
lobby_id = id; lobby_id = id;
} }
ChatId::ChatId(std::string str): ChatId::ChatId(std::string str) : lobby_id(0)
lobby_id(0)
{ {
type = TYPE_NOT_SET; type = TYPE_NOT_SET;
if(str.empty()) if(str.empty()) return;
return;
if(str[0] == 'P') if(str[0] == 'P')
{ {
type = TYPE_PRIVATE; type = TYPE_PRIVATE;
peer_id = RsPeerId(str.substr(1)); peer_id = RsPeerId(str.substr(1));
} }
else if(str[0] == 'D') else if(str[0] == 'D')
{ {
type = TYPE_PRIVATE_DISTANT; type = TYPE_PRIVATE_DISTANT;
distant_chat_id == DistantChatPeerId(str.substr(1)); distant_chat_id = DistantChatPeerId(str.substr(1));
} }
else if(str[0] == 'L') else if(str[0] == 'L')
{ {
if(sizeof(ChatLobbyId) != 8) if(sizeof(ChatLobbyId) != 8)
@ -401,7 +400,7 @@ bool p3Msgs::resetMessageStandardTagTypes(MsgTagType& tags)
/****************************************/ /****************************************/
bool p3Msgs::sendChat(ChatId destination, std::string msg) bool p3Msgs::sendChat(ChatId destination, std::string msg)
{ {
return mChatSrv->sendChat(destination, msg); return mChatSrv->sendChat(destination, msg);
} }
uint32_t p3Msgs::getMaxMessageSecuritySize(int type) uint32_t p3Msgs::getMaxMessageSecuritySize(int type)

View file

@ -0,0 +1,34 @@
#pragma once
/*
* RetroShare deprecation macros
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
# define RS_DEPRECATED __attribute__((__deprecated__))
#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
# define RS_DEPRECATED __declspec(deprecated)
#else
# define RS_DEPRECATED
#endif
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
# define RS_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead")))
#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320)
# define RS_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead"))
#else
# define RS_DEPRECATED_FOR(f) RS_DEPRECATED
#endif