CppWAMP
C++11 client library for the WAMP protocol
session.hpp
Go to the documentation of this file.
1 /*------------------------------------------------------------------------------
2  Copyright Butterfly Energy Systems 2014-2015, 2022.
3  Distributed under the Boost Software License, Version 1.0.
4  http://www.boost.org/LICENSE_1_0.txt
5 ------------------------------------------------------------------------------*/
6 
7 #ifndef CPPWAMP_SESSION_HPP
8 #define CPPWAMP_SESSION_HPP
9 
10 //------------------------------------------------------------------------------
14 //------------------------------------------------------------------------------
15 
16 #include <atomic>
17 #include <memory>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 #include "anyhandler.hpp"
22 #include "api.hpp"
23 #include "asiodefs.hpp"
24 #include "chits.hpp"
25 #include "config.hpp"
26 #include "connector.hpp"
27 #include "error.hpp"
28 #include "erroror.hpp"
29 #include "peerdata.hpp"
30 #include "registration.hpp"
31 #include "subscription.hpp"
32 #include "traits.hpp"
33 #include "wampdefs.hpp"
34 #include "internal/clientinterface.hpp"
35 
36 namespace wamp
37 {
38 
39 //------------------------------------------------------------------------------
44 //------------------------------------------------------------------------------
45 struct ThreadSafe
46 {
47  constexpr ThreadSafe() = default;
48 };
49 
50 //------------------------------------------------------------------------------
52 //------------------------------------------------------------------------------
53 CPPWAMP_INLINE_VARIABLE constexpr ThreadSafe threadSafe;
54 
55 
56 //------------------------------------------------------------------------------
109 //------------------------------------------------------------------------------
110 class CPPWAMP_API Session : public std::enable_shared_from_this<Session>
111 {
112 private:
113  struct GenericOp { template <typename F> void operator()(F&&) {} };
114 
115 public:
117  using Ptr = std::shared_ptr<Session>;
118 
121 
124 
127 
130 
132  using LogHandler = AnyReusableHandler<void(std::string)>;
133 
136 
139 
150  template <typename T, typename C>
151  using Deduced = decltype(
152  boost::asio::async_initiate<C, void(T)>(std::declval<GenericOp&>(),
153  std::declval<C&>()));
155  static Ptr create(AnyIoExecutor exec, const Connector::Ptr& connector);
156 
158  static Ptr create(AnyIoExecutor exec, const ConnectorList& connectors);
159 
166  template <typename TExecutionContext>
167  static CPPWAMP_ENABLED_TYPE(Ptr, isExecutionContext<TExecutionContext>())
168  create(
169  TExecutionContext& context,
171  const Connector::Ptr& connector
173  )
174  {
175  return create(context.get_executor(), connector);
176  }
177 
184  template <typename TExecutionContext>
185  static CPPWAMP_ENABLED_TYPE(Ptr, isExecutionContext<TExecutionContext>())
186  create(
187  TExecutionContext& context,
189  const ConnectorList& connectors
191  )
192  {
193  return create(context.get_executor(), connectors);
194  }
195 
198  static const Object& roles();
199 
202  Session(const Session&) = delete;
203  Session& operator=(const Session&) = delete;
205 
207  virtual ~Session();
208 
211 
213  AnyIoExecutor userExecutor() const;
214 
216  CPPWAMP_DEPRECATED AnyIoExecutor userIosvc() const;
217 
220  IoStrand strand() const;
221 
223  SessionState state() const;
225 
228 
229  void setWarningHandler(LogHandler handler);
230 
232  void setWarningHandler(ThreadSafe, LogHandler handler);
233 
235  void setTraceHandler(LogHandler handler);
236 
238  void setTraceHandler(ThreadSafe, LogHandler handler);
239 
241  void setStateChangeHandler(StateChangeHandler handler);
242 
244  void setStateChangeHandler(ThreadSafe, StateChangeHandler handler);
245 
247  void setChallengeHandler(ChallengeHandler handler);
248 
250  void setChallengeHandler(ThreadSafe, ChallengeHandler handler);
252 
255 
256  template <typename C>
257  CPPWAMP_NODISCARD Deduced<ErrorOr<std::size_t>, C>
258  connect(C&& completion);
259 
261  template <typename C>
262  CPPWAMP_NODISCARD Deduced<ErrorOr<std::size_t>, C>
263  connect(ThreadSafe, C&& completion);
264 
266  template <typename C>
267  CPPWAMP_NODISCARD Deduced<ErrorOr<SessionInfo>, C>
268  join(Realm realm, C&& completion);
269 
271  template <typename C>
272  CPPWAMP_NODISCARD Deduced<ErrorOr<SessionInfo>, C>
273  join(ThreadSafe, Realm realm, C&& completion);
274 
276  void authenticate(Authentication auth);
277 
279  void authenticate(ThreadSafe, Authentication auth);
280 
282  template <typename C>
283  CPPWAMP_NODISCARD Deduced<ErrorOr<Reason>, C>
284  leave(C&& completion);
285 
287  template <typename C>
288  CPPWAMP_NODISCARD Deduced<ErrorOr<Reason>, C>
289  leave(ThreadSafe, C&& completion);
290 
292  template <typename C>
293  CPPWAMP_NODISCARD Deduced<ErrorOr<Reason>, C>
294  leave(Reason reason, C&& completion);
295 
297  template <typename C>
298  CPPWAMP_NODISCARD Deduced<ErrorOr<Reason>, C>
299  leave(ThreadSafe, Reason reason, C&& completion);
300 
302  void disconnect();
303 
305  void disconnect(ThreadSafe);
306 
308  void reset();
309 
311  void reset(ThreadSafe);
313 
316 
317  template <typename C>
318  CPPWAMP_NODISCARD Deduced<ErrorOr<Subscription>, C>
319  subscribe(Topic topic, EventSlot eventSlot, C&& completion);
320 
322  template <typename C>
323  CPPWAMP_NODISCARD Deduced<ErrorOr<Subscription>, C>
324  subscribe(ThreadSafe, Topic topic, EventSlot eventSlot, C&& completion);
325 
327  void unsubscribe(Subscription sub);
328 
330  void unsubscribe(ThreadSafe, Subscription sub);
331 
334  template <typename C>
335  CPPWAMP_NODISCARD Deduced<ErrorOr<bool>, C>
336  unsubscribe(Subscription sub, C&& completion);
337 
339  template <typename C>
340  CPPWAMP_NODISCARD Deduced<ErrorOr<bool>, C>
341  unsubscribe(ThreadSafe, Subscription sub, C&& completion);
342 
344  void publish(Pub pub);
345 
347  void publish(ThreadSafe, Pub pub);
348 
350  template <typename C>
351  CPPWAMP_NODISCARD Deduced<ErrorOr<PublicationId>, C>
352  publish(Pub pub, C&& completion);
353 
355  template <typename C>
356  CPPWAMP_NODISCARD Deduced<ErrorOr<PublicationId>, C>
357  publish(ThreadSafe, Pub pub, C&& completion);
359 
362 
363  template <typename C>
364  CPPWAMP_NODISCARD Deduced<ErrorOr<Registration>, C>
365  enroll(Procedure procedure, CallSlot callSlot, C&& completion);
366 
368  template <typename C>
369  CPPWAMP_NODISCARD Deduced<ErrorOr<Registration>, C>
370  enroll(ThreadSafe, Procedure procedure, CallSlot callSlot, C&& completion);
371 
373  template <typename C>
374  CPPWAMP_NODISCARD Deduced<ErrorOr<Registration>, C>
375  enroll(Procedure procedure, CallSlot callSlot, InterruptSlot interruptSlot,
376  C&& completion);
377 
379  template <typename C>
380  CPPWAMP_NODISCARD Deduced<ErrorOr<Registration>, C>
381  enroll(ThreadSafe, Procedure procedure, CallSlot callSlot,
382  InterruptSlot interruptSlot, C&& completion);
383 
385  void unregister(Registration reg);
386 
388  void unregister(ThreadSafe, Registration reg);
389 
392  template <typename C>
393  CPPWAMP_NODISCARD Deduced<ErrorOr<bool>, C>
394  unregister(Registration reg, C&& completion);
395 
397  template <typename C>
398  CPPWAMP_NODISCARD Deduced<ErrorOr<bool>, C>
399  unregister(ThreadSafe, Registration reg, C&& completion);
400 
402  template <typename C>
403  CPPWAMP_NODISCARD Deduced<ErrorOr<Result>, C>
404  call(Rpc rpc, C&& completion);
405 
407  template <typename C>
408  CPPWAMP_NODISCARD Deduced<ErrorOr<Result>, C>
409  call(ThreadSafe, Rpc rpc, C&& completion);
410 
413  template <typename C>
414  CPPWAMP_NODISCARD Deduced<ErrorOr<Result>, C>
415  call(Rpc rpc, CallChit& chit, C&& completion);
416 
418  template <typename C>
419  CPPWAMP_NODISCARD Deduced<ErrorOr<Result>, C>
420  call(ThreadSafe, Rpc rpc, CallChit& chit, C&& completion);
421 
424  void cancel(CallChit);
425 
427  void cancel(ThreadSafe, CallChit);
428 
430  void cancel(CallChit, CallCancelMode mode);
431 
433  void cancel(ThreadSafe, CallChit, CallCancelMode mode);
434 
437  void cancel(CallCancellation cancellation);
438 
441  void cancel(ThreadSafe, CallCancellation cancellation);
443 
444 private:
445  using ImplPtr = typename internal::ClientInterface::Ptr;
446 
447  template <typename T>
448  using CompletionHandler = AnyCompletionHandler<void(ErrorOr<T>)>;
449 
450  template <typename T>
451  using ReusableHandler = AnyReusableHandler<void(T)>;
452 
453  using OneShotCallHandler = CompletionHandler<Result>;
454  using MultiShotCallHandler = AnyReusableHandler<void(ErrorOr<Result>)>;
455 
456  // These initiator function objects are needed due to C++11 lacking
457  // generic lambdas.
458  template <typename O> class SafeOp;
459  struct ConnectOp;
460  struct JoinOp;
461  struct LeaveOp;
462  struct SubscribeOp;
463  struct UnsubscribeOp;
464  struct PublishOp;
465  struct EnrollOp;
466  struct EnrollIntrOp;
467  struct UnregisterOp;
468  struct CallOp;
469 
470  template <typename O, typename C, typename... As>
471  Deduced<ErrorOr<typename O::ResultValue>, C>
472  initiate(C&& token, As&&... args);
473 
474  template <typename O, typename C, typename... As>
475  Deduced<ErrorOr<typename O::ResultValue>, C>
476  safelyInitiate(C&& token, As&&... args);
477 
478  template <typename F>
479  void dispatchViaStrand(F&& operation);
480 
481  template <typename TResultValue, typename F>
482  bool checkState(State expectedState, F& handler);
483 
484  void asyncConnect(CompletionHandler<size_t>&& handler);
485 
486  CPPWAMP_HIDDEN explicit Session(AnyIoExecutor userExec,
487  const ConnectorList& connectors);
488 
489  CPPWAMP_HIDDEN void warn(std::string message);
490 
491  CPPWAMP_HIDDEN void setState(SessionState state);
492 
493  CPPWAMP_HIDDEN void doConnect(
494  size_t index, std::shared_ptr<CompletionHandler<size_t>> handler);
495 
496  CPPWAMP_INLINE void onConnectFailure(
497  size_t index, std::error_code ec,
498  std::shared_ptr<CompletionHandler<size_t>> handler);
499 
500  CPPWAMP_INLINE void onConnectSuccess(
501  size_t index, ImplPtr impl,
502  std::shared_ptr<CompletionHandler<size_t>> handler);
503 
504  AnyIoExecutor userExecutor_;
505  ConnectorList connectors_;
506  Connector::Ptr currentConnector_;
507  ReusableHandler<std::string> warningHandler_;
508  ReusableHandler<std::string> traceHandler_;
509  ReusableHandler<State> stateChangeHandler_;
510  ReusableHandler<Challenge> challengeHandler_;
511  std::atomic<SessionState> state_;
512  bool isTerminating_ = false;
513  ImplPtr impl_;
514 
515  // TODO: Remove this once CoroSession is removed
516  template <typename> friend class CoroSession;
517 };
518 
519 
520 //******************************************************************************
521 // Session template function implementations
522 //******************************************************************************
523 
524 //------------------------------------------------------------------------------
525 template <typename O>
526 class Session::SafeOp
527 {
528 public:
529  using ResultValue = typename O::ResultValue;
530 
531  template <typename... Ts>
532  SafeOp(Session* self, Ts&&... args)
533  : self_(self),
534  operation_({self, std::forward<Ts>(args)...})
535  {}
536 
537  template <typename F>
538  void operator()(F&& handler)
539  {
540  struct Dispatched
541  {
542  Session::Ptr self;
543  O operation;
544  typename std::decay<F>::type handler;
545 
546  void operator()()
547  {
548  operation(std::move(handler));
549  }
550  };
551 
552  boost::asio::dispatch(self_->strand(),
553  Dispatched{self_->shared_from_this(),
554  std::move(operation_),
555  std::forward<F>(handler)});
556  }
557 
558 private:
559  Session* self_;
560  O operation_;
561 };
562 
563 //------------------------------------------------------------------------------
564 struct Session::ConnectOp
565 {
566  using ResultValue = size_t;
567  Session* self;
568  template <typename F> void operator()(F&& f)
569  {
570  self->asyncConnect(std::forward<F>(f));
571  }
572 };
573 
574 //------------------------------------------------------------------------------
590 //------------------------------------------------------------------------------
591 template <typename C>
592 #ifdef CPPWAMP_FOR_DOXYGEN
593 Deduced<ErrorOr<std::size_t>, C>
594 #else
595 Session::template Deduced<ErrorOr<std::size_t>, C>
596 #endif
598  C&& completion
600  )
601 {
602  return initiate<ConnectOp>(std::forward<C>(completion));
603 }
604 
605 //------------------------------------------------------------------------------
607 //------------------------------------------------------------------------------
608 template <typename C>
609 #ifdef CPPWAMP_FOR_DOXYGEN
610 Deduced<ErrorOr<std::size_t>, C>
611 #else
612 Session::template Deduced<ErrorOr<std::size_t>, C>
613 #endif
615  ThreadSafe,
616  C&& completion
618  )
619 {
620  return safelyInitiate<ConnectOp>(std::forward<C>(completion));
621 }
622 
623 //------------------------------------------------------------------------------
624 struct Session::JoinOp
625 {
626  using ResultValue = SessionInfo;
627  Session* self;
628  Realm realm;
629  template <typename F> void operator()(F&& f)
630  {
631  CompletionHandler<ResultValue> handler(std::forward<F>(f));
632  if (self->checkState<ResultValue>(State::closed, handler))
633  self->impl_->join(std::move(realm), std::move(handler));
634  }
635 };
636 
637 //------------------------------------------------------------------------------
652 //------------------------------------------------------------------------------
653 template <typename C>
654 #ifdef CPPWAMP_FOR_DOXYGEN
655 Deduced<ErrorOr<SessionInfo>, C>
656 #else
657 Session::template Deduced<ErrorOr<SessionInfo>, C>
658 #endif
660  Realm realm,
661  C&& completion
663  )
664 {
665  return initiate<JoinOp>(std::forward<C>(completion), std::move(realm));
666 }
667 
668 //------------------------------------------------------------------------------
670 //------------------------------------------------------------------------------
671 template <typename C>
672 #ifdef CPPWAMP_FOR_DOXYGEN
673 Deduced<ErrorOr<SessionInfo>, C>
674 #else
675 Session::template Deduced<ErrorOr<SessionInfo>, C>
676 #endif
678  ThreadSafe,
679  Realm realm,
680  C&& completion
682  )
683 {
684  return safelyInitiate<JoinOp>(std::forward<C>(completion),
685  std::move(realm));
686 }
687 
688 //------------------------------------------------------------------------------
689 struct Session::LeaveOp
690 {
691  using ResultValue = Reason;
692  Session* self;
693  Reason reason;
694  template <typename F> void operator()(F&& f)
695  {
696  CompletionHandler<ResultValue> handler(std::forward<F>(f));
697  if (self->checkState<ResultValue>(State::established, handler))
698  self->impl_->leave(std::move(reason), std::move(handler));
699  }
700 };
701 
702 //------------------------------------------------------------------------------
715 //------------------------------------------------------------------------------
716 template <typename C>
717 #ifdef CPPWAMP_FOR_DOXYGEN
718 Deduced<ErrorOr<Reason>, C>
719 #else
720 Session::template Deduced<ErrorOr<Reason>, C>
721 #endif
723  C&& completion
725  )
726 {
727  return leave(Reason("wamp.close.close_realm"), std::forward<C>(completion));
728 }
729 
730 //------------------------------------------------------------------------------
732 //------------------------------------------------------------------------------
733 template <typename C>
734 #ifdef CPPWAMP_FOR_DOXYGEN
735 Deduced<ErrorOr<Reason>, C>
736 #else
737 Session::template Deduced<ErrorOr<Reason>, C>
738 #endif
740  ThreadSafe,
741  C&& completion
743  )
744 {
745  return leave(threadSafe, Reason("wamp.close.close_realm"),
746  std::forward<C>(completion));
747 }
748 
749 //------------------------------------------------------------------------------
760 //------------------------------------------------------------------------------
761 template <typename C>
762 #ifdef CPPWAMP_FOR_DOXYGEN
763 Deduced<ErrorOr<Reason>, C>
764 #else
765 Session::template Deduced<ErrorOr<Reason>, C>
766 #endif
768  Reason reason,
769  C&& completion
771  )
772 {
773  return initiate<LeaveOp>(std::forward<C>(completion), std::move(reason));
774 }
775 
776 //------------------------------------------------------------------------------
778 //------------------------------------------------------------------------------
779 template <typename C>
780 #ifdef CPPWAMP_FOR_DOXYGEN
781 Deduced<ErrorOr<Reason>, C>
782 #else
783 Session::template Deduced<ErrorOr<Reason>, C>
784 #endif
786  ThreadSafe,
787  Reason reason,
788  C&& completion
790  )
791 {
792  return safelyInitiate<LeaveOp>(std::forward<C>(completion),
793  std::move(reason));
794 }
795 
796 //------------------------------------------------------------------------------
797 struct Session::SubscribeOp
798 {
799  using ResultValue = Subscription;
800  Session* self;
801  Topic topic;
802  EventSlot slot;
803  template <typename F> void operator()(F&& f)
804  {
805  using std::move;
806  CompletionHandler<ResultValue> handler(std::forward<F>(f));
807  if (self->checkState<ResultValue>(State::established, handler))
808  self->impl_->subscribe(move(topic), move(slot), move(handler));
809  }
810 };
811 
812 //------------------------------------------------------------------------------
823 //------------------------------------------------------------------------------
824 template <typename C>
825 #ifdef CPPWAMP_FOR_DOXYGEN
826 Deduced<ErrorOr<Subscription>, C>
827 #else
828 Session::template Deduced<ErrorOr<Subscription>, C>
829 #endif
831  Topic topic,
832  EventSlot eventSlot,
834  C&& completion
837  )
838 {
839  return initiate<SubscribeOp>(std::forward<C>(completion), std::move(topic),
840  std::move(eventSlot));
841 }
842 
843 //------------------------------------------------------------------------------
845 //------------------------------------------------------------------------------
846 template <typename C>
847 #ifdef CPPWAMP_FOR_DOXYGEN
848 Deduced<ErrorOr<Subscription>, C>
849 #else
850 Session::template Deduced<ErrorOr<Subscription>, C>
851 #endif
853  ThreadSafe,
854  Topic topic,
855  EventSlot eventSlot,
857  C&& completion
860  )
861 {
862  return safelyInitiate<SubscribeOp>(std::forward<C>(completion),
863  std::move(topic), std::move(eventSlot));
864 }
865 
866 //------------------------------------------------------------------------------
867 struct Session::UnsubscribeOp
868 {
869  using ResultValue = bool;
870  Session* self;
871  Subscription sub;
872  template <typename F> void operator()(F&& f)
873  {
874  CompletionHandler<ResultValue> handler(std::forward<F>(f));
875  if (self->checkState<ResultValue>(State::established, handler))
876  self->impl_->unsubscribe(std::move(sub), std::move(handler));
877  }
878 };
879 
880 //------------------------------------------------------------------------------
901 //------------------------------------------------------------------------------
902 template <typename C>
903 #ifdef CPPWAMP_FOR_DOXYGEN
904 Deduced<ErrorOr<bool>, C>
905 #else
906 Session::template Deduced<ErrorOr<bool>, C>
907 #endif
909  Subscription sub,
910  C&& completion
912  )
913 {
914  CPPWAMP_LOGIC_CHECK(bool(sub), "The subscription is empty");
915  return initiate<UnsubscribeOp>(std::forward<C>(completion), sub);
916 }
917 
918 //------------------------------------------------------------------------------
920 //------------------------------------------------------------------------------
921 template <typename C>
922 #ifdef CPPWAMP_FOR_DOXYGEN
923 Deduced<ErrorOr<bool>, C>
924 #else
925 Session::template Deduced<ErrorOr<bool>, C>
926 #endif
928  ThreadSafe,
929  Subscription sub,
930  C&& completion
932  )
933 {
934  CPPWAMP_LOGIC_CHECK(bool(sub), "The subscription is empty");
935  return safelyInitiate<UnsubscribeOp>(std::forward<C>(completion), sub);
936 }
937 
938 //------------------------------------------------------------------------------
939 struct Session::PublishOp
940 {
941  using ResultValue = PublicationId;
942  Session* self;
943  Pub pub;
944  template <typename F> void operator()(F&& f)
945  {
946  CompletionHandler<ResultValue> handler(std::forward<F>(f));
947  if (self->checkState<ResultValue>(State::established, handler))
948  self->impl_->publish(std::move(pub), std::move(handler));
949  }
950 };
951 
952 //------------------------------------------------------------------------------
962 //------------------------------------------------------------------------------
963 template <typename C>
964 #ifdef CPPWAMP_FOR_DOXYGEN
965 Deduced<ErrorOr<PublicationId>, C>
966 #else
967 Session::template Deduced<ErrorOr<PublicationId>, C>
968 #endif
970  Pub pub,
971  C&& completion
973 )
974 {
975  return initiate<PublishOp>(std::forward<C>(completion), std::move(pub));
976 }
977 
978 //------------------------------------------------------------------------------
980 //------------------------------------------------------------------------------
981 template <typename C>
982 #ifdef CPPWAMP_FOR_DOXYGEN
983 Deduced<ErrorOr<PublicationId>, C>
984 #else
985 Session::template Deduced<ErrorOr<PublicationId>, C>
986 #endif
988  ThreadSafe,
989  Pub pub,
990  C&& completion
992  )
993 {
994  return safelyInitiate<PublishOp>(std::forward<C>(completion),
995  std::move(pub));
996 }
997 
998 //------------------------------------------------------------------------------
999 struct Session::EnrollOp
1000 {
1001  using ResultValue = Registration;
1002  Session* self;
1003  Procedure procedure;
1004  CallSlot slot;
1005  template <typename F> void operator()(F&& f)
1006  {
1007  using std::move;
1008  CompletionHandler<ResultValue> handler(std::forward<F>(f));
1009  if (self->checkState<ResultValue>(State::established, handler))
1010  self->impl_->enroll(move(procedure), move(slot), nullptr,
1011  move(handler));
1012  }
1013 };
1014 
1015 //------------------------------------------------------------------------------
1030 //------------------------------------------------------------------------------
1031 template <typename C>
1032 #ifdef CPPWAMP_FOR_DOXYGEN
1033 Deduced<ErrorOr<Registration>, C>
1034 #else
1035 Session::template Deduced<ErrorOr<Registration>, C>
1036 #endif
1038  Procedure procedure,
1039  CallSlot callSlot,
1041  C&& completion
1044 )
1045 {
1046  return initiate<EnrollOp>(
1047  std::forward<C>(completion), std::move(procedure), std::move(callSlot));
1048 }
1049 
1050 //------------------------------------------------------------------------------
1052 //------------------------------------------------------------------------------
1053 template <typename C>
1054 #ifdef CPPWAMP_FOR_DOXYGEN
1055 Deduced<ErrorOr<Registration>, C>
1056 #else
1057 Session::template Deduced<ErrorOr<Registration>, C>
1058 #endif
1060  ThreadSafe,
1061  Procedure procedure,
1062  CallSlot callSlot,
1064  C&& completion
1067  )
1068 {
1069  return safelyInitiate<EnrollOp>(
1070  std::forward<C>(completion), std::move(procedure), std::move(callSlot));
1071 }
1072 
1073 //------------------------------------------------------------------------------
1074 struct Session::EnrollIntrOp
1075 {
1076  using ResultValue = Registration;
1077  Session* self;
1078  Procedure procedure;
1079  CallSlot callSlot;
1080  InterruptSlot interruptSlot;
1081  template <typename F> void operator()(F&& f)
1082  {
1083  CompletionHandler<ResultValue> handler(std::forward<F>(f));
1084  if (self->checkState<ResultValue>(State::established, handler))
1085  {
1086  self->impl_->enroll(std::move(procedure), std::move(callSlot),
1087  std::move(interruptSlot), std::move(handler));
1088  }
1089  }
1090 };
1091 
1092 //------------------------------------------------------------------------------
1106 //------------------------------------------------------------------------------
1107 template <typename C>
1108 #ifdef CPPWAMP_FOR_DOXYGEN
1109 Deduced<ErrorOr<Registration>, C>
1110 #else
1111 Session::template Deduced<ErrorOr<Registration>, C>
1112 #endif
1114  Procedure procedure,
1115  CallSlot callSlot,
1118  interruptSlot,
1120  C&& completion
1123  )
1124 {
1125  return initiate<EnrollIntrOp>(
1126  std::forward<C>(completion), std::move(procedure), std::move(callSlot),
1127  std::move(interruptSlot));
1128 }
1129 
1130 //------------------------------------------------------------------------------
1132 //------------------------------------------------------------------------------
1133 template <typename C>
1134 #ifdef CPPWAMP_FOR_DOXYGEN
1135 Deduced<ErrorOr<Registration>, C>
1136 #else
1137 Session::template Deduced<ErrorOr<Registration>, C>
1138 #endif
1140  ThreadSafe,
1141  Procedure procedure,
1142  CallSlot callSlot,
1145  interruptSlot,
1147  C&& completion
1150  )
1151 {
1152  return safelyInitiate<EnrollIntrOp>(
1153  std::forward<C>(completion), std::move(procedure), std::move(callSlot),
1154  std::move(interruptSlot));
1155 }
1156 
1157 //------------------------------------------------------------------------------
1158 struct Session::UnregisterOp
1159 {
1160  using ResultValue = bool;
1161  Session* self;
1162  Registration reg;
1163  template <typename F> void operator()(F&& f)
1164  {
1165  CompletionHandler<ResultValue> handler(std::forward<F>(f));
1166  if (self->checkState<ResultValue>(State::established, handler))
1167  self->impl_->unregister(std::move(reg), std::move(handler));
1168  }
1169 };
1170 
1171 //------------------------------------------------------------------------------
1188 //------------------------------------------------------------------------------
1189 template <typename C>
1190 #ifdef CPPWAMP_FOR_DOXYGEN
1191 Deduced<ErrorOr<bool>, C>
1192 #else
1193 Session::template Deduced<ErrorOr<bool>, C>
1194 #endif
1196  Registration reg,
1197  C&& completion
1199  )
1200 {
1201  CPPWAMP_LOGIC_CHECK(bool(reg), "The registration is empty");
1202  return initiate<UnregisterOp>(std::forward<C>(completion), reg);
1203 }
1204 
1205 //------------------------------------------------------------------------------
1207 //------------------------------------------------------------------------------
1208 template <typename C>
1209 #ifdef CPPWAMP_FOR_DOXYGEN
1210 Deduced<ErrorOr<bool>, C>
1211 #else
1212 Session::template Deduced<ErrorOr<bool>, C>
1213 #endif
1215  ThreadSafe,
1216  Registration reg,
1217  C&& completion
1219  )
1220 {
1221  CPPWAMP_LOGIC_CHECK(bool(reg), "The registration is empty");
1222  return safelyInitiate<UnregisterOp>(std::forward<C>(completion), reg);
1223 }
1224 
1225 //------------------------------------------------------------------------------
1226 struct Session::CallOp
1227 {
1228  using ResultValue = Result;
1229  Session* self;
1230  Rpc rpc;
1231  CallChit* chitPtr;
1232 
1233  template <typename F>
1234  void operator()(F&& f)
1235  {
1236  if (chitPtr)
1237  *chitPtr = {};
1238  auto chit = call(std::is_copy_constructible<ValueTypeOf<F>>{},
1239  std::forward<F>(f));
1240  if (chitPtr)
1241  *chitPtr = chit;
1242  }
1243 
1244  template <typename F>
1245  CallChit call(std::true_type, F&& f)
1246  {
1247  using std::move;
1248  CallChit chit;
1249  if (rpc.progressiveResultsAreEnabled())
1250  {
1251  MultiShotCallHandler handler(std::forward<F>(f));
1252  if (self->checkState<Result>(State::established, handler))
1253  chit = self->impl_->ongoingCall(move(rpc), move(handler));
1254  }
1255  else
1256  {
1257  OneShotCallHandler handler(std::forward<F>(f));
1258  if (self->checkState<Result>(State::established, handler))
1259  chit = self->impl_->oneShotCall(move(rpc), move(handler));
1260  }
1261  return chit;
1262  }
1263 
1264  template <typename F>
1265  CallChit call(std::false_type, F&& f)
1266  {
1267  using std::move;
1268  CallChit chit;
1270  "Progressive results require copyable "
1271  "multi-shot handler");
1272  CompletionHandler<Result> handler(std::forward<F>(f));
1273  if (self->checkState<ResultValue>(State::established, handler))
1274  chit = self->impl_->oneShotCall(move(rpc), move(handler));
1275  return chit;
1276  }
1277 };
1278 
1279 //------------------------------------------------------------------------------
1299 //------------------------------------------------------------------------------
1300 template <typename C>
1301 #ifdef CPPWAMP_FOR_DOXYGEN
1302 Deduced<ErrorOr<Result>, C>
1303 #else
1304 Session::template Deduced<ErrorOr<Result>, C>
1305 #endif
1307  Rpc rpc,
1308  C&& completion
1310 )
1311 {
1312  return initiate<CallOp>(std::forward<C>(completion), std::move(rpc),
1313  nullptr);
1314 }
1315 
1316 //------------------------------------------------------------------------------
1318 //------------------------------------------------------------------------------
1319 template <typename C>
1320 #ifdef CPPWAMP_FOR_DOXYGEN
1321 Deduced<ErrorOr<Result>, C>
1322 #else
1323 Session::template Deduced<ErrorOr<Result>, C>
1324 #endif
1326  ThreadSafe,
1327  Rpc rpc,
1328  C&& completion
1330  )
1331 {
1332  return safelyInitiate<CallOp>(std::forward<C>(completion), std::move(rpc),
1333  nullptr);
1334 }
1335 
1336 //------------------------------------------------------------------------------
1338 //------------------------------------------------------------------------------
1339 template <typename C>
1340 #ifdef CPPWAMP_FOR_DOXYGEN
1341 Deduced<ErrorOr<Result>, C>
1342 #else
1343 Session::template Deduced<ErrorOr<Result>, C>
1344 #endif
1346  Rpc rpc,
1347  CallChit& chit,
1348  C&& completion
1350  )
1351 {
1352  return initiate<CallOp>(std::forward<C>(completion), std::move(rpc), &chit);
1353 }
1354 
1355 //------------------------------------------------------------------------------
1357 //------------------------------------------------------------------------------
1358 template <typename C>
1359 #ifdef CPPWAMP_FOR_DOXYGEN
1360 Deduced<ErrorOr<Result>, C>
1361 #else
1362 Session::template Deduced<ErrorOr<Result>, C>
1363 #endif
1365  ThreadSafe,
1366  Rpc rpc,
1367  CallChit& chit,
1368  C&& completion
1370  )
1371 {
1372  return safelyInitiate<CallOp>(std::forward<C>(completion), std::move(rpc),
1373  &chit);
1374 }
1375 
1376 //------------------------------------------------------------------------------
1377 template <typename O, typename C, typename... As>
1378 #ifdef CPPWAMP_FOR_DOXYGEN
1379 Deduced<ErrorOr<typename O::ResultValue>, C>
1380 #else
1381 Session::template Deduced<ErrorOr<typename O::ResultValue>, C>
1382 #endif
1383 Session::initiate(C&& token, As&&... args)
1384 {
1385  return boost::asio::async_initiate<
1387  O{this, std::forward<As>(args)...}, token);
1388 }
1389 
1390 //------------------------------------------------------------------------------
1391 template <typename O, typename C, typename... As>
1392 #ifdef CPPWAMP_FOR_DOXYGEN
1393 Deduced<ErrorOr<typename O::ResultValue>, C>
1394 #else
1395 Session::template Deduced<ErrorOr<typename O::ResultValue>, C>
1396 #endif
1397 Session::safelyInitiate(C&& token, As&&... args)
1398 {
1399 
1400  return initiate<SafeOp<O>>(std::forward<C>(token),
1401  std::forward<As>(args)...);
1402 }
1403 
1404 //------------------------------------------------------------------------------
1405 template <typename F>
1406 void Session::dispatchViaStrand(F&& operation)
1407 {
1408  boost::asio::dispatch(strand(), std::forward<F>(operation));
1409 }
1410 
1411 //------------------------------------------------------------------------------
1412 template <typename TResultValue, typename F>
1413 bool Session::checkState(State expectedState, F& handler)
1414 {
1415  bool valid = state() == expectedState;
1416  if (!valid)
1417  {
1418  ErrorOr<TResultValue> e{makeUnexpectedError(SessionErrc::invalidState)};
1419  postVia(userExecutor_, std::move(handler), std::move(e));
1420  }
1421  return valid;
1422 }
1423 
1424 } // namespace wamp
1425 
1426 #ifndef CPPWAMP_COMPILED_LIB
1427 #include "internal/session.ipp"
1428 #endif
1429 
1430 #endif // CPPWAMP_SESSION_HPP
wamp::Rpc::progressiveResultsAreEnabled
bool progressiveResultsAreEnabled() const
Indicates if progressive results were enabled.
Definition: peerdata.ipp:628
wamp::Session::unregister
void unregister(Registration reg)
Unregisters a remote procedure call.
Definition: session.ipp:423
wamp::Reason
Provides the reason URI and other options contained within GOODBYE messages.
Definition: peerdata.hpp:181
anyhandler.hpp
Contains facilities for type-erasing asynchronous handlers.
registration.hpp
Contains the declaration of the Registration class.
wamp::CoroSession
Coroutine API used by a client peer in WAMP applications.
Definition: corosession.hpp:58
wamp::AnyIoExecutor
boost::asio::any_io_executor AnyIoExecutor
Polymorphic executor for all I/O objects.
Definition: asiodefs.hpp:27
wamp::Realm
Realm URI and other options contained within WAMP HELLO messages.
Definition: peerdata.hpp:59
CPPWAMP_LOGIC_CHECK
#define CPPWAMP_LOGIC_CHECK(cond, msg)
Conditionally throws an error::Logic exception having the given message string.
Definition: error.hpp:36
wamp::Session::CallSlot
AnyReusableHandler< Outcome(Invocation)> CallSlot
Type-erased wrapper around an RPC handler.
Definition: session.hpp:126
wamp::CallCancellation
Contains the request ID and options contained within WAMP CANCEL messages.
Definition: peerdata.hpp:885
wamp::Session::unsubscribe
void unsubscribe(Subscription sub)
Unsubscribes a subscription to a topic.
Definition: session.ipp:354
wamp::Authentication
Provides the Signature and Extra dictionary contained within WAMP AUTHENTICATE messages.
Definition: peerdata.hpp:205
wamp::Session::InterruptSlot
AnyReusableHandler< Outcome(Interruption)> InterruptSlot
Type-erased wrapper around an RPC interruption handler.
Definition: session.hpp:129
connector.hpp
Contains the declaration of the Connector abstract base class.
wamp::AnyReusableHandler< void(Event)>
erroror.hpp
Contains the ErrorOr template class.
api.hpp
Defines macros related to exporting/importing APIs.
wamp::Session::publish
void publish(Pub pub)
Publishes an event.
Definition: session.ipp:381
wamp::Interruption
Contains details within WAMP INTERRUPT messages.
Definition: peerdata.hpp:916
wamp::Session::strand
IoStrand strand() const
Obtains the execution context in which which I/O operations are serialized.
Definition: session.ipp:92
wamp::IoStrand
boost::asio::strand< AnyIoExecutor > IoStrand
Serializes I/O operations.
Definition: asiodefs.hpp:41
wamp::Connector::Ptr
std::shared_ptr< Connector > Ptr
Shared pointer to a Connector.
Definition: connector.hpp:43
wamp::Object
std::map< String, Variant > Object
Variant bound type for maps of variants.
Definition: variantdefs.hpp:52
wamp::Session::Ptr
std::shared_ptr< Session > Ptr
Shared pointer to a Session.
Definition: session.hpp:117
wamp::Topic
Provides the topic URI and other options contained within WAMP ‘SUBSCRIBE’ messages.
Definition: peerdata.hpp:331
wamp::Procedure
Contains the procedure URI and other options contained within WAMP REGISTER messages.
Definition: peerdata.hpp:492
wamp::Session::state
SessionState state() const
Returns the current state of the session.
Definition: session.ipp:103
wamp::makeUnexpectedError
UnexpectedError makeUnexpectedError(TErrorEnum errc)
Convenience function that creates an UnexpectedError from an error code enum.
Definition: erroror.hpp:113
peerdata.hpp
Contains declarations for data structures exchanged between WAMP peers.
asiodefs.hpp
Common type definitions used by transports that rely on Boost.Asio.
wamp
Definition: anyhandler.hpp:36
chits.hpp
Contains lightweight tokens representing pending requests.
wamp::Session::enroll
Deduced< ErrorOr< Registration >, C > enroll(Procedure procedure, CallSlot callSlot, C &&completion)
Registers a WAMP remote procedure call.
Definition: session.hpp:1037
wamp::Session::EventSlot
AnyReusableHandler< void(Event)> EventSlot
Type-erased wrapper around a WAMP event handler.
Definition: session.hpp:123
wamp::Connector
Abstract base class for establishing client transport endpoints.
Definition: connector.hpp:39
wamp::Session::connect
Deduced< ErrorOr< std::size_t >, C > connect(C &&completion)
Asynchronously attempts to connect to a router.
Definition: session.hpp:597
wamp::Subscription
Represents a pub/sub event subscription.
Definition: subscription.hpp:41
wamp::Session::subscribe
Deduced< ErrorOr< Subscription >, C > subscribe(Topic topic, EventSlot eventSlot, C &&completion)
Subscribes to WAMP pub/sub events having the given topic.
Definition: session.hpp:830
wamp::CallChit
Lightweight token representing a call request.
Definition: chits.hpp:29
wamp::SessionErrc::invalidState
@ invalidState
Invalid state for this operation.
wamp::Rpc
Contains the procedure URI, options, and payload contained within WAMP CALL messages.
Definition: peerdata.hpp:535
wamp::threadSafe
constexpr ThreadSafe threadSafe
Constant ThreadSafe object instance that can be passed to functions.
Definition: session.hpp:53
wamp::Outcome
Contains the outcome of an RPC invocation.
Definition: peerdata.hpp:709
wamp::Challenge
Provides the AuthMethod and Extra dictionary contained within WAMP CHALLENGE messages.
Definition: peerdata.hpp:240
wamp::PublicationId
int64_t PublicationId
Ephemeral ID associated with an event publication.
Definition: wampdefs.hpp:25
wamp::Pub
Provides the topic URI, options, and payload contained within WAMP PUBLISH messages.
Definition: peerdata.hpp:363
wamp::Result
Contains the remote procedure result options/payload within WAMP RESULT and YIELD messages.
Definition: peerdata.hpp:646
wamp::Registration
Represents a remote procedure registration.
Definition: registration.hpp:42
wamp::ConnectorList
std::vector< Connector::Ptr > ConnectorList
List of Connector objects to use when attempting connection.
Definition: connector.hpp:74
wamp::ErrorOr
Minimalistic implementation of std::expected<T, std::error_code>
Definition: erroror.hpp:128
wamp::Session
Session API used by a client peer in WAMP applications.
Definition: session.hpp:110
wamp::SessionInfo
Session information contained within WAMP WELCOME messages.
Definition: peerdata.hpp:97
wampdefs.hpp
Contains type definitions related to WAMP IDs and sessions.
wamp::Session::join
Deduced< ErrorOr< SessionInfo >, C > join(Realm realm, C &&completion)
Asynchronously attempts to join the given WAMP realm.
Definition: session.hpp:659
traits.hpp
Contains general-purpose type traits.
wamp::Invocation
Contains payload arguments and other options within WAMP INVOCATION messages.
Definition: peerdata.hpp:799
wamp::SessionState
SessionState
Enumerates the possible states that a client or router session can be in.
Definition: wampdefs.hpp:34
wamp::Event
Provides the subscription/publication ids, options, and payload contained within WAMP EVENT messages.
Definition: peerdata.hpp:427
wamp::Session::Deduced
decltype(boost::asio::async_initiate< C, void(T)>(std::declval< GenericOp & >(), std::declval< C & >())) Deduced
Obtains the type returned by boost::asio::async_initiate with given the completion token type C and s...
Definition: session.hpp:153
wamp::postVia
void postVia(const E &fallbackExec, F &&handler, Ts &&... args)
Posts the given handler using the given fallback executor, passing the given arguments.
Definition: anyhandler.hpp:327
wamp::Session::leave
Deduced< ErrorOr< Reason >, C > leave(C &&completion)
Asynchronously leaves the WAMP session.
Definition: session.hpp:722
wamp::Session::call
Deduced< ErrorOr< Result >, C > call(Rpc rpc, C &&completion)
Calls a remote procedure.
Definition: session.hpp:1306
wamp::CallCancelMode
CallCancelMode
Enumerates the possible call cancelling modes.
Definition: wampdefs.hpp:49
subscription.hpp
Contains the declaration of the Subscription class.
wamp::ThreadSafe
Tag type used to specify than an operation is to be dispatched via the called objects's execution str...
Definition: session.hpp:45
wamp::AnyCompletionHandler
boost::asio::any_completion_handler< TSignature > AnyCompletionHandler
Type-erases a one-shot (and possibly move-only) asynchronous completion handler.
Definition: anyhandler.hpp:55
error.hpp
Contains facilities for reporting and describing errors.