session.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. // Copyright 2019 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifndef dap_session_h
  15. #define dap_session_h
  16. #include "future.h"
  17. #include "io.h"
  18. #include "traits.h"
  19. #include "typeinfo.h"
  20. #include "typeof.h"
  21. #include <functional>
  22. namespace dap {
  23. // Forward declarations
  24. struct Request;
  25. struct Response;
  26. struct Event;
  27. ////////////////////////////////////////////////////////////////////////////////
  28. // Error
  29. ////////////////////////////////////////////////////////////////////////////////
  30. // Error represents an error message in response to a DAP request.
  31. struct Error {
  32. Error() = default;
  33. Error(const std::string& error);
  34. Error(const char* msg, ...);
  35. // operator bool() returns true if there is an error.
  36. inline operator bool() const { return message.size() > 0; }
  37. std::string message; // empty represents success.
  38. };
  39. ////////////////////////////////////////////////////////////////////////////////
  40. // ResponseOrError<T>
  41. ////////////////////////////////////////////////////////////////////////////////
  42. // ResponseOrError holds either the response to a DAP request or an error
  43. // message.
  44. template <typename T>
  45. struct ResponseOrError {
  46. using Request = T;
  47. inline ResponseOrError() = default;
  48. inline ResponseOrError(const T& response);
  49. inline ResponseOrError(T&& response);
  50. inline ResponseOrError(const Error& error);
  51. inline ResponseOrError(Error&& error);
  52. inline ResponseOrError(const ResponseOrError& other);
  53. inline ResponseOrError(ResponseOrError&& other);
  54. inline ResponseOrError& operator=(const ResponseOrError& other);
  55. inline ResponseOrError& operator=(ResponseOrError&& other);
  56. T response;
  57. Error error; // empty represents success.
  58. };
  59. template <typename T>
  60. ResponseOrError<T>::ResponseOrError(const T& resp) : response(resp) {}
  61. template <typename T>
  62. ResponseOrError<T>::ResponseOrError(T&& resp) : response(std::move(resp)) {}
  63. template <typename T>
  64. ResponseOrError<T>::ResponseOrError(const Error& err) : error(err) {}
  65. template <typename T>
  66. ResponseOrError<T>::ResponseOrError(Error&& err) : error(std::move(err)) {}
  67. template <typename T>
  68. ResponseOrError<T>::ResponseOrError(const ResponseOrError& other)
  69. : response(other.response), error(other.error) {}
  70. template <typename T>
  71. ResponseOrError<T>::ResponseOrError(ResponseOrError&& other)
  72. : response(std::move(other.response)), error(std::move(other.error)) {}
  73. template <typename T>
  74. ResponseOrError<T>& ResponseOrError<T>::operator=(
  75. const ResponseOrError& other) {
  76. response = other.response;
  77. error = other.error;
  78. return *this;
  79. }
  80. template <typename T>
  81. ResponseOrError<T>& ResponseOrError<T>::operator=(ResponseOrError&& other) {
  82. response = std::move(other.response);
  83. error = std::move(other.error);
  84. return *this;
  85. }
  86. ////////////////////////////////////////////////////////////////////////////////
  87. // Session
  88. ////////////////////////////////////////////////////////////////////////////////
  89. // An enum flag that controls how the Session handles invalid data.
  90. enum OnInvalidData {
  91. // Ignore invalid data.
  92. kIgnore,
  93. // Close the underlying reader when invalid data is received.
  94. kClose,
  95. };
  96. // Session implements a DAP client or server endpoint.
  97. // The general usage is as follows:
  98. // (1) Create a session with Session::create().
  99. // (2) Register request and event handlers with registerHandler().
  100. // (3) Optionally register a protocol error handler with onError().
  101. // (3) Bind the session to the remote endpoint with bind().
  102. // (4) Send requests or events with send().
  103. class Session {
  104. template <typename F, int N>
  105. using ParamType = traits::ParameterType<F, N>;
  106. template <typename T>
  107. using IsRequest = traits::EnableIfIsType<dap::Request, T>;
  108. template <typename T>
  109. using IsEvent = traits::EnableIfIsType<dap::Event, T>;
  110. template <typename F>
  111. using IsRequestHandlerWithoutCallback = traits::EnableIf<
  112. traits::CompatibleWith<F, std::function<void(dap::Request)>>::value>;
  113. template <typename F, typename CallbackType>
  114. using IsRequestHandlerWithCallback = traits::EnableIf<traits::CompatibleWith<
  115. F,
  116. std::function<void(dap::Request, std::function<void(CallbackType)>)>>::
  117. value>;
  118. public:
  119. virtual ~Session();
  120. // ErrorHandler is the type of callback function used for reporting protocol
  121. // errors.
  122. using ErrorHandler = std::function<void(const char*)>;
  123. // ClosedHandler is the type of callback function used to signal that a
  124. // connected endpoint has closed.
  125. using ClosedHandler = std::function<void()>;
  126. // create() constructs and returns a new Session.
  127. static std::unique_ptr<Session> create();
  128. // Sets how the Session handles invalid data.
  129. virtual void setOnInvalidData(OnInvalidData) = 0;
  130. // onError() registers a error handler that will be called whenever a protocol
  131. // error is encountered.
  132. // Only one error handler can be bound at any given time, and later calls
  133. // will replace the existing error handler.
  134. virtual void onError(const ErrorHandler&) = 0;
  135. // registerHandler() registers a request handler for a specific request type.
  136. // The function F must have one of the following signatures:
  137. // ResponseOrError<ResponseType>(const RequestType&)
  138. // ResponseType(const RequestType&)
  139. // Error(const RequestType&)
  140. template <typename F, typename RequestType = ParamType<F, 0>>
  141. inline IsRequestHandlerWithoutCallback<F> registerHandler(F&& handler);
  142. // registerHandler() registers a request handler for a specific request type.
  143. // The handler has a response callback function for the second argument of the
  144. // handler function. This callback may be called after the handler has
  145. // returned.
  146. // The function F must have the following signature:
  147. // void(const RequestType& request,
  148. // std::function<void(ResponseType)> response)
  149. template <typename F,
  150. typename RequestType = ParamType<F, 0>,
  151. typename ResponseType = typename RequestType::Response>
  152. inline IsRequestHandlerWithCallback<F, ResponseType> registerHandler(
  153. F&& handler);
  154. // registerHandler() registers a request handler for a specific request type.
  155. // The handler has a response callback function for the second argument of the
  156. // handler function. This callback may be called after the handler has
  157. // returned.
  158. // The function F must have the following signature:
  159. // void(const RequestType& request,
  160. // std::function<void(ResponseOrError<ResponseType>)> response)
  161. template <typename F,
  162. typename RequestType = ParamType<F, 0>,
  163. typename ResponseType = typename RequestType::Response>
  164. inline IsRequestHandlerWithCallback<F, ResponseOrError<ResponseType>>
  165. registerHandler(F&& handler);
  166. // registerHandler() registers a event handler for a specific event type.
  167. // The function F must have the following signature:
  168. // void(const EventType&)
  169. template <typename F, typename EventType = ParamType<F, 0>>
  170. inline IsEvent<EventType> registerHandler(F&& handler);
  171. // registerSentHandler() registers the function F to be called when a response
  172. // of the specific type has been sent.
  173. // The function F must have the following signature:
  174. // void(const ResponseOrError<ResponseType>&)
  175. template <typename F,
  176. typename ResponseType = typename ParamType<F, 0>::Request>
  177. inline void registerSentHandler(F&& handler);
  178. // send() sends the request to the connected endpoint and returns a
  179. // future that is assigned the request response or error.
  180. template <typename T, typename = IsRequest<T>>
  181. future<ResponseOrError<typename T::Response>> send(const T& request);
  182. // send() sends the event to the connected endpoint.
  183. template <typename T, typename = IsEvent<T>>
  184. void send(const T& event);
  185. // bind() connects this Session to an endpoint using connect(), and then
  186. // starts processing incoming messages with startProcessingMessages().
  187. // onClose is the optional callback which will be called when the session
  188. // endpoint has been closed.
  189. inline void bind(const std::shared_ptr<Reader>& reader,
  190. const std::shared_ptr<Writer>& writer,
  191. const ClosedHandler& onClose);
  192. inline void bind(const std::shared_ptr<ReaderWriter>& readerWriter,
  193. const ClosedHandler& onClose);
  194. //////////////////////////////////////////////////////////////////////////////
  195. // Note:
  196. // Methods and members below this point are for advanced usage, and are more
  197. // likely to change signature than the methods above.
  198. // The methods above this point should be sufficient for most use cases.
  199. //////////////////////////////////////////////////////////////////////////////
  200. // connect() connects this Session to an endpoint.
  201. // connect() can only be called once. Repeated calls will raise an error, but
  202. // otherwise will do nothing.
  203. // Note: This method is used for explicit control over message handling.
  204. // Most users will use bind() instead of calling this method directly.
  205. virtual void connect(const std::shared_ptr<Reader>&,
  206. const std::shared_ptr<Writer>&) = 0;
  207. inline void connect(const std::shared_ptr<ReaderWriter>&);
  208. // startProcessingMessages() starts a new thread to receive and dispatch
  209. // incoming messages.
  210. // onClose is the optional callback which will be called when the session
  211. // endpoint has been closed.
  212. // Note: This method is used for explicit control over message handling.
  213. // Most users will use bind() instead of calling this method directly.
  214. virtual void startProcessingMessages(const ClosedHandler& onClose = {}) = 0;
  215. // getPayload() blocks until the next incoming message is received, returning
  216. // the payload or an empty function if the connection was lost. The returned
  217. // payload is function that can be called on any thread to dispatch the
  218. // message to the Session handler.
  219. // Note: This method is used for explicit control over message handling.
  220. // Most users will use bind() instead of calling this method directly.
  221. virtual std::function<void()> getPayload() = 0;
  222. // The callback function type called when a request handler is invoked, and
  223. // the request returns a successful result.
  224. // 'responseTypeInfo' is the type information of the response data structure.
  225. // 'responseData' is a pointer to response payload data.
  226. using RequestHandlerSuccessCallback =
  227. std::function<void(const TypeInfo* responseTypeInfo,
  228. const void* responseData)>;
  229. // The callback function type used to notify when a DAP request fails.
  230. // 'responseTypeInfo' is the type information of the response data structure.
  231. // 'message' is the error message
  232. using RequestHandlerErrorCallback =
  233. std::function<void(const TypeInfo* responseTypeInfo,
  234. const Error& message)>;
  235. // The callback function type used to invoke a request handler.
  236. // 'request' is a pointer to the request data structure
  237. // 'onSuccess' is the function to call if the request completed succesfully.
  238. // 'onError' is the function to call if the request failed.
  239. // For each call of the request handler, 'onSuccess' or 'onError' must be
  240. // called exactly once.
  241. using GenericRequestHandler =
  242. std::function<void(const void* request,
  243. const RequestHandlerSuccessCallback& onSuccess,
  244. const RequestHandlerErrorCallback& onError)>;
  245. // The callback function type used to handle a response to a request.
  246. // 'response' is a pointer to the response data structure. May be nullptr.
  247. // 'error' is a pointer to the reponse error message. May be nullptr.
  248. // One of 'data' or 'error' will be nullptr.
  249. using GenericResponseHandler =
  250. std::function<void(const void* response, const Error* error)>;
  251. // The callback function type used to handle an event.
  252. // 'event' is a pointer to the event data structure.
  253. using GenericEventHandler = std::function<void(const void* event)>;
  254. // The callback function type used to notify when a response has been sent
  255. // from this session endpoint.
  256. // 'response' is a pointer to the response data structure.
  257. // 'error' is a pointer to the reponse error message. May be nullptr.
  258. using GenericResponseSentHandler =
  259. std::function<void(const void* response, const Error* error)>;
  260. // registerHandler() registers 'handler' as the request handler callback for
  261. // requests of the type 'typeinfo'.
  262. virtual void registerHandler(const TypeInfo* typeinfo,
  263. const GenericRequestHandler& handler) = 0;
  264. // registerHandler() registers 'handler' as the event handler callback for
  265. // events of the type 'typeinfo'.
  266. virtual void registerHandler(const TypeInfo* typeinfo,
  267. const GenericEventHandler& handler) = 0;
  268. // registerHandler() registers 'handler' as the response-sent handler function
  269. // which is called whenever a response of the type 'typeinfo' is sent from
  270. // this session endpoint.
  271. virtual void registerHandler(const TypeInfo* typeinfo,
  272. const GenericResponseSentHandler& handler) = 0;
  273. // send() sends a request to the remote endpoint.
  274. // 'requestTypeInfo' is the type info of the request data structure.
  275. // 'requestTypeInfo' is the type info of the response data structure.
  276. // 'request' is a pointer to the request data structure.
  277. // 'responseHandler' is the handler function for the response.
  278. virtual bool send(const dap::TypeInfo* requestTypeInfo,
  279. const dap::TypeInfo* responseTypeInfo,
  280. const void* request,
  281. const GenericResponseHandler& responseHandler) = 0;
  282. // send() sends an event to the remote endpoint.
  283. // 'eventTypeInfo' is the type info for the event data structure.
  284. // 'event' is a pointer to the event data structure.
  285. virtual bool send(const TypeInfo* eventTypeInfo, const void* event) = 0;
  286. };
  287. template <typename F, typename RequestType>
  288. Session::IsRequestHandlerWithoutCallback<F> Session::registerHandler(
  289. F&& handler) {
  290. using ResponseType = typename RequestType::Response;
  291. const TypeInfo* typeinfo = TypeOf<RequestType>::type();
  292. registerHandler(typeinfo,
  293. [handler](const void* args,
  294. const RequestHandlerSuccessCallback& onSuccess,
  295. const RequestHandlerErrorCallback& onError) {
  296. ResponseOrError<ResponseType> res =
  297. handler(*reinterpret_cast<const RequestType*>(args));
  298. if (res.error) {
  299. onError(TypeOf<ResponseType>::type(), res.error);
  300. } else {
  301. onSuccess(TypeOf<ResponseType>::type(), &res.response);
  302. }
  303. });
  304. }
  305. template <typename F, typename RequestType, typename ResponseType>
  306. Session::IsRequestHandlerWithCallback<F, ResponseType> Session::registerHandler(
  307. F&& handler) {
  308. using CallbackType = ParamType<F, 1>;
  309. registerHandler(
  310. TypeOf<RequestType>::type(),
  311. [handler](const void* args,
  312. const RequestHandlerSuccessCallback& onSuccess,
  313. const RequestHandlerErrorCallback&) {
  314. CallbackType responseCallback = [onSuccess](const ResponseType& res) {
  315. onSuccess(TypeOf<ResponseType>::type(), &res);
  316. };
  317. handler(*reinterpret_cast<const RequestType*>(args), responseCallback);
  318. });
  319. }
  320. template <typename F, typename RequestType, typename ResponseType>
  321. Session::IsRequestHandlerWithCallback<F, ResponseOrError<ResponseType>>
  322. Session::registerHandler(F&& handler) {
  323. using CallbackType = ParamType<F, 1>;
  324. registerHandler(
  325. TypeOf<RequestType>::type(),
  326. [handler](const void* args,
  327. const RequestHandlerSuccessCallback& onSuccess,
  328. const RequestHandlerErrorCallback& onError) {
  329. CallbackType responseCallback =
  330. [onError, onSuccess](const ResponseOrError<ResponseType>& res) {
  331. if (res.error) {
  332. onError(TypeOf<ResponseType>::type(), res.error);
  333. } else {
  334. onSuccess(TypeOf<ResponseType>::type(), &res.response);
  335. }
  336. };
  337. handler(*reinterpret_cast<const RequestType*>(args), responseCallback);
  338. });
  339. }
  340. template <typename F, typename T>
  341. Session::IsEvent<T> Session::registerHandler(F&& handler) {
  342. auto cb = [handler](const void* args) {
  343. handler(*reinterpret_cast<const T*>(args));
  344. };
  345. const TypeInfo* typeinfo = TypeOf<T>::type();
  346. registerHandler(typeinfo, cb);
  347. }
  348. template <typename F, typename T>
  349. void Session::registerSentHandler(F&& handler) {
  350. auto cb = [handler](const void* response, const Error* error) {
  351. if (error != nullptr) {
  352. handler(ResponseOrError<T>(*error));
  353. } else {
  354. handler(ResponseOrError<T>(*reinterpret_cast<const T*>(response)));
  355. }
  356. };
  357. const TypeInfo* typeinfo = TypeOf<T>::type();
  358. registerHandler(typeinfo, cb);
  359. }
  360. template <typename T, typename>
  361. future<ResponseOrError<typename T::Response>> Session::send(const T& request) {
  362. using Response = typename T::Response;
  363. promise<ResponseOrError<Response>> promise;
  364. auto sent = send(TypeOf<T>::type(), TypeOf<Response>::type(), &request,
  365. [=](const void* result, const Error* error) {
  366. if (error != nullptr) {
  367. promise.set_value(ResponseOrError<Response>(*error));
  368. } else {
  369. promise.set_value(ResponseOrError<Response>(
  370. *reinterpret_cast<const Response*>(result)));
  371. }
  372. });
  373. if (!sent) {
  374. promise.set_value(Error("Failed to send request"));
  375. }
  376. return promise.get_future();
  377. }
  378. template <typename T, typename>
  379. void Session::send(const T& event) {
  380. const TypeInfo* typeinfo = TypeOf<T>::type();
  381. send(typeinfo, &event);
  382. }
  383. void Session::connect(const std::shared_ptr<ReaderWriter>& rw) {
  384. connect(rw, rw);
  385. }
  386. void Session::bind(const std::shared_ptr<dap::Reader>& r,
  387. const std::shared_ptr<dap::Writer>& w,
  388. const ClosedHandler& onClose = {}) {
  389. connect(r, w);
  390. startProcessingMessages(onClose);
  391. }
  392. void Session::bind(const std::shared_ptr<ReaderWriter>& rw,
  393. const ClosedHandler& onClose = {}) {
  394. bind(rw, rw, onClose);
  395. }
  396. } // namespace dap
  397. #endif // dap_session_h