1 #pragma once 2 3 #ifndef SERVER_H_S0HB5KXY 4 #define SERVER_H_S0HB5KXY 5 6 #include "rpc/config.h" 7 #include "rpc/msgpack.hpp" 8 #include "rpc/dispatcher.h" 9 10 #include "rpc/detail/pimpl.h" 11 12 namespace rpc { 13 14 namespace detail { 15 class server_session; 16 } 17 18 //! \brief Implements a msgpack-rpc server. This is the main interfacing 19 //! point with the library for creating servers. 20 //! 21 //! The server maintains a registry of function bindings that it uses to 22 //! dispatch calls. It also takes care of managing worker threads and TCP 23 //! connections. 24 //! The server does not start listening right after construction in order 25 //! to allow binding functions before that. Use the `run` or `async_run` 26 //! functions to start listening on the port. 27 class server { 28 public: 29 //! \brief Constructs a server that listens on the localhost on the 30 //! specified port. 31 //! 32 //! \param port The port number to listen on. 33 explicit server(uint16_t port); 34 35 //! \brief Constructs a server that listens on the specified address on 36 //! the specified port. 37 //! 38 //! \param port The port number to listen on. 39 server(std::string const &address, uint16_t port); 40 41 //! \brief Destructor. 42 //! 43 //! When the server is destroyed, all ongoin sessions are closed gracefully. 44 ~server(); 45 46 //! \brief Starts the server loop. This is a blocking call. 47 //! 48 //! First and foremost, running the event loop causes the server to start 49 //! listening on the specified port. Also, as connections are established 50 //! and calls are made by clients, the server executes the calls as part 51 //! of this call. This means that the handlers are executed on the thread 52 //! that calls `run`. Reads and writes are initiated by this function 53 //% internally as well. 54 void run(); 55 56 //! \brief Starts the server loop on one or more threads. This is a 57 //! non-blocking call. 58 //! 59 //! This function behaves similarly to `run`, except the event loop is 60 //! optionally started on different threads. Effectively this sets up a 61 //! worker thread pool for the server. Handlers will be executed on one 62 //! of the threads. 63 //! 64 //! \param worker_threads The number of worker threads to start. 65 void async_run(std::size_t worker_threads = 1); 66 67 //! \brief Binds a functor to a name so it becomes callable via RPC. 68 //! 69 //! This function template accepts a wide range of callables. The arguments 70 //! and return types of these callables should be serializable by msgpack. 71 //! `bind` effectively generates a suitable, light-weight compile-time 72 //! wrapper for the functor. 73 //! 74 //! \param name The name of the functor. 75 //! \param func The functor to bind. 76 //! \tparam F The type of the functor. bind(std::string const & name,F func)77 template <typename F> void bind(std::string const &name, F func) { 78 disp_->bind(name, func); 79 } 80 81 //! \brief Sets the exception behavior in handlers. By default, 82 //! handlers throwing will crash the server. If suppressing is on, 83 //! the server will try to gather textual data and return it to 84 //! the client as an error response. 85 //! \note Setting this flag only affects subsequent connections. 86 void suppress_exceptions(bool suppress); 87 88 //! \brief Stops the server. 89 //! \note This should not be called from worker threads. 90 void stop(); 91 92 //! \brief Closes all sessions gracefully. 93 void close_sessions(); 94 95 friend class detail::server_session; 96 97 private: 98 RPCLIB_DECLARE_PIMPL() 99 std::shared_ptr<detail::dispatcher> disp_; 100 }; 101 102 } /* rpc */ 103 104 #endif /* end of include guard: SERVER_H_S0HB5KXY */ 105