session.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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. // Session implements a DAP client or server endpoint.
  90. // The general usage is as follows:
  91. // (1) Create a session with Session::create().
  92. // (2) Register request and event handlers with registerHandler().
  93. // (3) Optionally register a protocol error handler with onError().
  94. // (3) Bind the session to the remote endpoint with bind().
  95. // (4) Send requests or events with send().
  96. class Session {
  97. template <typename F, int N>
  98. using ParamType = traits::ParameterType<F, N>;
  99. template <typename T>
  100. using IsRequest = traits::EnableIfIsType<dap::Request, T>;
  101. template <typename T>
  102. using IsEvent = traits::EnableIfIsType<dap::Event, T>;
  103. template <typename F>
  104. using IsRequestHandlerWithoutCallback = traits::EnableIf<
  105. traits::CompatibleWith<F, std::function<void(dap::Request)>>::value>;
  106. template <typename F, typename CallbackType>
  107. using IsRequestHandlerWithCallback = traits::EnableIf<traits::CompatibleWith<
  108. F,
  109. std::function<void(dap::Request, std::function<void(CallbackType)>)>>::
  110. value>;
  111. public:
  112. virtual ~Session();
  113. // ErrorHandler is the type of callback function used for reporting protocol
  114. // errors.
  115. using ErrorHandler = std::function<void(const char*)>;
  116. // ClosedHandler is the type of callback function used to signal that a
  117. // connected endpoint has closed.
  118. using ClosedHandler = std::function<void()>;
  119. // create() constructs and returns a new Session.
  120. static std::unique_ptr<Session> create();
  121. // onError() registers a error handler that will be called whenever a protocol
  122. // error is encountered.
  123. // Only one error handler can be bound at any given time, and later calls
  124. // will replace the existing error handler.
  125. virtual void onError(const ErrorHandler&) = 0;
  126. // registerHandler() registers a request handler for a specific request type.
  127. // The function F must have one of the following signatures:
  128. // ResponseOrError<ResponseType>(const RequestType&)
  129. // ResponseType(const RequestType&)
  130. // Error(const RequestType&)
  131. template <typename F, typename RequestType = ParamType<F, 0>>
  132. inline IsRequestHandlerWithoutCallback<F> registerHandler(F&& handler);
  133. // registerHandler() registers a request handler for a specific request type.
  134. // The handler has a response callback function for the second argument of the
  135. // handler function. This callback may be called after the handler has
  136. // returned.
  137. // The function F must have the following signature:
  138. // void(const RequestType& request,
  139. // std::function<void(ResponseType)> response)
  140. template <typename F,
  141. typename RequestType = ParamType<F, 0>,
  142. typename ResponseType = typename RequestType::Response>
  143. inline IsRequestHandlerWithCallback<F, ResponseType> registerHandler(
  144. F&& handler);
  145. // registerHandler() registers a request handler for a specific request type.
  146. // The handler has a response callback function for the second argument of the
  147. // handler function. This callback may be called after the handler has
  148. // returned.
  149. // The function F must have the following signature:
  150. // void(const RequestType& request,
  151. // std::function<void(ResponseOrError<ResponseType>)> response)
  152. template <typename F,
  153. typename RequestType = ParamType<F, 0>,
  154. typename ResponseType = typename RequestType::Response>
  155. inline IsRequestHandlerWithCallback<F, ResponseOrError<ResponseType>>
  156. registerHandler(F&& handler);
  157. // registerHandler() registers a event handler for a specific event type.
  158. // The function F must have the following signature:
  159. // void(const EventType&)
  160. template <typename F, typename EventType = ParamType<F, 0>>
  161. inline IsEvent<EventType> registerHandler(F&& handler);
  162. // registerSentHandler() registers the function F to be called when a response
  163. // of the specific type has been sent.
  164. // The function F must have the following signature:
  165. // void(const ResponseOrError<ResponseType>&)
  166. template <typename F,
  167. typename ResponseType = typename ParamType<F, 0>::Request>
  168. inline void registerSentHandler(F&& handler);
  169. // send() sends the request to the connected endpoint and returns a
  170. // future that is assigned the request response or error.
  171. template <typename T, typename = IsRequest<T>>
  172. future<ResponseOrError<typename T::Response>> send(const T& request);
  173. // send() sends the event to the connected endpoint.
  174. template <typename T, typename = IsEvent<T>>
  175. void send(const T& event);
  176. // bind() connects this Session to an endpoint using connect(), and then
  177. // starts processing incoming messages with startProcessingMessages().
  178. // onClose is the optional callback which will be called when the session
  179. // endpoint has been closed.
  180. inline void bind(const std::shared_ptr<Reader>& reader,
  181. const std::shared_ptr<Writer>& writer,
  182. const ClosedHandler& onClose);
  183. inline void bind(const std::shared_ptr<ReaderWriter>& readerWriter,
  184. const ClosedHandler& onClose);
  185. //////////////////////////////////////////////////////////////////////////////
  186. // Note:
  187. // Methods and members below this point are for advanced usage, and are more
  188. // likely to change signature than the methods above.
  189. // The methods above this point should be sufficient for most use cases.
  190. //////////////////////////////////////////////////////////////////////////////
  191. // connect() connects this Session to an endpoint.
  192. // connect() can only be called once. Repeated calls will raise an error, but
  193. // otherwise will do nothing.
  194. // Note: This method is used for explicit control over message handling.
  195. // Most users will use bind() instead of calling this method directly.
  196. virtual void connect(const std::shared_ptr<Reader>&,
  197. const std::shared_ptr<Writer>&) = 0;
  198. inline void connect(const std::shared_ptr<ReaderWriter>&);
  199. // startProcessingMessages() starts a new thread to receive and dispatch
  200. // incoming messages.
  201. // onClose is the optional callback which will be called when the session
  202. // endpoint has been closed.
  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 startProcessingMessages(const ClosedHandler& onClose = {}) = 0;
  206. // getPayload() blocks until the next incoming message is received, returning
  207. // the payload or an empty function if the connection was lost. The returned
  208. // payload is function that can be called on any thread to dispatch the
  209. // message to the Session handler.
  210. // Note: This method is used for explicit control over message handling.
  211. // Most users will use bind() instead of calling this method directly.
  212. virtual std::function<void()> getPayload() = 0;
  213. // The callback function type called when a request handler is invoked, and
  214. // the request returns a successful result.
  215. // 'responseTypeInfo' is the type information of the response data structure.
  216. // 'responseData' is a pointer to response payload data.
  217. using RequestHandlerSuccessCallback =
  218. std::function<void(const TypeInfo* responseTypeInfo,
  219. const void* responseData)>;
  220. // The callback function type used to notify when a DAP request fails.
  221. // 'responseTypeInfo' is the type information of the response data structure.
  222. // 'message' is the error message
  223. using RequestHandlerErrorCallback =
  224. std::function<void(const TypeInfo* responseTypeInfo,
  225. const Error& message)>;
  226. // The callback function type used to invoke a request handler.
  227. // 'request' is a pointer to the request data structure
  228. // 'onSuccess' is the function to call if the request completed succesfully.
  229. // 'onError' is the function to call if the request failed.
  230. // For each call of the request handler, 'onSuccess' or 'onError' must be
  231. // called exactly once.
  232. using GenericRequestHandler =
  233. std::function<void(const void* request,
  234. const RequestHandlerSuccessCallback& onSuccess,
  235. const RequestHandlerErrorCallback& onError)>;
  236. // The callback function type used to handle a response to a request.
  237. // 'response' is a pointer to the response data structure. May be nullptr.
  238. // 'error' is a pointer to the reponse error message. May be nullptr.
  239. // One of 'data' or 'error' will be nullptr.
  240. using GenericResponseHandler =
  241. std::function<void(const void* response, const Error* error)>;
  242. // The callback function type used to handle an event.
  243. // 'event' is a pointer to the event data structure.
  244. using GenericEventHandler = std::function<void(const void* event)>;
  245. // The callback function type used to notify when a response has been sent
  246. // from this session endpoint.
  247. // 'response' is a pointer to the response data structure.
  248. // 'error' is a pointer to the reponse error message. May be nullptr.
  249. using GenericResponseSentHandler =
  250. std::function<void(const void* response, const Error* error)>;
  251. // registerHandler() registers 'handler' as the request handler callback for
  252. // requests of the type 'typeinfo'.
  253. virtual void registerHandler(const TypeInfo* typeinfo,
  254. const GenericRequestHandler& handler) = 0;
  255. // registerHandler() registers 'handler' as the event handler callback for
  256. // events of the type 'typeinfo'.
  257. virtual void registerHandler(const TypeInfo* typeinfo,
  258. const GenericEventHandler& handler) = 0;
  259. // registerHandler() registers 'handler' as the response-sent handler function
  260. // which is called whenever a response of the type 'typeinfo' is sent from
  261. // this session endpoint.
  262. virtual void registerHandler(const TypeInfo* typeinfo,
  263. const GenericResponseSentHandler& handler) = 0;
  264. // send() sends a request to the remote endpoint.
  265. // 'requestTypeInfo' is the type info of the request data structure.
  266. // 'requestTypeInfo' is the type info of the response data structure.
  267. // 'request' is a pointer to the request data structure.
  268. // 'responseHandler' is the handler function for the response.
  269. virtual bool send(const dap::TypeInfo* requestTypeInfo,
  270. const dap::TypeInfo* responseTypeInfo,
  271. const void* request,
  272. const GenericResponseHandler& responseHandler) = 0;
  273. // send() sends an event to the remote endpoint.
  274. // 'eventTypeInfo' is the type info for the event data structure.
  275. // 'event' is a pointer to the event data structure.
  276. virtual bool send(const TypeInfo* eventTypeInfo, const void* event) = 0;
  277. };
  278. template <typename F, typename RequestType>
  279. Session::IsRequestHandlerWithoutCallback<F> Session::registerHandler(
  280. F&& handler) {
  281. using ResponseType = typename RequestType::Response;
  282. const TypeInfo* typeinfo = TypeOf<RequestType>::type();
  283. registerHandler(typeinfo,
  284. [handler](const void* args,
  285. const RequestHandlerSuccessCallback& onSuccess,
  286. const RequestHandlerErrorCallback& onError) {
  287. ResponseOrError<ResponseType> res =
  288. handler(*reinterpret_cast<const RequestType*>(args));
  289. if (res.error) {
  290. onError(TypeOf<ResponseType>::type(), res.error);
  291. } else {
  292. onSuccess(TypeOf<ResponseType>::type(), &res.response);
  293. }
  294. });
  295. }
  296. template <typename F, typename RequestType, typename ResponseType>
  297. Session::IsRequestHandlerWithCallback<F, ResponseType> Session::registerHandler(
  298. F&& handler) {
  299. using CallbackType = ParamType<F, 1>;
  300. registerHandler(
  301. TypeOf<RequestType>::type(),
  302. [handler](const void* args,
  303. const RequestHandlerSuccessCallback& onSuccess,
  304. const RequestHandlerErrorCallback&) {
  305. CallbackType responseCallback = [onSuccess](const ResponseType& res) {
  306. onSuccess(TypeOf<ResponseType>::type(), &res);
  307. };
  308. handler(*reinterpret_cast<const RequestType*>(args), responseCallback);
  309. });
  310. }
  311. template <typename F, typename RequestType, typename ResponseType>
  312. Session::IsRequestHandlerWithCallback<F, ResponseOrError<ResponseType>>
  313. Session::registerHandler(F&& handler) {
  314. using CallbackType = ParamType<F, 1>;
  315. registerHandler(
  316. TypeOf<RequestType>::type(),
  317. [handler](const void* args,
  318. const RequestHandlerSuccessCallback& onSuccess,
  319. const RequestHandlerErrorCallback& onError) {
  320. CallbackType responseCallback =
  321. [onError, onSuccess](const ResponseOrError<ResponseType>& res) {
  322. if (res.error) {
  323. onError(TypeOf<ResponseType>::type(), res.error);
  324. } else {
  325. onSuccess(TypeOf<ResponseType>::type(), &res.response);
  326. }
  327. };
  328. handler(*reinterpret_cast<const RequestType*>(args), responseCallback);
  329. });
  330. }
  331. template <typename F, typename T>
  332. Session::IsEvent<T> Session::registerHandler(F&& handler) {
  333. auto cb = [handler](const void* args) {
  334. handler(*reinterpret_cast<const T*>(args));
  335. };
  336. const TypeInfo* typeinfo = TypeOf<T>::type();
  337. registerHandler(typeinfo, cb);
  338. }
  339. template <typename F, typename T>
  340. void Session::registerSentHandler(F&& handler) {
  341. auto cb = [handler](const void* response, const Error* error) {
  342. if (error != nullptr) {
  343. handler(ResponseOrError<T>(*error));
  344. } else {
  345. handler(ResponseOrError<T>(*reinterpret_cast<const T*>(response)));
  346. }
  347. };
  348. const TypeInfo* typeinfo = TypeOf<T>::type();
  349. registerHandler(typeinfo, cb);
  350. }
  351. template <typename T, typename>
  352. future<ResponseOrError<typename T::Response>> Session::send(const T& request) {
  353. using Response = typename T::Response;
  354. promise<ResponseOrError<Response>> promise;
  355. auto sent = send(TypeOf<T>::type(), TypeOf<Response>::type(), &request,
  356. [=](const void* result, const Error* error) {
  357. if (error != nullptr) {
  358. promise.set_value(ResponseOrError<Response>(*error));
  359. } else {
  360. promise.set_value(ResponseOrError<Response>(
  361. *reinterpret_cast<const Response*>(result)));
  362. }
  363. });
  364. if (!sent) {
  365. promise.set_value(Error("Failed to send request"));
  366. }
  367. return promise.get_future();
  368. }
  369. template <typename T, typename>
  370. void Session::send(const T& event) {
  371. const TypeInfo* typeinfo = TypeOf<T>::type();
  372. send(typeinfo, &event);
  373. }
  374. void Session::connect(const std::shared_ptr<ReaderWriter>& rw) {
  375. connect(rw, rw);
  376. }
  377. void Session::bind(const std::shared_ptr<dap::Reader>& r,
  378. const std::shared_ptr<dap::Writer>& w,
  379. const ClosedHandler& onClose = {}) {
  380. connect(r, w);
  381. startProcessingMessages(onClose);
  382. }
  383. void Session::bind(const std::shared_ptr<ReaderWriter>& rw,
  384. const ClosedHandler& onClose = {}) {
  385. bind(rw, rw, onClose);
  386. }
  387. } // namespace dap
  388. #endif // dap_session_h