mal-packet-weaver
C++20 packet serialization/deserialization library.
Loading...
Searching...
No Matches
dispatcher-session.hpp
Go to the documentation of this file.
1#pragma once
3#include "session.hpp"
4namespace mal_packet_weaver
5{
11 {
12 public:
18 DispatcherSession(boost::asio::io_context &io_context, boost::asio::ip::tcp::socket &&socket)
19 : io_context_{ io_context },
20 session_{ std::make_shared<Session>(io_context, std::move(socket)) },
21 dispatcher_{ std::make_shared<PacketDispatcher>(io_context) }
22 {
23 session_->set_packet_receiver([&dispatcher_ = *dispatcher_](std::unique_ptr<Packet> &&packet)
24 __mal_toolkit_lambda_force_inline { dispatcher_.enqueue_packet(std::move(packet)); });
25 }
26
32 {
33 if (session_ != nullptr)
34 {
35 session_->Destroy();
36 }
37 if (dispatcher_ != nullptr)
38 {
39 dispatcher_->Destroy();
40 }
41 }
42
57 template <IsPacket T>
58 inline bool send_packet(const T &packet_arg) requires std::is_base_of_v<Packet, T>
59 {
60 return session_->send_packet(packet_arg);
61 }
62
73 inline std::unique_ptr<Packet> pop_packet_now() { return session_->pop_packet_now(); }
74
81 inline boost::asio::awaitable<std::unique_ptr<Packet>> pop_packet_async()
82 {
83 auto value = co_await session_->pop_packet_async(io_context_);
84 co_return std::move(value);
85 }
86
93 [[nodiscard]] inline bool has_packets() { return session_->has_packets(); }
94
101 [[nodiscard]] inline bool secured() const noexcept { return session_->secured(); }
102
109 [[nodiscard]] constexpr bool is_closed() const noexcept { return session_->is_closed(); }
110
117 [[nodiscard]] constexpr bool alive() const noexcept { return session_->alive(); }
118
123 inline void setup_encryption(std::shared_ptr<mal_packet_weaver::crypto::EncryptionInterface> encryption)
124 {
125 session_->setup_encryption(encryption);
126 }
127
134 inline void set_packet_receiver(PacketReceiverFn const receiver) { session_->set_packet_receiver(receiver); }
135
145 {
146 dispatcher_->enqueue_packet(std::move(packet));
147 }
148
163 template <IsPacket DerivedPacket>
164 boost::asio::awaitable<std::unique_ptr<DerivedPacket>> await_packet(float timeout = -1.0f)
165 {
166 return dispatcher_->await_packet<DerivedPacket>(timeout);
167 }
168
187 template <IsPacket DerivedPacket>
188 boost::asio::awaitable<std::unique_ptr<DerivedPacket>> await_packet(PacketFilterFunc<DerivedPacket> filter,
189 float timeout = -1.0f)
190 {
191 return dispatcher_->await_packet<DerivedPacket>(filter, timeout);
192 }
193
212 template <IsPacket DerivedPacket>
214 PacketFilterFunc<DerivedPacket> filter = {}, float delay = 0.0f)
215 {
216 return dispatcher_->register_default_handler(handler, filter, delay);
217 }
238 template <typename Arg1, IsPacket CustomPacket>
240 PacketFilterFunc<CustomPacket, Arg1> &&filter = {}, float delay = 0.0f)
241 {
242 if constexpr (std::is_same_v<Arg1, std::shared_ptr<Session>>)
243 {
245 [session_ = std::weak_ptr<Session>(session_), moved_handler = std::move(handler)](
246 std::unique_ptr<CustomPacket> &&packet) { moved_handler(session_.lock(), std::move(packet)); },
247 (bool(filter) ? ([session_ = std::weak_ptr<Session>(session_), moved_filter = std::move(filter)](
248 const CustomPacket &packet) { return moved_filter(session_.lock(), packet); })
249 : PacketFilterFunc<CustomPacket>{}),
250 delay);
251 }
252 else if constexpr (std::is_same_v<Arg1, Session &>)
253 {
255 [session_ = std::weak_ptr<Session>(session_), moved_handler = std::move(handler)](
256 std::unique_ptr<CustomPacket> &&packet) { moved_handler(*session_.lock(), std::move(packet)); },
257 (bool(filter) ? ([session_ = std::weak_ptr<Session>(session_), moved_filter = std::move(filter)](
258 const CustomPacket &packet) { return moved_filter(*session_.lock(), packet); })
259 : PacketFilterFunc<CustomPacket>{}),
260 delay);
261 }
262 else if constexpr (std::is_same_v<Arg1, boost::asio::io_context &>)
263 {
265 [io_context_ = std::ref(io_context_), moved_handler = std::move(handler)](
266 std::unique_ptr<CustomPacket> &&packet) { moved_handler(io_context_, std::move(packet)); },
267 (bool(filter) ? ([io_context_ = std::ref(io_context_), moved_filter = std::move(filter)](
268 const CustomPacket &packet) { return moved_filter(io_context_, packet); })
269 : PacketFilterFunc<CustomPacket>{}),
270 delay);
271 }
272 else if constexpr (std::is_same_v<Arg1, std::shared_ptr<PacketDispatcher>>)
273 {
275 [dispatcher_ = std::weak_ptr<PacketDispatcher>(dispatcher_),
276 moved_handler = std::move(handler)](std::unique_ptr<CustomPacket> &&packet)
277 { moved_handler(dispatcher_.lock(), std::move(packet)); },
278 (bool(filter) ? ([dispatcher_ = std::weak_ptr<PacketDispatcher>(dispatcher_),
279 moved_filter = std::move(filter)](const CustomPacket &packet)
280 { return moved_filter(dispatcher_.lock(), packet); })
281 : PacketFilterFunc<CustomPacket>{}),
282 delay);
283 }
284 else if constexpr (std::is_same_v<Arg1, PacketDispatcher &>)
285 {
287 [dispatcher_ = std::weak_ptr<PacketDispatcher>(dispatcher_),
288 moved_handler = std::move(handler)](std::unique_ptr<CustomPacket> &&packet)
289 { moved_handler(*dispatcher_.lock(), std::move(packet)); },
290 (bool(filter) ? ([dispatcher_ = std::weak_ptr<PacketDispatcher>(dispatcher_),
291 moved_filter = std::move(filter)](const CustomPacket &packet)
292 { return moved_filter(*dispatcher_.lock(), packet); })
293 : PacketFilterFunc<CustomPacket>{}),
294 delay);
295 }
296 else
297 {
298 []<bool flag = false>()
299 {
300 static_assert(flag,
301 "Unknown type passed! Supported types for handler are: Session&, "
302 "std::shared_ptr<Session>, io_context &, std::shared_ptr<PacketDispatcher> and "
303 "PacketDispatcher&. The CustomPacket type should be last.");
304 }
305 ();
306 }
307 }
308
330 template <typename Arg1, typename Arg2, typename... Args, IsPacket CustomPacket>
333 float delay = 0.0f)
334 {
335 if constexpr (std::is_same_v<Arg1, std::shared_ptr<Session>>)
336 {
337 return register_default_handler<Arg2, Args..., CustomPacket>(
338 [session_ = std::weak_ptr<Session>(session_), moved_handler = std::move(handler)](
339 Arg2 &&arg2, Args &&...args, std::unique_ptr<CustomPacket> &&packet) {
340 moved_handler(session_.lock(), std::forward<Arg2>(arg2), std::forward<Args>(args)...,
341 std::move(packet));
342 },
343 (bool(filter) ? (
344 [session_ = std::weak_ptr<Session>(session_), moved_filter = std::move(filter)](
345 Arg2 &&arg2, Args &&...args, const CustomPacket &packet) {
346 return moved_filter(session_.lock(), std::forward<Arg2>(arg2),
347 std::forward<Args>(args)..., packet);
348 })
349 : PacketFilterFunc<CustomPacket, Arg2, Args...>{}),
350 delay);
351 }
352 else if constexpr (std::is_same_v<Arg1, Session &>)
353 {
354 return register_default_handler<Arg2, Args..., CustomPacket>(
355 [session_ = std::weak_ptr<Session>(session_), moved_handler = std::move(handler)](
356 Arg2 &&arg2, Args &&...args, std::unique_ptr<CustomPacket> &&packet) {
357 moved_handler(*session_.lock(), std::forward<Arg2>(arg2), std::forward<Args>(args)...,
358 std::move(packet));
359 },
360 (bool(filter) ? (
361 [session_ = std::weak_ptr<Session>(session_), moved_filter = std::move(filter)](
362 Arg2 &&arg2, Args &&...args, const CustomPacket &packet) {
363 return moved_filter(*session_.lock(), std::forward<Arg2>(arg2),
364 std::forward<Args>(args)..., packet);
365 })
366 : PacketFilterFunc<CustomPacket, Arg2, Args...>{}),
367 delay);
368 }
369 else if constexpr (std::is_same_v<Arg1, boost::asio::io_context &>)
370 {
371 return register_default_handler<Arg2, Args..., CustomPacket>(
372 [io_context_ = std::ref(io_context_), moved_handler = std::move(handler)](
373 Arg2 &&arg2, Args &&...args, std::unique_ptr<CustomPacket> &&packet) {
374 moved_handler(io_context_, std::forward<Arg2>(arg2), std::forward<Args>(args)...,
375 std::move(packet));
376 },
377 (bool(filter) ? (
378 [io_context_ = std::ref(io_context_), moved_filter = std::move(filter)](
379 Arg2 &&arg2, Args &&...args, const CustomPacket &packet) {
380 return moved_filter(io_context_, std::forward<Arg2>(arg2),
381 std::forward<Args>(args)..., packet);
382 })
383 : PacketFilterFunc<CustomPacket, Arg2, Args...>{}),
384 delay);
385 }
386 else if constexpr (std::is_same_v<Arg1, std::shared_ptr<PacketDispatcher>>)
387 {
388 return register_default_handler<Arg2, Args..., CustomPacket>(
389 [dispatcher_ = std::weak_ptr<PacketDispatcher>(dispatcher_), moved_handler = std::move(handler)](
390 Arg2 &&arg2, Args &&...args, std::unique_ptr<CustomPacket> &&packet) {
391 moved_handler(dispatcher_.lock(), std::forward<Arg2>(arg2), std::forward<Args>(args)...,
392 std::move(packet));
393 },
394 (bool(filter) ? (
395 [dispatcher_ = std::weak_ptr<PacketDispatcher>(dispatcher_),
396 moved_filter = std::move(filter)](Arg2 &&arg2, Args &&...args,
397 const CustomPacket &packet) {
398 return moved_filter(dispatcher_.lock(), std::forward<Arg2>(arg2),
399 std::forward<Args>(args)..., packet);
400 })
401 : PacketFilterFunc<CustomPacket, Arg2, Args...>{}),
402 delay);
403 }
404 else if constexpr (std::is_same_v<Arg1, PacketDispatcher &>)
405 {
406 return register_default_handler<Arg2, Args..., CustomPacket>(
407 [dispatcher_ = std::weak_ptr<PacketDispatcher>(dispatcher_), moved_handler = std::move(handler)](
408 Arg2 &&arg2, Args &&...args, std::unique_ptr<CustomPacket> &&packet) {
409 moved_handler(*dispatcher_.lock(), std::forward<Arg2>(arg2), std::forward<Args>(args)...,
410 std::move(packet));
411 },
412 (bool(filter) ? (
413 [dispatcher_ = std::weak_ptr<PacketDispatcher>(dispatcher_),
414 moved_filter = std::move(filter)](Arg2 &&arg2, Args &&...args,
415 const CustomPacket &packet) {
416 return moved_filter(*dispatcher_.lock(), std::forward<Arg2>(arg2),
417 std::forward<Args>(args)..., packet);
418 })
419 : PacketFilterFunc<CustomPacket, Arg2, Args...>{}),
420 delay);
421 }
422 else
423 {
424 []<bool flag = false>()
425 {
426 static_assert(flag,
427 "Unknown type passed! Supported types for handler are: Session&, "
428 "std::shared_ptr<Session>, io_context &, std::shared_ptr<PacketDispatcher> and "
429 "PacketDispatcher&. The CustomPacket type should be last.");
430 }
431 ();
432 }
433 }
434
435 template <IsPacket CustomPacket, typename... FnArgs>
436 inline void register_default_handler(std::function<void(FnArgs...)> &&handler,
437 std::function<bool(FnArgs...)> &&filter = {}, float delay = 0.0f)
438 {
439 return register_default_handler<FnArgs..., CustomPacket>(handler, filter, delay);
440 }
452 {
453 return dispatcher_->enqueue_promise(packet_id, promise);
454 }
455
468 {
469 return dispatcher_->enqueue_filter_promise(packet_id, filtered_promise);
470 }
471
476 [[nodiscard]] inline Session &session() { return *session_; }
477
482 [[nodiscard]] inline PacketDispatcher &dispatcher() { return *dispatcher_; }
483
484 void Destroy()
485 {
486 session_->Destroy();
487 dispatcher_->Destroy();
488 }
489
490 private:
491 boost::asio::io_context &io_context_;
492 std::shared_ptr<Session> session_;
493 std::shared_ptr<PacketDispatcher> dispatcher_;
494 };
495} // namespace mal_packet_weaver
A templated class representing a derived packet from the base Packet class.
Definition packet.hpp:114
Represents a session with packet dispatching functionality.
bool has_packets()
Checks if there are packets in the queue.
void register_default_handler(std::function< void(FnArgs...)> &&handler, std::function< bool(FnArgs...)> &&filter={}, float delay=0.0f)
constexpr bool alive() const noexcept
Checks if the session is alive.
void set_packet_receiver(PacketReceiverFn const receiver)
Sets the packet receiver for the session.
boost::asio::awaitable< std::unique_ptr< DerivedPacket > > await_packet(float timeout=-1.0f)
Wait until the packet is registered in the dispatch system and return as soon as possible.
boost::asio::io_context & io_context_
Reference to the associated Boost.Asio io_context.
void enqueue_promise(UniquePacketID packet_id, PacketDispatcher::shared_packet_promise promise)
Enqueues a promise associated with a packet.
~DispatcherSession()
Destructor for DispatcherSession. Cleans up the session and packet dispatcher.
void register_default_handler(PacketHandlerFunc< CustomPacket, Arg1 > &&handler, PacketFilterFunc< CustomPacket, Arg1 > &&filter={}, float delay=0.0f)
Register a default handler for the provided packet type.
PacketDispatcher & dispatcher()
Get a reference to the underlying packet dispatcher.
void register_default_handler(PacketHandlerFunc< DerivedPacket > handler, PacketFilterFunc< DerivedPacket > filter={}, float delay=0.0f)
Registers a default handler for the provided packet type.
void register_default_handler(PacketHandlerFunc< CustomPacket, Arg1, Arg2, Args... > &&handler, PacketFilterFunc< CustomPacket, Arg1, Arg2, Args... > &&filter={}, float delay=0.0f)
Register a default handler for the provided packet type.
std::unique_ptr< Packet > pop_packet_now()
Returns the earliest acquired packet. If packet queue is empty, returns nullptr.
DispatcherSession(boost::asio::io_context &io_context, boost::asio::ip::tcp::socket &&socket)
Constructor for DispatcherSession.
std::shared_ptr< Session > session_
The underlying session.
boost::asio::awaitable< std::unique_ptr< DerivedPacket > > await_packet(PacketFilterFunc< DerivedPacket > filter, float timeout=-1.0f)
Wait until a packet satisfying the filter condition is registered in the dispatch system and return a...
bool send_packet(const T &packet_arg)
Sends any packet derived from DerivedPacket through the network.
boost::asio::awaitable< std::unique_ptr< Packet > > pop_packet_async()
bool secured() const noexcept
Checks if the session is secured using encryption.
void enqueue_filter_promise(UniquePacketID packet_id, PacketDispatcher::promise_filter filtered_promise)
Enqueues a promise with a filter associated with a packet.
constexpr bool is_closed() const noexcept
Checks if the session is closed.
Session & session()
Get a reference to the underlying session.
std::shared_ptr< PacketDispatcher > dispatcher_
The underlying packet dispatcher.
void setup_encryption(std::shared_ptr< mal_packet_weaver::crypto::EncryptionInterface > encryption)
Sets up encryption for the session using provided encryption interface.
void enqueue_packet(PacketDispatcher::BasePacketPtr &&packet)
Enqueues a packet for processing.
The PacketDispatcher class is responsible for managing packet dispatching and handling.
shared_promise< BasePacketPtr > shared_packet_promise
Alias for a shared promise of a base packet pointer.
std::unique_ptr< Packet > BasePacketPtr
Alias for a unique pointer to a base packet type.
std::pair< std::function< bool(BasePacketPtr const &)>, shared_packet_promise > promise_filter
Alias for a filter function paired with a shared packet promise.
Represents a network session for sending and receiving packets.
Definition session.hpp:17
A class that can't be copied neither moved.
This is the main namespace for the Mal Packet Weaver library.
Definition common.hpp:42
std::function< bool(Args..., DerivedPacket const &)> PacketFilterFunc
Predicate function type to filter packets.
std::function< void(std::unique_ptr< Packet > &&)> PacketReceiverFn
Definition session.hpp:7
std::function< void(Args..., std::unique_ptr< DerivedPacket >)> PacketHandlerFunc
Callback function type to handle packets asynchronously.
uint32_t UniquePacketID
Unique identifier for a packet, combining subsystem and packet IDs.
Definition packet.hpp:16
STL namespace.