autobahn.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2014 Tavendo GmbH
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. ///////////////////////////////////////////////////////////////////////////////
  19. // This file was modified by Audiokinetic inc.
  20. ///////////////////////////////////////////////////////////////////////////////
  21. #ifndef AUTOBAHN_H
  22. #define AUTOBAHN_H
  23. #include <atomic>
  24. #include <condition_variable>
  25. #include <cstdint>
  26. #include <functional>
  27. #include <future>
  28. #include <istream>
  29. #include <map>
  30. #include <mutex>
  31. #include <ostream>
  32. #include <queue>
  33. #include <stdexcept>
  34. #include <string>
  35. #include <utility>
  36. #include <vector>
  37. #include "AK/WwiseAuthoringAPI/AkAutobahn/AkVariant.h"
  38. #include "AK/WwiseAuthoringAPI/AkAutobahn/AkJson.h"
  39. #include "AK/WwiseAuthoringAPI/AkAutobahn/JsonProvider.h"
  40. #include "AK/WwiseAuthoringAPI/AkAutobahn/IWebSocketClientHandler.h"
  41. #include "AK/WwiseAuthoringAPI/AkAutobahn/WebSocketClient.h"
  42. // thank you microsoft
  43. #ifdef ERROR
  44. #undef ERROR
  45. #endif
  46. namespace AK
  47. {
  48. namespace WwiseAuthoringAPI
  49. {
  50. typedef AkVariant any;
  51. /// A vector holding any values.
  52. typedef std::vector<AkVariant> anyvec;
  53. /// Handler type for use with session::subscribe(const std::string&, handler_t)
  54. typedef std::function<void(uint64_t, const JsonProvider&)> handler_t;
  55. /// Disconnect handler.
  56. typedef std::function<void()> disconnectHandler_t;
  57. struct result_t
  58. {
  59. result_t() : success(false) {}
  60. result_t(bool in_success) : success(in_success) {}
  61. result_t(bool in_success, const AkJson& in_data) : success(in_success), data(in_data) {}
  62. bool success;
  63. AkJson data;
  64. };
  65. /// Represents a topic subscription.
  66. struct subscription
  67. {
  68. subscription() : id(0), success(false) {}
  69. subscription(const AkJson& in_errorJson) : id(0), success(false), errorJson(in_errorJson) {}
  70. subscription(uint64_t in_id) : id(in_id), success(true) {};
  71. uint64_t id;
  72. bool success;
  73. AkJson errorJson;
  74. };
  75. /// Represents the authentication information sent on welcome
  76. struct authinfo
  77. {
  78. std::string authmethod;
  79. std::string authprovider;
  80. std::string authid;
  81. std::string authrole;
  82. };
  83. /*!
  84. * A WAMP session.
  85. */
  86. class session : public IWebSocketClientHandler
  87. {
  88. public:
  89. static void createErrorMessageJson(const std::string& in_message, AkJson& out_jsonError);
  90. private:
  91. static void createNoSessionErrorJson(AkJson& out_jsonError);
  92. public:
  93. session();
  94. ~session();
  95. /*!
  96. * Start listening on the IStream provided to the constructor
  97. * of this session.
  98. */
  99. bool start(const char* in_uri, unsigned int in_port, disconnectHandler_t disconnectHandler = nullptr);
  100. /*!
  101. * Closes the IStream and the OStream provided to the constructor
  102. * of this session.
  103. */
  104. void stop(const std::string& errorMessage);
  105. bool isConnected() const;
  106. uint64_t getSessionId() const { return m_session_id; }
  107. /*!
  108. * Join a realm with this session.
  109. *
  110. * \param realm The realm to join on the WAMP router connected to.
  111. * \param method The method used for login. Empty string will cause no login.
  112. * \param authid The authid to login with.
  113. * \param signature The signature to use when logging in. For method "ticket" the ticket, for method "wampcra" the
  114. * passphrase.
  115. * \return A future that resolves with the session ID when the realm was joined.
  116. */
  117. std::future<uint64_t> join(const std::string& realm, const std::string& method = "", const std::string& authid = "",
  118. const std::string& signature = "");
  119. authinfo getAuthInfo() const;
  120. bool subscribe(const std::string& topic, handler_t handler, const AkJson& options, std::future<subscription>& out_future, AkJson& out_jsonError);
  121. bool unsubscribe(uint64_t subscription_id, std::future<result_t>& out_future, AkJson& out_jsonError);
  122. bool call_options(
  123. const std::string& procedure,
  124. const anyvec& args,
  125. const AkJson& kwargs,
  126. const AkJson& options,
  127. std::future<result_t>& out_future,
  128. AkJson& out_jsonError);
  129. private:
  130. //////////////////////////////////////////////////////////////////////////////////////
  131. /// Caller
  132. /// An outstanding WAMP call.
  133. struct call_t
  134. {
  135. call_t() {}
  136. call_t(call_t&& c) : m_res(std::move(c.m_res)) {}
  137. std::promise<result_t> m_res;
  138. };
  139. /// Map of outstanding WAMP calls (request ID -> call).
  140. typedef std::map<uint64_t, call_t> calls_t;
  141. /// Map of WAMP call ID -> call
  142. calls_t m_calls;
  143. std::mutex m_callsMutex;
  144. //////////////////////////////////////////////////////////////////////////////////////
  145. /// Subscriber
  146. /// An outstanding WAMP subscribe request.
  147. struct subscribe_request_t
  148. {
  149. subscribe_request_t(){};
  150. subscribe_request_t(subscribe_request_t&& s) : m_handler(std::move(s.m_handler)), m_res(std::move(s.m_res)) {}
  151. subscribe_request_t(handler_t handler) : m_handler(handler){};
  152. handler_t m_handler;
  153. std::promise<subscription> m_res;
  154. };
  155. /// Map of outstanding WAMP subscribe requests (request ID -> subscribe request).
  156. typedef std::map<uint64_t, subscribe_request_t> subscribe_requests_t;
  157. /// Map of WAMP subscribe request ID -> subscribe request
  158. subscribe_requests_t m_subscribe_requests;
  159. std::mutex m_subreqMutex;
  160. /// Map of subscribed handlers (subscription ID -> handler)
  161. typedef std::map<uint64_t, handler_t> handlers_t;
  162. /// Map of WAMP subscription ID -> handler
  163. std::mutex m_handlersMutex;
  164. handlers_t m_handlers;
  165. /// Disconnect handler.
  166. disconnectHandler_t m_disconnectHandler;
  167. // No mutex required.
  168. //////////////////////////////////////////////////////////////////////////////////////
  169. /// Unsubscriber
  170. /// An outstanding WAMP unsubscribe request.
  171. struct unsubscribe_request_t
  172. {
  173. unsubscribe_request_t(){};
  174. unsubscribe_request_t(unsubscribe_request_t&& s) : m_res(std::move(s.m_res)) {}
  175. std::promise<result_t> m_res;
  176. };
  177. /// Map of outstanding WAMP subscribe requests (request ID -> subscribe request).
  178. typedef std::map<uint64_t, unsubscribe_request_t> unsubscribe_requests_t;
  179. /// Map of WAMP subscribe request ID -> subscribe request
  180. unsubscribe_requests_t m_unsubscribe_requests;
  181. std::mutex m_unsubreqMutex;
  182. //////////////////////////////////////////////////////////////////////////////////////
  183. /// Callee
  184. /// An unserialized, raw WAMP message.
  185. typedef AkJson wamp_msg_t;
  186. /// Process a WAMP WELCOME message.
  187. void process_welcome(const wamp_msg_t& msg);
  188. /// Process a WAMP CHALLENGE message.
  189. void process_challenge(const wamp_msg_t& msg);
  190. /// Process a WAMP ERROR message.
  191. void process_error(const wamp_msg_t& msg);
  192. /// Process a WAMP RESULT message.
  193. void process_call_result(const wamp_msg_t& msg);
  194. /// Process a WAMP SUBSCRIBED message.
  195. void process_subscribed(const wamp_msg_t& msg);
  196. /// Process a WAMP UNSUBSCRIBED message.
  197. void process_unsubscribed(const wamp_msg_t& msg);
  198. /// Process a WAMP EVENT message.
  199. void process_event(const wamp_msg_t& msg);
  200. /// Process a WAMP GOODBYE message.
  201. void process_goodbye(const wamp_msg_t& msg);
  202. /// Send wamp message. Asynchronous.
  203. void send(const AkJson& jsonPayload);
  204. void send(std::string ssout);
  205. /// Process incoming message.
  206. void got_msg(const std::string& jsonPayload);
  207. // IWebSocketClientHandler
  208. void OnMessage(std::string&& message);
  209. void OnConnectionLost();
  210. void sendThread();
  211. void logMessage(const char* logContent);
  212. #ifdef VALIDATE_WAMP
  213. void WampAssert(bool value, const char* message);
  214. #endif
  215. std::atomic<bool> m_running;
  216. std::atomic<bool> m_wasDisconnected;
  217. std::shared_ptr<WebSocketClient> m_websocket;
  218. std::recursive_mutex m_websocketMutex;
  219. std::thread m_sendThread;
  220. std::mutex m_sendQueueMutex;
  221. std::condition_variable m_sendEvent;
  222. std::queue<std::shared_ptr<std::vector<char>>> m_sendQueue;
  223. //Poco::JSON::Parser m_parser;
  224. /// WAMP session ID (if the session is joined to a realm).
  225. uint64_t m_session_id = 0;
  226. /// Future to be fired when session was joined.
  227. std::promise<uint64_t> m_session_join;
  228. /// Future to be fired when the send thread has started waiting
  229. std::promise<bool> m_send_thread_started;
  230. std::mutex m_joinMutex;
  231. /// Last request ID of outgoing WAMP requests.
  232. uint64_t m_request_id = 0;
  233. /// Signature to be used to authenticate
  234. std::string m_signature;
  235. /// Authentication information sent on welcome
  236. authinfo m_authinfo;
  237. bool m_goodbye_sent = false;
  238. /// WAMP message type codes.
  239. enum class msg_code : int
  240. {
  241. HELLO = 1,
  242. WELCOME = 2,
  243. ABORT = 3,
  244. CHALLENGE = 4,
  245. AUTHENTICATE = 5,
  246. GOODBYE = 6,
  247. HEARTBEAT = 7,
  248. ERROR = 8,
  249. PUBLISH = 16,
  250. PUBLISHED = 17,
  251. SUBSCRIBE = 32,
  252. SUBSCRIBED = 33,
  253. UNSUBSCRIBE = 34,
  254. UNSUBSCRIBED = 35,
  255. EVENT = 36,
  256. CALL = 48,
  257. CANCEL = 49,
  258. RESULT = 50,
  259. REGISTER = 64,
  260. // Renamed from original source to avoid clash with macro from Wwise SDK.
  261. // Keeping the others as-is to remain in sync with the original source as much as possible.
  262. WAMP_REGISTERED = 65,
  263. UNREGISTER = 66,
  264. UNREGISTERED = 67,
  265. INVOCATION = 68,
  266. INTERRUPT = 69,
  267. YIELD = 70
  268. };
  269. };
  270. }
  271. }
  272. #endif // AUTOBAHN_H