Experiment of notification via NotifyClient + JSON API

This commit is contained in:
Gioacchino Mazzurco 2018-06-29 16:03:09 +02:00
parent 130007b578
commit 1bc518041c
No known key found for this signature in database
GPG Key ID: A1FBCA3872E87051
5 changed files with 142 additions and 50 deletions

View File

@ -18,19 +18,40 @@
#include "jsonapi.h" #include "jsonapi.h"
#include <rapid_json/document.h>
#include <rapid_json/writer.h>
#include <rapid_json/stringbuffer.h>
// Generated at compile time // Generated at compile time
#include "jsonapi-wrappers.h" #include "jsonapi-wrappers.h"
JsonApiServer::JsonApiServer( JsonApiServer::JsonApiServer(
uint16_t port, const std::function<void(int)> shutdownCallback) : uint16_t port, const std::function<void(int)> shutdownCallback) :
mPort(port), mShutdownCallback(shutdownCallback) mPort(port), mShutdownCallback(shutdownCallback), notifyClientWrapper(*this)
{ {
registerHandler("/jsonApiServer/shutdown", registerHandler("/jsonApiServer/shutdown",
[this](const std::shared_ptr<restbed::Session>) [this](const std::shared_ptr<rb::Session>)
{ {
shutdown(); shutdown();
}); });
registerHandler("/jsonApiServer/notifications",
[this](const std::shared_ptr<rb::Session> session)
{
const auto headers = std::multimap<std::string, std::string>
{
{ "Connection", "keep-alive" },
{ "Cache-Control", "no-cache" },
{ "Content-Type", "text/event-stream" },
};
session->yield(rb::OK, headers,
[this](const std::shared_ptr<rb::Session> session)
{
notifySessions.push_back(session);
} );
} );
// Generated at compile time // Generated at compile time
#include "jsonapi-register.inl" #include "jsonapi-register.inl"
} }
@ -59,3 +80,47 @@ void JsonApiServer::shutdown(int exitCode)
mService.stop(); mService.stop();
mShutdownCallback(exitCode); mShutdownCallback(exitCode);
} }
void JsonApiServer::cleanClosedNotifySessions()
{
notifySessions.erase(
std::remove_if(
notifySessions.begin(), notifySessions.end(),
[](const std::shared_ptr<rb::Session> &s)
{ return s->is_closed(); } ), notifySessions.end());
}
JsonApiServer::NotifyClientWrapper::NotifyClientWrapper(JsonApiServer& parent) :
NotifyClient(), mJsonApiServer(parent)
{
rsNotify->registerNotifyClient(static_cast<NotifyClient*>(this));
}
void JsonApiServer::NotifyClientWrapper::notifyTurtleSearchResult(
uint32_t searchId, const std::list<TurtleFileInfo>& files )
{
mJsonApiServer.cleanClosedNotifySessions();
RsGenericSerializer::SerializeContext cAns;
RsJson& jAns(cAns.mJson);
// serialize parameters and method name to JSON
{
std::string methodName("NotifyClient/notifyTurtleSearchResult");
std::list<TurtleFileInfo> filesCopy(files);
RsGenericSerializer::SerializeContext& ctx(cAns);
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
RS_SERIAL_PROCESS(methodName);
RS_SERIAL_PROCESS(searchId);
// RS_SERIAL_PROCESS(filesCopy);
}
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
jAns.Accept(writer);
std::string message(buffer.GetString(), buffer.GetSize());
message.insert(0, "data: "); message.append("\n\n");
for(auto session : mJsonApiServer.notifySessions)
session->yield(message);
}

View File

@ -19,16 +19,12 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <restbed> #include <restbed>
#include <rapid_json/document.h>
#include "retroshare/rsgxschannels.h"
#include "serialiser/rstypeserializer.h"
#include "util/rsthreads.h" #include "util/rsthreads.h"
#include "retroshare/rsnotify.h"
namespace rb = restbed; namespace rb = restbed;
void apiVersionHandler(const std::shared_ptr<rb::Session> session);
void createChannelHandler(const std::shared_ptr<rb::Session> session);
/** /**
* Simple usage * Simple usage
@ -74,5 +70,20 @@ private:
uint16_t mPort; uint16_t mPort;
rb::Service mService; rb::Service mService;
const std::function<void(int)> mShutdownCallback; const std::function<void(int)> mShutdownCallback;
std::list<std::shared_ptr<rb::Session> > notifySessions;
void cleanClosedNotifySessions();
struct NotifyClientWrapper : NotifyClient
{
NotifyClientWrapper(JsonApiServer& parent);
void notifyTurtleSearchResult(
uint32_t searchId, const std::list<TurtleFileInfo>& files);
private:
JsonApiServer& mJsonApiServer;
};
NotifyClientWrapper notifyClientWrapper;
}; };

View File

@ -181,7 +181,7 @@ class RsFeedItem
// This mechanism can be used in plugins, new services, etc. // This mechanism can be used in plugins, new services, etc.
// //
class NotifyClient ; struct NotifyClient;
class RsNotify class RsNotify
{ {
@ -206,9 +206,8 @@ class RsNotify
virtual bool setDisableAskPassword (const bool /*bValue*/) { return false ; } virtual bool setDisableAskPassword (const bool /*bValue*/) { return false ; }
}; };
class NotifyClient struct NotifyClient
{ {
public:
NotifyClient() {} NotifyClient() {}
virtual ~NotifyClient() {} virtual ~NotifyClient() {}
@ -244,6 +243,5 @@ class NotifyClient
virtual bool askForPassword (const std::string& /* title */, const std::string& /* key_details */, bool /* prev_is_bad */, std::string& /* password */,bool& /* cancelled */ ) { return false ;} virtual bool askForPassword (const std::string& /* title */, const std::string& /* key_details */, bool /* prev_is_bad */, std::string& /* password */,bool& /* cancelled */ ) { return false ;}
virtual bool askForPluginConfirmation (const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */,bool /* first_time */) { return false ;} virtual bool askForPluginConfirmation (const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */,bool /* first_time */) { return false ;}
}; };
#endif #endif

View File

@ -29,11 +29,17 @@
#include "serialiser/rstlvbinary.h" #include "serialiser/rstlvbinary.h"
#include "retroshare/rstypes.h" #include "retroshare/rstypes.h"
#include "retroshare/rsgxsifacetypes.h" #include "retroshare/rsgxsifacetypes.h"
#include "serialiser/rsserializable.h"
namespace RsRegularExpression { class LinearizedExpression ; } namespace RsRegularExpression { class LinearizedExpression ; }
class RsTurtleClientService ; class RsTurtleClientService ;
class RsTurtle; class RsTurtle;
/**
* Pointer to global instance of RsTurtle service implementation
* @jsonapi{development}
*/
extern RsTurtle* rsTurtle; extern RsTurtle* rsTurtle;
typedef uint32_t TurtleRequestId ; typedef uint32_t TurtleRequestId ;
@ -42,11 +48,20 @@ typedef RsPeerId TurtleVirtualPeerId;
// This is the structure used to send back results of the turtle search // This is the structure used to send back results of the turtle search
// to the notifyBase class, or send info to the GUI. // to the notifyBase class, or send info to the GUI.
struct TurtleFileInfo struct TurtleFileInfo //: RsSerializable
{ {
RsFileHash hash; RsFileHash hash;
std::string name; std::string name;
uint64_t size; uint64_t size;
/*
/// @see RsSerializable::serial_process
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
RS_SERIAL_PROCESS(hash);
RS_SERIAL_PROCESS(name);
RS_SERIAL_PROCESS(size);
}*/
}; };
struct TurtleTunnelRequestDisplayInfo struct TurtleTunnelRequestDisplayInfo
@ -106,7 +121,9 @@ class RsTurtle
// the request id, which will be further used by the gui to store results // the request id, which will be further used by the gui to store results
// as they come back. // as they come back.
// //
virtual TurtleRequestId turtleSearch(unsigned char *search_bin_data,uint32_t search_bin_data_len,RsTurtleClientService *client_service) =0; virtual TurtleRequestId turtleSearch(
unsigned char *search_bin_data, uint32_t search_bin_data_len,
RsTurtleClientService* client_service ) = 0;
// Initiates tunnel handling for the given file hash. tunnels. Launches // Initiates tunnel handling for the given file hash. tunnels. Launches
// an exception if an error occurs during the initialization process. The // an exception if an error occurs during the initialization process. The

View File

@ -247,6 +247,7 @@ bool getRawString(const void *data, uint32_t size, uint32_t *offset, std::string
if(len > size || size-len < *offset) // better than if(size < *offset + len) because it avoids integer overflow if(len > size || size-len < *offset) // better than if(size < *offset + len) because it avoids integer overflow
{ {
std::cerr << "getRawString() not enough size" << std::endl; std::cerr << "getRawString() not enough size" << std::endl;
print_stacktrace();
return false; return false;
} }
uint8_t *buf = &(((uint8_t *) data)[*offset]); uint8_t *buf = &(((uint8_t *) data)[*offset]);