link_client.h 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #pragma once
  2. //
  3. // Copyright (c) 2019-2021 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_map>
  10. #include <functional>
  11. #include <forward_list>
  12. namespace rotor::plugin {
  13. /** \struct link_client_plugin_t
  14. *
  15. * \brief allows actor to have active (client) role in linking
  16. *
  17. * The plugin keeps records of all "servers" where it is connected to.
  18. * When actor is going to shutdown it will notify peers about unlinking.
  19. *
  20. * It is allowed to have a custom actors' callback on every link result.
  21. * connected clients will send unlink confirmation (or until
  22. * timeout will trigger).
  23. *
  24. */
  25. struct link_client_plugin_t : public plugin_base_t {
  26. /** \brief callback action upon link */
  27. using link_callback_t = std::function<void(const extended_error_ptr_t &)>;
  28. /** \brief unlink interceptor callback
  29. *
  30. * if it returns true, the unlink is not performed. It is assumed,
  31. * that `forget_link` will be called later
  32. */
  33. using unlink_reaction_t = std::function<bool(message::unlink_request_t &message)>;
  34. using plugin_base_t::plugin_base_t;
  35. /** The plugin unique identity to allow further static_cast'ing*/
  36. static const void *class_identity;
  37. const void *identity() const noexcept override;
  38. void activate(actor_base_t *actor) noexcept override;
  39. /** \brief attempt to link with the address
  40. *
  41. * If `operational_only` is set, then the server side will respond
  42. * only upon becoming operational.
  43. *
  44. * The link callback is always invoked upon response (successful or
  45. * nor) receiving.
  46. *
  47. */
  48. virtual void link(const address_ptr_t &address, bool operational_only = true,
  49. const link_callback_t &callback = {}) noexcept;
  50. /** \brief sets actor's callback on unlink request */
  51. template <typename F> void on_unlink(F &&callback) noexcept { unlink_reaction = std::forward<F>(callback); }
  52. /** \brief handler for link response */
  53. virtual void on_link_response(message::link_response_t &message) noexcept;
  54. /** \brief handler for unlink request */
  55. virtual void on_unlink_request(message::unlink_request_t &message) noexcept;
  56. bool handle_shutdown(message::shutdown_request_t *message) noexcept override;
  57. bool handle_init(message::init_request_t *message) noexcept override;
  58. /** \brief continues previously suspended unlink request */
  59. void forget_link(message::unlink_request_t &message) noexcept;
  60. private:
  61. enum class link_state_t { LINKING, OPERATIONAL, UNLINKING };
  62. struct server_record_t {
  63. link_callback_t callback;
  64. link_state_t state;
  65. request_id_t request_id;
  66. };
  67. using servers_map_t = std::unordered_map<address_ptr_t, server_record_t>;
  68. using unlink_req_t = intrusive_ptr_t<message::unlink_request_t>;
  69. using unlink_queue_t = std::list<unlink_req_t>;
  70. void try_forget_links(bool attempt_shutdown) noexcept;
  71. servers_map_t servers_map;
  72. unlink_reaction_t unlink_reaction;
  73. unlink_queue_t unlink_queue;
  74. bool configured = false;
  75. };
  76. } // namespace rotor::plugin