From 5fd772b30210b36fa11d7ffe47dc6bf9c6ce7351 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sun, 15 May 2022 00:50:39 +0200 Subject: [PATCH] Improve BitcoinityReader. It sends a pong message back, but I'm not sure it's having an effect --- src/bitcoinity_payload.hpp | 2 ++ src/bitcoinity_reader.cpp | 53 +++++++++++++++++++++++++++++++------- src/bitcoinity_reader.hpp | 13 +++++----- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/bitcoinity_payload.hpp b/src/bitcoinity_payload.hpp index eb934e8..70391b8 100644 --- a/src/bitcoinity_payload.hpp +++ b/src/bitcoinity_payload.hpp @@ -44,6 +44,8 @@ class BitcoinityPayload { public: static constexpr std::string_view JsonKeyPayload = "payload"; + BitcoinityPayload() = default; + BitcoinityPayload( simdjson::padded_string&& body_p, simdjson::ondemand::parser&& parser_p diff --git a/src/bitcoinity_reader.cpp b/src/bitcoinity_reader.cpp index a5e55fa..4366efd 100644 --- a/src/bitcoinity_reader.cpp +++ b/src/bitcoinity_reader.cpp @@ -37,6 +37,7 @@ namespace { } BitcoinityMessage to_bitcoinity_message (const std::string& message) { + typedef std::optional OptionalString; if (message.empty()) throw BitcoinityError("Unable to make a BitcoinityMessage from an empty message"); @@ -56,7 +57,8 @@ namespace { auto ref_result = doc[JsonKeyRef]; if (ref_result.error()) throw BitcoinityMissingKeyError({std::string(JsonKeyRef)}, message); - std::string_view ref = (ref_result.is_null() ? std::string_view{} : ref_result.value()); + OptionalString ref = + (ref_result.is_null() ? OptionalString{} : OptionalString{static_cast(ref_result.value())}); auto topic_result = doc[JsonKeyTopic]; if (topic_result.error()) @@ -66,11 +68,20 @@ namespace { return BitcoinityMessage{ BitcoinityPayload{std::move(body), std::move(parser)}, std::move(ref), - std::move(event), - std::move(topic) + std::string(event), + std::string(topic) }; } + BitcoinityMessage wait_for_event (WebsocketReader& ws, std::string_view event, int max_messages) { + do { + auto resp = to_bitcoinity_message(ws.read()); + if (resp.event == event) + return resp; + } while (--max_messages > 0); + return BitcoinityMessage{}; + } + void init_bitcoinity (WebsocketReader& ws, std::string_view exchange, std::string_view currency) { //thanks to blueagain from #javascript libera.chat for helping figuring //out the websocket address and the correct sequence of messages to @@ -81,9 +92,11 @@ namespace { //3) {"topic":"webs:markets_bitfinex_USD","event":"phx_join","payload":{},"ref":"3"} //See docs/bitcoinity/sample_communication.md for a real world example + constexpr int MaxDiscardedReplies = 5; + { ws.write(R"({"topic":"all","event":"phx_join","payload":{},"ref":"1"})"); - auto resp = to_bitcoinity_message(ws.read()); + auto resp = wait_for_event(ws, "phx_reply", MaxDiscardedReplies); if (resp.event != "phx_reply" or resp.payload.get_string_or_empty("status") != "ok" or not resp.ref or *resp.ref != "1") throw BitcoinityError("Server responded to message 1 \"" + std::string{resp.event} + "\" with status \"" + @@ -93,7 +106,7 @@ namespace { { ws.write(R"({"topic":"webs:markets","event":"phx_join","payload":{},"ref":"2"})"); - auto resp = to_bitcoinity_message(ws.read()); + auto resp = wait_for_event(ws, "phx_reply", MaxDiscardedReplies); if (resp.event != "phx_reply" or resp.payload.get_string_or_empty("status") != "ok" or not resp.ref or *resp.ref != "2") throw BitcoinityError("Server responded to message 2 \"" + std::string{resp.event} + "\" with status \"" + @@ -106,7 +119,7 @@ namespace { R"({"topic":"webs:markets_)" + std::string{exchange} + "_" + std::string{currency} + R"(","event":"phx_join","payload":{},"ref":"3"})" ); - auto resp = to_bitcoinity_message(ws.read()); + auto resp = wait_for_event(ws, "phx_reply", MaxDiscardedReplies); if (resp.event != "phx_reply" or resp.payload.get_string_or_empty("status") != "ok" or not resp.ref or *resp.ref != "3") throw BitcoinityError("Server responded to message 3 \"" + std::string{resp.event} + "\" with status \"" + @@ -146,9 +159,9 @@ const std::string& BitcoinityMissingKeyError::json() const noexcept { BitcoinityMessage::BitcoinityMessage ( BitcoinityPayload&& payload_p, - std::optional ref_p, - std::string_view event_p, - std::string_view topic_p + std::optional ref_p, + std::string event_p, + std::string topic_p ) : payload(std::move(payload_p)), ref(std::move(ref_p)), @@ -168,6 +181,26 @@ BitcoinityReader::BitcoinityReader(const std::string& user_agent, std::string_vi } BitcoinityMessage BitcoinityReader::read() { - return to_bitcoinity_message(WebsocketReader::read()); + do { + auto response = to_bitcoinity_message(WebsocketReader::read()); + if (response.event == "ping") { + //received something like + // {"event":"ping","payload":{"token":"wassup"},"ref":null,"topic":"all"} + std::string reply = R"({"event":"pong","payload":{"token":")"; + reply += response.payload.get_string_or_empty("token"); + reply += R"("},"ref":)"; + if (response.ref) + reply += "\"" + std::string{*response.ref} + "\""; + else + reply += "null"; + reply += R"(,"topic":")"; + reply += response.topic; + reply += R"("})"; + WebsocketReader::write(reply); + } + else { + return response; + } + } while(true); } } //namespace duck diff --git a/src/bitcoinity_reader.hpp b/src/bitcoinity_reader.hpp index 170cdee..1ff227c 100644 --- a/src/bitcoinity_reader.hpp +++ b/src/bitcoinity_reader.hpp @@ -43,17 +43,18 @@ private: }; struct BitcoinityMessage { + BitcoinityMessage() = default; BitcoinityMessage ( BitcoinityPayload&& payload_p, - std::optional ref_p, - std::string_view event_p, - std::string_view topic_p + std::optional ref_p, + std::string event_p, + std::string topic_p ); BitcoinityPayload payload; - std::optional ref; - std::string_view event; - std::string_view topic; + std::optional ref; + std::string event; + std::string topic; }; class BitcoinityReader : private WebsocketReader {