1 /*************************************************************************
6 * [2011] - [2012] Realm Inc
9 * NOTICE: All information contained herein is, and remains
10 * the property of Realm Incorporated and its suppliers,
11 * if any. The intellectual and technical concepts contained
12 * herein are proprietary to Realm Incorporated
13 * and its suppliers and may be covered by U.S. and Foreign Patents,
14 * patents in process, and are protected by trade secret or copyright law.
15 * Dissemination of this information or reproduction of this material
16 * is strictly forbidden unless prior written permission is obtained
17 * from Realm Incorporated.
19 **************************************************************************/
20 #ifndef REALM_SYNC_SERVER_HPP
21 #define REALM_SYNC_SERVER_HPP
27 #include <realm/util/network.hpp>
28 #include <realm/util/logger.hpp>
29 #include <realm/util/optional.hpp>
30 #include <realm/sync/crypto_server.hpp>
31 #include <realm/sync/metrics.hpp>
38 class TokenExpirationClock;
43 /// The maximum number of Realm files that will be kept open
44 /// concurrently by this server. The server keeps a cache of open Realm
45 /// files for efficiency reasons.
46 long max_open_files = 256;
48 /// An optional custom clock to be used for token expiration checks. If
49 /// no clock is specified, the server will use the system clock.
50 TokenExpirationClock* token_expiration_clock = nullptr;
52 /// An optional logger to be used by the server. If no logger is
53 /// specified, the server will use an instance of util::StderrLogger
54 /// with the log level threshold set to util::Logger::Level::info. The
55 /// server does not require a thread-safe logger, and it guarantees that
56 /// all logging happens on behalf of start() and run() (which are not
57 /// allowed to execute concurrently).
58 util::Logger* logger = nullptr;
60 /// An optional sink for recording metrics about the internal operation
61 /// of the server. For the list of counters and gauges see
62 /// "doc/monitoring.md".
63 Metrics* metrics = nullptr;
65 /// A unique id of this server. Used in the backup protocol to tell
67 std::string id = "unknown";
69 /// The address at which the listening socket is bound.
70 /// The address can be a name or on numerical form.
71 /// Use "localhost" to listen on the loopback interface.
72 std::string listen_address;
74 /// The port at which the listening socket is bound.
75 /// The port can be a name or on numerical form.
76 /// Use the empty string to have the system assign a dynamic
78 std::string listen_port;
80 bool reuse_address = true;
82 /// The listening socket accepts TLS/SSL connections if `ssl` is
83 /// true, and non-secure tcp connections otherwise.
86 /// The path of the certificate that will be sent to clients during
87 /// the SSL/TLS handshake.
89 /// From the point of view of OpenSSL, this file will be passed to
90 /// `SSL_CTX_use_certificate_chain_file()`.
92 /// This option is ignore if `ssl` is false.
93 std::string ssl_certificate_path;
95 /// The path of the private key corresponding to the certificate.
97 /// From the point of view of OpenSSL, this file will be passed to
98 /// `SSL_CTX_use_PrivateKey_file()`.
100 /// This option is ignore if `ssl` is false.
101 std::string ssl_certificate_key_path;
103 // A connection which has not been sending any messages or pings for
104 // `idle_timeout_ms` is considered dead and will be dropped by the server.
105 uint_fast64_t idle_timeout_ms = 1800000; // 30 minutes
107 // How often the server scans through the connection list to drop idle ones.
108 uint_fast64_t drop_period_ms = 60000; // 1 minute
110 /// @{ \brief The operating mode of the Sync worker.
112 /// MasterWithNoSlave is a standard Sync worker without backup.
113 /// If a backup slave attempts to contact a MasterNoBackup server,
114 /// the slave will be rejected.
116 /// MasterWithAsynchronousSlave represents a Sync worker that operates
117 /// independently of a backup slave. If a slave connects to the
118 /// MasterAsynchronousSlave server, the server will accept the connection
119 /// and send backup information to the slave. This type of master server
120 /// will never wait for the slave, however.
122 /// MasterWithSynchronousSlave represents a Sync worker that works in
123 /// coordination with a slave. The master will send all updates to the
124 /// slave and wait for acknowledgment before the master sends its own
125 /// acknowledgment to the clients. This mode of operation is the safest
126 /// type of backup, but it generally will have higher latency than the previous
127 /// two types of server.
129 /// Slave represents a backup server. A slave is used to backup a master.
130 /// The slave connects to the master and reconnects in case a network fallout.
131 /// The slave receives updates from the master and acknowledges them.
132 /// A slave rejects all connections from Sync clients.
133 enum class OperatingMode {
135 MasterWithAsynchronousSlave,
136 MasterWithSynchronousSlave,
139 OperatingMode operating_mode = OperatingMode::MasterWithNoSlave;
142 /// @{ \brief Adress of master sync work.
144 /// master_address and master_port are only meaningful in Slave mode.
145 /// The parameters represent the address of the master from which this
146 /// slave obtains Realm updates.
147 std::string master_address;
148 std::string master_port;
151 /// @{ \brief SSL for master slave communication.
153 /// The master and slave communicate over a SSL connection if
154 /// master_slave_ssl is set to true(default = false). The certificate of the
155 /// master is verified if master_verify_ssl_certificate is set to true.
156 /// The certificate verification attempts to use the default trust store of the
157 /// instance if master_ssl_trust_certificate_path is none(default), otherwise
158 /// the certificate at the master_ssl_trust_certificate_path is used for
160 bool master_slave_ssl = false;
161 bool master_verify_ssl_certificate = true;
162 util::Optional<std::string> master_ssl_trust_certificate_path = util::none;
165 /// A master Sync server will only accept a backup connection from a slave
166 /// that can present the correct master_slave_shared_secret.
167 /// The configuration of the master and the slave must contain the same
169 /// The secret is sent in a HTTP header and must be a valid HTTP header value.
170 std::string master_slave_shared_secret = "replace-this-string-with-a-secret";
172 /// A callback which gets called by the backup master every time the slave
173 /// changes its status to up-to-date or back. The arguments carry the
174 /// slave's id (string) and its up-to-dateness state (bool).
175 std::function<void(std::string, bool)> slave_status_callback;
177 /// The feature token is used by the server to gate access to various
179 util::Optional<std::string> feature_token;
181 /// The server can try to eliminate redundant instructions from
182 /// changesets before sending them to clients, minimizing download sizes
183 /// at the expense of server CPU usage.
184 bool enable_download_log_compaction = true;
186 /// The accumulated size of changesets that are included in download
187 /// messages. The size of the changesets is calculated before log
188 /// compaction (if enabled). A larger value leads to more efficient
189 /// log compaction and download, at the expense of higher memory pressure,
190 /// higher latency for sending the first changeset, and a higher probability
191 /// for the need to resend the same changes after network disconnects.
192 size_t max_download_size = 0x20000; // 128 KiB
194 /// Set the `TCP_NODELAY` option on all TCP/IP sockets. This disables
195 /// the Nagle algorithm. Disabling it, can in some cases be used to
196 /// decrease latencies, but possibly at the expense of scalability. Be
197 /// sure to research the subject before you enable this option.
198 bool tcp_no_delay = false;
201 Server(const std::string& root_dir, util::Optional<PKey> public_key, Config = {});
202 Server(Server&&) noexcept;
205 /// start() binds a listening socket to the address and port specified in
206 /// Config and starts accepting connections.
207 /// The resolved endpoint (including the dynamically assigned port, if requested)
208 /// can be obtained by calling listen_endpoint().
209 /// This can be done immediately after start() returns.
212 /// A helper function, for backwards compatibility, that starts a listening
213 /// socket without SSL at the specified address and port.
214 void start(const std::string& listen_address,
215 const std::string& listen_port,
216 bool reuse_address = true);
218 /// Return the resolved and bound endpoint of the listening socket.
219 util::network::Endpoint listen_endpoint() const;
221 /// Run the internal event-loop of the server. At most one thread may
222 /// execute run() at any given time. It is an error if run() is called
223 /// before start() has been successfully executed. The call to run() will
224 /// not return until somebody calls stop().
227 /// Stop any thread that is currently executing run(). This function may be
228 /// called by any thread.
229 void stop() noexcept;
231 /// Must not be called while run() is executing.
232 uint_fast64_t errors_seen() const noexcept;
234 /// A connection which has not been sending any messages or pings for
235 /// `idle_timeout_ms` is considered idle and will be dropped by the server.
236 void set_idle_timeout_ms(uint_fast64_t idle_timeout_ms);
238 /// Close all connections with error code ProtocolError::connection_closed.
240 /// This function exists mainly for debugging purposes.
241 void close_connections();
244 class Implementation;
245 std::unique_ptr<Implementation> m_impl;
249 class Server::TokenExpirationClock {
251 /// Number of seconds since the Epoch. The Epoch is the epoch of
252 /// std::chrono::system_clock.
253 virtual std::int_fast64_t now() noexcept = 0;
255 virtual ~TokenExpirationClock() {}
261 #endif // REALM_SYNC_SERVER_HPP