link_server.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #pragma once
  2. //
  3. // Copyright (c) 2019-2020 Ivan Baidakou (basiliscos) (the dot dmol at gmail dot com)
  4. //
  5. // Distributed under the MIT Software License
  6. //
  7. #include "plugin_base.h"
  8. #include <string>
  9. #include <unordered_set>
  10. #include <functional>
  11. #include <optional>
  12. namespace rotor::plugin {
  13. /** \struct link_server_plugin_t
  14. *
  15. * \brief allows actor to have passive (server) role in linking
  16. *
  17. * The plugin keeps records of connected clients. When actor is
  18. * going to shutdown it will block shutdown process until all
  19. * connected clients will send unlink confirmation (or until
  20. * timeout will trigger).
  21. *
  22. */
  23. struct link_server_plugin_t : public plugin_base_t {
  24. using plugin_base_t::plugin_base_t;
  25. /** The plugin unique identity to allow further static_cast'ing*/
  26. static const void *class_identity;
  27. const void *identity() const noexcept override;
  28. void activate(actor_base_t *actor) noexcept override;
  29. /** \brief reaction upon link request */
  30. virtual void on_link_request(message::link_request_t &message) noexcept;
  31. /** \brief reaction upon link unlink response */
  32. virtual void on_unlink_response(message::unlink_response_t &message) noexcept;
  33. /** \brief reaction upon link unlink notify */
  34. virtual void on_unlink_notify(message::unlink_notify_t &message) noexcept;
  35. bool handle_shutdown(message::shutdown_request_t *message) noexcept override;
  36. void handle_start(message::start_trigger_t *message) noexcept override;
  37. /** \brief returns true if there is any connected client */
  38. virtual bool has_clients() noexcept { return !linked_clients.empty(); }
  39. /** \brief let clients know that the actor is going to shut self down */
  40. virtual void notify_shutdown() noexcept;
  41. /** \brief generic non-public fields accessor */
  42. template <typename T> auto &access() noexcept;
  43. private:
  44. enum class link_state_t { PENDING, OPERATIONAL, UNLINKING };
  45. using link_request_ptr_t = intrusive_ptr_t<message::link_request_t>;
  46. using request_option_t = std::optional<request_id_t>;
  47. struct link_info_t {
  48. link_info_t(link_state_t state_, link_request_ptr_t request_) noexcept : state{state_}, request{request_} {}
  49. link_state_t state;
  50. link_request_ptr_t request;
  51. request_option_t unlink_request;
  52. bool shutdown_notified = false;
  53. };
  54. using linked_clients_t = std::unordered_map<address_ptr_t, link_info_t>;
  55. linked_clients_t linked_clients;
  56. };
  57. } // namespace rotor::plugin