diff --git a/libretroshare/src/jsonapi/jsonapi.cpp b/libretroshare/src/jsonapi/jsonapi.cpp index 0f298ffc5..ee4ef1158 100644 --- a/libretroshare/src/jsonapi/jsonapi.cpp +++ b/libretroshare/src/jsonapi/jsonapi.cpp @@ -18,19 +18,40 @@ #include "jsonapi.h" +#include +#include +#include + // Generated at compile time #include "jsonapi-wrappers.h" JsonApiServer::JsonApiServer( uint16_t port, const std::function shutdownCallback) : - mPort(port), mShutdownCallback(shutdownCallback) + mPort(port), mShutdownCallback(shutdownCallback), notifyClientWrapper(*this) { registerHandler("/jsonApiServer/shutdown", - [this](const std::shared_ptr) + [this](const std::shared_ptr) { shutdown(); }); + registerHandler("/jsonApiServer/notifications", + [this](const std::shared_ptr session) + { + const auto headers = std::multimap + { + { "Connection", "keep-alive" }, + { "Cache-Control", "no-cache" }, + { "Content-Type", "text/event-stream" }, + }; + + session->yield(rb::OK, headers, + [this](const std::shared_ptr session) + { + notifySessions.push_back(session); + } ); + } ); + // Generated at compile time #include "jsonapi-register.inl" } @@ -59,3 +80,47 @@ void JsonApiServer::shutdown(int exitCode) mService.stop(); mShutdownCallback(exitCode); } + +void JsonApiServer::cleanClosedNotifySessions() +{ + notifySessions.erase( + std::remove_if( + notifySessions.begin(), notifySessions.end(), + [](const std::shared_ptr &s) + { return s->is_closed(); } ), notifySessions.end()); +} + +JsonApiServer::NotifyClientWrapper::NotifyClientWrapper(JsonApiServer& parent) : + NotifyClient(), mJsonApiServer(parent) +{ + rsNotify->registerNotifyClient(static_cast(this)); +} + +void JsonApiServer::NotifyClientWrapper::notifyTurtleSearchResult( + uint32_t searchId, const std::list& files ) +{ + mJsonApiServer.cleanClosedNotifySessions(); + + RsGenericSerializer::SerializeContext cAns; + RsJson& jAns(cAns.mJson); + + // serialize parameters and method name to JSON + { + std::string methodName("NotifyClient/notifyTurtleSearchResult"); + std::list 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 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); +} diff --git a/libretroshare/src/jsonapi/jsonapi.h b/libretroshare/src/jsonapi/jsonapi.h index 9c321c22a..bb3f78378 100644 --- a/libretroshare/src/jsonapi/jsonapi.h +++ b/libretroshare/src/jsonapi/jsonapi.h @@ -19,16 +19,12 @@ #include #include #include -#include -#include "retroshare/rsgxschannels.h" -#include "serialiser/rstypeserializer.h" #include "util/rsthreads.h" +#include "retroshare/rsnotify.h" namespace rb = restbed; -void apiVersionHandler(const std::shared_ptr session); -void createChannelHandler(const std::shared_ptr session); /** * Simple usage @@ -74,5 +70,20 @@ private: uint16_t mPort; rb::Service mService; const std::function mShutdownCallback; + + std::list > notifySessions; + void cleanClosedNotifySessions(); + + struct NotifyClientWrapper : NotifyClient + { + NotifyClientWrapper(JsonApiServer& parent); + + void notifyTurtleSearchResult( + uint32_t searchId, const std::list& files); + + private: + JsonApiServer& mJsonApiServer; + }; + NotifyClientWrapper notifyClientWrapper; }; diff --git a/libretroshare/src/retroshare/rsnotify.h b/libretroshare/src/retroshare/rsnotify.h index 6c916e034..bba4ff959 100644 --- a/libretroshare/src/retroshare/rsnotify.h +++ b/libretroshare/src/retroshare/rsnotify.h @@ -181,7 +181,7 @@ class RsFeedItem // This mechanism can be used in plugins, new services, etc. // -class NotifyClient ; +struct NotifyClient; class RsNotify { @@ -206,44 +206,42 @@ class RsNotify virtual bool setDisableAskPassword (const bool /*bValue*/) { return false ; } }; -class NotifyClient +struct NotifyClient { - public: - NotifyClient() {} - virtual ~NotifyClient() {} + NotifyClient() {} + virtual ~NotifyClient() {} - virtual void notifyListPreChange (int /* list */, int /* type */) {} - virtual void notifyListChange (int /* list */, int /* type */) {} - virtual void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) {} - virtual void notifyChatMessage (const ChatMessage& /* msg */) {} - virtual void notifyChatStatus (const ChatId& /* chat_id */, const std::string& /* status_string */) {} - virtual void notifyChatCleared (const ChatId& /* chat_id */) {} - virtual void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ ,const RsGxsId& /* nickname */,const std::string& /* any string */) {} - virtual void notifyChatLobbyTimeShift (int /* time_shift*/) {} - virtual void notifyCustomState (const std::string& /* peer_id */, const std::string& /* status_string */) {} - virtual void notifyHashingInfo (uint32_t /* type */, const std::string& /* fileinfo */) {} - virtual void notifyTurtleSearchResult (uint32_t /* search_id */, const std::list& /* files */) {} + virtual void notifyListPreChange (int /* list */, int /* type */) {} + virtual void notifyListChange (int /* list */, int /* type */) {} + virtual void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) {} + virtual void notifyChatMessage (const ChatMessage& /* msg */) {} + virtual void notifyChatStatus (const ChatId& /* chat_id */, const std::string& /* status_string */) {} + virtual void notifyChatCleared (const ChatId& /* chat_id */) {} + virtual void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ ,const RsGxsId& /* nickname */,const std::string& /* any string */) {} + virtual void notifyChatLobbyTimeShift (int /* time_shift*/) {} + virtual void notifyCustomState (const std::string& /* peer_id */, const std::string& /* status_string */) {} + virtual void notifyHashingInfo (uint32_t /* type */, const std::string& /* fileinfo */) {} + virtual void notifyTurtleSearchResult (uint32_t /* search_id */, const std::list& /* files */) {} #warning MISSING CODE HERE - // virtual void notifyTurtleSearchResult (uint32_t /* search_id */, const std::list& /* groups */) {} - virtual void notifyPeerHasNewAvatar (std::string /* peer_id */) {} - virtual void notifyOwnAvatarChanged () {} - virtual void notifyOwnStatusMessageChanged () {} - virtual void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) {} - virtual void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) {} - virtual void notifyGxsChange (const RsGxsChanges& /* changes */) {} - virtual void notifyConnectionWithoutCert () {} + // virtual void notifyTurtleSearchResult (uint32_t /* search_id */, const std::list& /* groups */) {} + virtual void notifyPeerHasNewAvatar (std::string /* peer_id */) {} + virtual void notifyOwnAvatarChanged () {} + virtual void notifyOwnStatusMessageChanged () {} + virtual void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) {} + virtual void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) {} + virtual void notifyGxsChange (const RsGxsChanges& /* changes */) {} + virtual void notifyConnectionWithoutCert () {} - /* one or more peers has changed the states */ - virtual void notifyPeerStatusChangedSummary () {} - virtual void notifyDiscInfoChanged () {} + /* one or more peers has changed the states */ + virtual void notifyPeerStatusChangedSummary () {} + virtual void notifyDiscInfoChanged () {} - virtual bool askForDeferredSelfSignature (const void * /* data */, const uint32_t /* len */, unsigned char * /* sign */, unsigned int * /* signlen */,int& signature_result , std::string /*reason = ""*/) { signature_result = false ;return true; } - virtual void notifyDownloadComplete (const std::string& /* fileHash */) {} - virtual void notifyDownloadCompleteCount (uint32_t /* count */) {} - virtual void notifyHistoryChanged (uint32_t /* msgId */, int /* type */) {} - - 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 askForDeferredSelfSignature (const void * /* data */, const uint32_t /* len */, unsigned char * /* sign */, unsigned int * /* signlen */,int& signature_result , std::string /*reason = ""*/) { signature_result = false ;return true; } + virtual void notifyDownloadComplete (const std::string& /* fileHash */) {} + virtual void notifyDownloadCompleteCount (uint32_t /* count */) {} + virtual void notifyHistoryChanged (uint32_t /* msgId */, int /* type */) {} + 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 ;} }; #endif diff --git a/libretroshare/src/retroshare/rsturtle.h b/libretroshare/src/retroshare/rsturtle.h index 91cc75adc..c183e454c 100644 --- a/libretroshare/src/retroshare/rsturtle.h +++ b/libretroshare/src/retroshare/rsturtle.h @@ -29,12 +29,18 @@ #include "serialiser/rstlvbinary.h" #include "retroshare/rstypes.h" #include "retroshare/rsgxsifacetypes.h" +#include "serialiser/rsserializable.h" namespace RsRegularExpression { class LinearizedExpression ; } class RsTurtleClientService ; class RsTurtle; -extern RsTurtle *rsTurtle ; + +/** + * Pointer to global instance of RsTurtle service implementation + * @jsonapi{development} + */ +extern RsTurtle* rsTurtle; typedef uint32_t TurtleRequestId ; typedef RsPeerId TurtleVirtualPeerId; @@ -42,11 +48,20 @@ typedef RsPeerId TurtleVirtualPeerId; // This is the structure used to send back results of the turtle search // to the notifyBase class, or send info to the GUI. -struct TurtleFileInfo +struct TurtleFileInfo //: RsSerializable { - RsFileHash hash ; - std::string name ; - uint64_t size ; + RsFileHash hash; + std::string name; + 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 @@ -90,7 +105,7 @@ class TurtleTrafficStatisticsInfo // class RsTurtle { - public: +public: RsTurtle() {} virtual ~RsTurtle() {} @@ -106,7 +121,9 @@ class RsTurtle // the request id, which will be further used by the gui to store results // 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 // an exception if an error occurs during the initialization process. The diff --git a/libretroshare/src/serialiser/rsbaseserial.cc b/libretroshare/src/serialiser/rsbaseserial.cc index a5b84518f..65528c801 100644 --- a/libretroshare/src/serialiser/rsbaseserial.cc +++ b/libretroshare/src/serialiser/rsbaseserial.cc @@ -244,9 +244,10 @@ bool getRawString(const void *data, uint32_t size, uint32_t *offset, std::string } /* check there is space for 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; } uint8_t *buf = &(((uint8_t *) data)[*offset]);