7 #ifndef CPPWAMP_SESSION_HPP
8 #define CPPWAMP_SESSION_HPP
34 #include "internal/clientinterface.hpp"
110 class CPPWAMP_API
Session :
public std::enable_shared_from_this<Session>
113 struct GenericOp {
template <
typename F>
void operator()(F&&) {} };
117 using Ptr = std::shared_ptr<Session>;
150 template <
typename T,
typename C>
152 boost::asio::async_initiate<C,
void(T)>(std::declval<GenericOp&>(),
153 std::declval<C&>()));
166 template <
typename TExecutionContext>
167 static CPPWAMP_ENABLED_TYPE(
Ptr, isExecutionContext<TExecutionContext>())
169 TExecutionContext& context,
175 return create(context.get_executor(), connector);
184 template <
typename TExecutionContext>
185 static CPPWAMP_ENABLED_TYPE(Ptr, isExecutionContext<TExecutionContext>())
187 TExecutionContext& context,
193 return create(context.get_executor(), connectors);
198 static const Object& roles();
229 void setWarningHandler(LogHandler handler);
232 void setWarningHandler(
ThreadSafe, LogHandler handler);
235 void setTraceHandler(LogHandler handler);
238 void setTraceHandler(
ThreadSafe, LogHandler handler);
241 void setStateChangeHandler(StateChangeHandler handler);
244 void setStateChangeHandler(
ThreadSafe, StateChangeHandler handler);
247 void setChallengeHandler(ChallengeHandler handler);
250 void setChallengeHandler(
ThreadSafe, ChallengeHandler handler);
256 template <
typename C>
257 CPPWAMP_NODISCARD Deduced<ErrorOr<std::size_t>, C>
258 connect(C&& completion);
261 template <
typename C>
262 CPPWAMP_NODISCARD Deduced<ErrorOr<std::size_t>, C>
266 template <
typename C>
267 CPPWAMP_NODISCARD Deduced<ErrorOr<SessionInfo>, C>
268 join(
Realm realm, C&& completion);
271 template <
typename C>
272 CPPWAMP_NODISCARD Deduced<ErrorOr<SessionInfo>, C>
282 template <
typename C>
283 CPPWAMP_NODISCARD Deduced<ErrorOr<Reason>, C>
284 leave(C&& completion);
287 template <
typename C>
288 CPPWAMP_NODISCARD Deduced<ErrorOr<Reason>, C>
292 template <
typename C>
293 CPPWAMP_NODISCARD Deduced<ErrorOr<Reason>, C>
294 leave(
Reason reason, C&& completion);
297 template <
typename C>
298 CPPWAMP_NODISCARD Deduced<ErrorOr<Reason>, C>
317 template <
typename C>
318 CPPWAMP_NODISCARD Deduced<ErrorOr<Subscription>, C>
319 subscribe(
Topic topic, EventSlot eventSlot, C&& completion);
322 template <
typename C>
323 CPPWAMP_NODISCARD Deduced<ErrorOr<Subscription>, C>
324 subscribe(
ThreadSafe,
Topic topic, EventSlot eventSlot, C&& completion);
334 template <
typename C>
335 CPPWAMP_NODISCARD Deduced<ErrorOr<bool>, C>
339 template <
typename C>
340 CPPWAMP_NODISCARD Deduced<ErrorOr<bool>, C>
344 void publish(
Pub pub);
350 template <
typename C>
351 CPPWAMP_NODISCARD Deduced<ErrorOr<PublicationId>, C>
352 publish(
Pub pub, C&& completion);
355 template <
typename C>
356 CPPWAMP_NODISCARD Deduced<ErrorOr<PublicationId>, C>
363 template <
typename C>
364 CPPWAMP_NODISCARD Deduced<ErrorOr<Registration>, C>
365 enroll(
Procedure procedure, CallSlot callSlot, C&& completion);
368 template <
typename C>
369 CPPWAMP_NODISCARD Deduced<ErrorOr<Registration>, C>
373 template <
typename C>
374 CPPWAMP_NODISCARD Deduced<ErrorOr<Registration>, C>
375 enroll(
Procedure procedure, CallSlot callSlot, InterruptSlot interruptSlot,
379 template <
typename C>
380 CPPWAMP_NODISCARD Deduced<ErrorOr<Registration>, C>
382 InterruptSlot interruptSlot, C&& completion);
392 template <
typename C>
393 CPPWAMP_NODISCARD Deduced<ErrorOr<bool>, C>
397 template <
typename C>
398 CPPWAMP_NODISCARD Deduced<ErrorOr<bool>, C>
402 template <
typename C>
403 CPPWAMP_NODISCARD Deduced<ErrorOr<Result>, C>
404 call(
Rpc rpc, C&& completion);
407 template <
typename C>
408 CPPWAMP_NODISCARD Deduced<ErrorOr<Result>, C>
413 template <
typename C>
414 CPPWAMP_NODISCARD Deduced<ErrorOr<Result>, C>
418 template <
typename C>
419 CPPWAMP_NODISCARD Deduced<ErrorOr<Result>, C>
445 using ImplPtr =
typename internal::ClientInterface::Ptr;
447 template <
typename T>
450 template <
typename T>
453 using OneShotCallHandler = CompletionHandler<Result>;
458 template <
typename O>
class SafeOp;
463 struct UnsubscribeOp;
470 template <
typename O,
typename C,
typename... As>
471 Deduced<ErrorOr<typename O::ResultValue>, C>
472 initiate(C&& token, As&&... args);
474 template <
typename O,
typename C,
typename... As>
475 Deduced<ErrorOr<typename O::ResultValue>, C>
476 safelyInitiate(C&& token, As&&... args);
478 template <
typename F>
479 void dispatchViaStrand(F&& operation);
481 template <
typename TResultValue,
typename F>
482 bool checkState(State expectedState, F& handler);
484 void asyncConnect(CompletionHandler<size_t>&& handler);
489 CPPWAMP_HIDDEN
void warn(std::string message);
493 CPPWAMP_HIDDEN
void doConnect(
494 size_t index, std::shared_ptr<CompletionHandler<size_t>> handler);
496 CPPWAMP_INLINE
void onConnectFailure(
497 size_t index, std::error_code ec,
498 std::shared_ptr<CompletionHandler<size_t>> handler);
500 CPPWAMP_INLINE
void onConnectSuccess(
501 size_t index, ImplPtr impl,
502 std::shared_ptr<CompletionHandler<size_t>> handler);
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;
525 template <
typename O>
526 class Session::SafeOp
529 using ResultValue =
typename O::ResultValue;
531 template <
typename... Ts>
532 SafeOp(Session*
self, Ts&&... args)
534 operation_({
self, std::forward<Ts>(args)...})
537 template <
typename F>
538 void operator()(F&& handler)
544 typename std::decay<F>::type handler;
548 operation(std::move(handler));
552 boost::asio::dispatch(self_->strand(),
553 Dispatched{self_->shared_from_this(),
554 std::move(operation_),
555 std::forward<F>(handler)});
564 struct Session::ConnectOp
566 using ResultValue = size_t;
568 template <
typename F>
void operator()(F&& f)
570 self->asyncConnect(std::forward<F>(f));
591 template <
typename C>
592 #ifdef CPPWAMP_FOR_DOXYGEN
593 Deduced<ErrorOr<std::size_t>, C>
595 Session::template Deduced<ErrorOr<std::size_t>, C>
602 return initiate<ConnectOp>(std::forward<C>(completion));
608 template <
typename C>
609 #ifdef CPPWAMP_FOR_DOXYGEN
610 Deduced<ErrorOr<std::size_t>, C>
612 Session::template Deduced<ErrorOr<std::size_t>, C>
620 return safelyInitiate<ConnectOp>(std::forward<C>(completion));
624 struct Session::JoinOp
629 template <
typename F>
void operator()(F&& f)
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));
653 template <
typename C>
654 #ifdef CPPWAMP_FOR_DOXYGEN
655 Deduced<ErrorOr<SessionInfo>, C>
657 Session::template Deduced<ErrorOr<SessionInfo>, C>
665 return initiate<JoinOp>(std::forward<C>(completion), std::move(realm));
671 template <
typename C>
672 #ifdef CPPWAMP_FOR_DOXYGEN
673 Deduced<ErrorOr<SessionInfo>, C>
675 Session::template Deduced<ErrorOr<SessionInfo>, C>
684 return safelyInitiate<JoinOp>(std::forward<C>(completion),
689 struct Session::LeaveOp
691 using ResultValue =
Reason;
694 template <
typename F>
void operator()(F&& f)
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));
716 template <
typename C>
717 #ifdef CPPWAMP_FOR_DOXYGEN
718 Deduced<ErrorOr<Reason>, C>
720 Session::template Deduced<ErrorOr<Reason>, C>
727 return leave(
Reason(
"wamp.close.close_realm"), std::forward<C>(completion));
733 template <
typename C>
734 #ifdef CPPWAMP_FOR_DOXYGEN
735 Deduced<ErrorOr<Reason>, C>
737 Session::template Deduced<ErrorOr<Reason>, C>
746 std::forward<C>(completion));
761 template <
typename C>
762 #ifdef CPPWAMP_FOR_DOXYGEN
763 Deduced<ErrorOr<Reason>, C>
765 Session::template Deduced<ErrorOr<Reason>, C>
773 return initiate<LeaveOp>(std::forward<C>(completion), std::move(reason));
779 template <
typename C>
780 #ifdef CPPWAMP_FOR_DOXYGEN
781 Deduced<ErrorOr<Reason>, C>
783 Session::template Deduced<ErrorOr<Reason>, C>
792 return safelyInitiate<LeaveOp>(std::forward<C>(completion),
797 struct Session::SubscribeOp
803 template <
typename F>
void operator()(F&& f)
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));
824 template <
typename C>
825 #ifdef CPPWAMP_FOR_DOXYGEN
826 Deduced<ErrorOr<Subscription>, C>
828 Session::template Deduced<ErrorOr<Subscription>, C>
839 return initiate<SubscribeOp>(std::forward<C>(completion), std::move(topic),
840 std::move(eventSlot));
846 template <
typename C>
847 #ifdef CPPWAMP_FOR_DOXYGEN
848 Deduced<ErrorOr<Subscription>, C>
850 Session::template Deduced<ErrorOr<Subscription>, C>
862 return safelyInitiate<SubscribeOp>(std::forward<C>(completion),
863 std::move(topic), std::move(eventSlot));
867 struct Session::UnsubscribeOp
869 using ResultValue = bool;
872 template <
typename F>
void operator()(F&& f)
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));
902 template <
typename C>
903 #ifdef CPPWAMP_FOR_DOXYGEN
904 Deduced<ErrorOr<bool>, C>
906 Session::template Deduced<ErrorOr<bool>, C>
915 return initiate<UnsubscribeOp>(std::forward<C>(completion), sub);
921 template <
typename C>
922 #ifdef CPPWAMP_FOR_DOXYGEN
923 Deduced<ErrorOr<bool>, C>
925 Session::template Deduced<ErrorOr<bool>, C>
935 return safelyInitiate<UnsubscribeOp>(std::forward<C>(completion), sub);
939 struct Session::PublishOp
944 template <
typename F>
void operator()(F&& f)
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));
963 template <
typename C>
964 #ifdef CPPWAMP_FOR_DOXYGEN
965 Deduced<ErrorOr<PublicationId>, C>
967 Session::template Deduced<ErrorOr<PublicationId>, C>
975 return initiate<PublishOp>(std::forward<C>(completion), std::move(pub));
981 template <
typename C>
982 #ifdef CPPWAMP_FOR_DOXYGEN
983 Deduced<ErrorOr<PublicationId>, C>
985 Session::template Deduced<ErrorOr<PublicationId>, C>
994 return safelyInitiate<PublishOp>(std::forward<C>(completion),
999 struct Session::EnrollOp
1005 template <
typename F>
void operator()(F&& f)
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,
1031 template <
typename C>
1032 #ifdef CPPWAMP_FOR_DOXYGEN
1033 Deduced<ErrorOr<Registration>, C>
1035 Session::template Deduced<ErrorOr<Registration>, C>
1046 return initiate<EnrollOp>(
1047 std::forward<C>(completion), std::move(procedure), std::move(callSlot));
1053 template <
typename C>
1054 #ifdef CPPWAMP_FOR_DOXYGEN
1055 Deduced<ErrorOr<Registration>, C>
1057 Session::template Deduced<ErrorOr<Registration>, C>
1069 return safelyInitiate<EnrollOp>(
1070 std::forward<C>(completion), std::move(procedure), std::move(callSlot));
1074 struct Session::EnrollIntrOp
1081 template <
typename F>
void operator()(F&& f)
1083 CompletionHandler<ResultValue> handler(std::forward<F>(f));
1084 if (self->checkState<ResultValue>(State::established, handler))
1086 self->impl_->enroll(std::move(procedure), std::move(callSlot),
1087 std::move(interruptSlot), std::move(handler));
1107 template <
typename C>
1108 #ifdef CPPWAMP_FOR_DOXYGEN
1109 Deduced<ErrorOr<Registration>, C>
1111 Session::template Deduced<ErrorOr<Registration>, C>
1125 return initiate<EnrollIntrOp>(
1126 std::forward<C>(completion), std::move(procedure), std::move(callSlot),
1127 std::move(interruptSlot));
1133 template <
typename C>
1134 #ifdef CPPWAMP_FOR_DOXYGEN
1135 Deduced<ErrorOr<Registration>, C>
1137 Session::template Deduced<ErrorOr<Registration>, C>
1152 return safelyInitiate<EnrollIntrOp>(
1153 std::forward<C>(completion), std::move(procedure), std::move(callSlot),
1154 std::move(interruptSlot));
1158 struct Session::UnregisterOp
1160 using ResultValue = bool;
1163 template <
typename F>
void operator()(F&& f)
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));
1189 template <
typename C>
1190 #ifdef CPPWAMP_FOR_DOXYGEN
1191 Deduced<ErrorOr<bool>, C>
1193 Session::template Deduced<ErrorOr<bool>, C>
1202 return initiate<UnregisterOp>(std::forward<C>(completion), reg);
1208 template <
typename C>
1209 #ifdef CPPWAMP_FOR_DOXYGEN
1210 Deduced<ErrorOr<bool>, C>
1212 Session::template Deduced<ErrorOr<bool>, C>
1222 return safelyInitiate<UnregisterOp>(std::forward<C>(completion), reg);
1226 struct Session::CallOp
1228 using ResultValue =
Result;
1233 template <
typename F>
1234 void operator()(F&& f)
1238 auto chit =
call(std::is_copy_constructible<ValueTypeOf<F>>{},
1239 std::forward<F>(f));
1244 template <
typename F>
1245 CallChit
call(std::true_type, F&& f)
1251 MultiShotCallHandler handler(std::forward<F>(f));
1252 if (self->checkState<Result>(State::established, handler))
1253 chit =
self->impl_->ongoingCall(move(rpc), move(handler));
1257 OneShotCallHandler handler(std::forward<F>(f));
1258 if (self->checkState<Result>(State::established, handler))
1259 chit =
self->impl_->oneShotCall(move(rpc), move(handler));
1264 template <
typename F>
1265 CallChit
call(std::false_type, F&& f)
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));
1300 template <
typename C>
1301 #ifdef CPPWAMP_FOR_DOXYGEN
1302 Deduced<ErrorOr<Result>, C>
1304 Session::template Deduced<ErrorOr<Result>, C>
1312 return initiate<CallOp>(std::forward<C>(completion), std::move(rpc),
1319 template <
typename C>
1320 #ifdef CPPWAMP_FOR_DOXYGEN
1321 Deduced<ErrorOr<Result>, C>
1323 Session::template Deduced<ErrorOr<Result>, C>
1332 return safelyInitiate<CallOp>(std::forward<C>(completion), std::move(rpc),
1339 template <
typename C>
1340 #ifdef CPPWAMP_FOR_DOXYGEN
1341 Deduced<ErrorOr<Result>, C>
1343 Session::template Deduced<ErrorOr<Result>, C>
1352 return initiate<CallOp>(std::forward<C>(completion), std::move(rpc), &chit);
1358 template <
typename C>
1359 #ifdef CPPWAMP_FOR_DOXYGEN
1360 Deduced<ErrorOr<Result>, C>
1362 Session::template Deduced<ErrorOr<Result>, C>
1372 return safelyInitiate<CallOp>(std::forward<C>(completion), std::move(rpc),
1377 template <
typename O,
typename C,
typename... As>
1378 #ifdef CPPWAMP_FOR_DOXYGEN
1379 Deduced<ErrorOr<typename O::ResultValue>, C>
1381 Session::template Deduced<ErrorOr<typename O::ResultValue>, C>
1383 Session::initiate(C&& token, As&&... args)
1385 return boost::asio::async_initiate<
1387 O{
this, std::forward<As>(args)...}, token);
1391 template <
typename O,
typename C,
typename... As>
1392 #ifdef CPPWAMP_FOR_DOXYGEN
1393 Deduced<ErrorOr<typename O::ResultValue>, C>
1395 Session::template Deduced<ErrorOr<typename O::ResultValue>, C>
1397 Session::safelyInitiate(C&& token, As&&... args)
1400 return initiate<SafeOp<O>>(std::forward<C>(token),
1401 std::forward<As>(args)...);
1405 template <
typename F>
1406 void Session::dispatchViaStrand(F&& operation)
1408 boost::asio::dispatch(
strand(), std::forward<F>(operation));
1412 template <
typename TResultValue,
typename F>
1413 bool Session::checkState(State expectedState, F& handler)
1415 bool valid =
state() == expectedState;
1419 postVia(userExecutor_, std::move(handler), std::move(e));
1426 #ifndef CPPWAMP_COMPILED_LIB
1427 #include "internal/session.ipp"
1430 #endif // CPPWAMP_SESSION_HPP