Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/daemon.cpp
4 : : \copyright 2022-2025 J. Bakosi,
5 : : All rights reserved. See the LICENSE file for details.
6 : : \brief Piac daemon
7 : : */
8 : : // *****************************************************************************
9 : :
10 : : #include <vector>
11 : : #include <iostream>
12 : : #include <thread>
13 : : #include <mutex>
14 : : #include <condition_variable>
15 : :
16 : : #include <getopt.h>
17 : : #include <unistd.h>
18 : :
19 : : #include "macro.hpp"
20 : : #include "project_config.hpp"
21 : : #include "logging_util.hpp"
22 : : #include "daemon_p2p_thread.hpp"
23 : : #include "daemon_db_thread.hpp"
24 : :
25 : 11 : [[noreturn]] static void s_signal_handler( int /*signal_value*/ ) {
26 [ + - ][ + - ]: 22 : MDEBUG( "interrupted" );
27 : 11 : exit( EXIT_SUCCESS );
28 : : }
29 : :
30 : : #if defined(__clang__)
31 : : #pragma clang diagnostic push
32 : : #pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
33 : : #endif
34 : :
35 : 11 : static void s_catch_signals() {
36 : : struct sigaction action;
37 : 11 : action.sa_handler = s_signal_handler;
38 : 11 : action.sa_flags = 0;
39 : 11 : sigemptyset( &action.sa_mask );
40 : 11 : sigaction( SIGINT, &action, nullptr );
41 : 11 : sigaction( SIGTERM, &action, nullptr );
42 : 11 : }
43 : :
44 : : #if defined(__clang__)
45 : : #pragma clang diagnostic pop
46 : : #endif
47 : :
48 : : namespace piac {
49 : :
50 : : std::mutex g_hashes_mtx;
51 : : std::condition_variable g_hashes_cv;
52 : : bool g_hashes_access = false;
53 : :
54 : : static void
55 [ - + ]: 1 : save_public_key( const std::string& filename, const std::string& public_key )
56 : : // *****************************************************************************
57 : : //! Save generated public key to file
58 : : //! \param[in] filename File to save keys to
59 : : //! \param[in] public_key Public key to save
60 : : // *****************************************************************************
61 : : {
62 [ - + ]: 1 : if (filename.empty()) return;
63 : 2 : std::ofstream f( filename );
64 [ + - ]: 1 : if (f.is_open()) {
65 : : f << public_key;
66 [ + - ]: 1 : f.close();
67 [ + - ][ + - ]: 2 : MINFO( "Public key saved to file: " << filename );
[ + - ]
68 : : } else {
69 : 0 : std::cerr << "Cannot open file for writing: " << filename << '\n';
70 : : }
71 : : }
72 : :
73 : : static void
74 [ + + ]: 6 : load_server_key( const std::string& filename, std::string& key )
75 : : // *****************************************************************************
76 : : //! Load server key from file
77 : : //! \param[in] filename File to load key from
78 : : //! \param[in] key String to store key in
79 : : // *****************************************************************************
80 : : {
81 [ + + ]: 6 : if (filename.empty()) return;
82 : 8 : std::ifstream f( filename );
83 [ - + ]: 4 : if (not f.good()) {
84 [ - - ]: 0 : epee::set_console_color( epee::console_color_red, /*bright=*/ false );
85 : 0 : std::cerr << "Cannot open file for reading: " << filename << '\n';
86 [ - - ]: 0 : epee::set_console_color( epee::console_color_default, /*bright=*/ false );
87 : 0 : return;
88 : : }
89 [ + - ]: 4 : f >> key;
90 : : assert( key.size() == 40 );
91 [ + - ]: 4 : f.close();
92 [ + - ][ + - ]: 12 : MINFO( "Read key from file " + filename );
[ + - ][ + - ]
93 : : }
94 : :
95 : : static void
96 [ + + ]: 3 : load_client_keys( const std::string& filename,
97 : : std::vector< std::string >& keys )
98 : : // *****************************************************************************
99 : : //! Load keys from file
100 : : //! \param[in] filename File to load keys from
101 : : //! \param[in] keys Vector of strings to store key in
102 : : // *****************************************************************************
103 : : {
104 [ + + ]: 3 : if (filename.empty()) return;
105 : 2 : std::ifstream f( filename );
106 [ - + ]: 1 : if (not f.good()) {
107 [ - - ]: 0 : epee::set_console_color( epee::console_color_red, /*bright=*/ false );
108 : 0 : std::cerr << "Cannot open file for reading: " << filename << '\n';
109 [ - - ]: 0 : epee::set_console_color( epee::console_color_default, /*bright=*/ false );
110 : 0 : exit( EXIT_FAILURE );
111 : : }
112 [ + + ]: 4 : while (not f.eof()) {
113 : : std::string key;
114 [ + - ]: 3 : f >> key;
115 [ + + ][ - + ]: 3 : if (key.size() != 40) continue;
116 [ + - ]: 2 : keys.emplace_back( std::move(key) );
117 : : }
118 [ + - ]: 1 : f.close();
119 [ + - ][ + - ]: 4 : MINFO("Read " << keys.size() << " client keys from file " + filename);
[ + - ][ + - ]
120 : : }
121 : :
122 : : static std::string
123 : 2 : usage( const std::string& db_name,
124 : : const std::string& logfile,
125 : : const std::string& rpc_server_save_public_key_file,
126 : : int rpc_port,
127 : : int p2p_port )
128 : : // *****************************************************************************
129 : : //! Return program usage information
130 : : //! \param[in] db_name Name of database to use to store ads
131 : : //! \param[in] rpc_server_save_public_key_file File to save generated public key
132 : : //! \param[in] rpc_port Port to use for client communication
133 : : //! \param[in] p2p_port Port to use for peer-to-peer communication
134 : : //! \param[in] logfile Logfile name
135 : : //! \return String containing usage information
136 : : // *****************************************************************************
137 : : {
138 [ + - ][ + - ]: 4 : return "Usage: " + piac::daemon_executable() + " [OPTIONS]\n\n"
[ - + ][ - + ]
[ - + ][ - - ]
[ - - ][ - - ]
139 : : "OPTIONS\n"
140 : : " --db <directory>\n"
141 [ + - ][ + - ]: 4 : " Use database, default: " + db_name + ".\n\n"
[ - + ][ - + ]
[ - - ][ - - ]
142 : : " --detach\n"
143 : : " Run as a daemon in the background.\n\n"
144 : : " --help\n"
145 : : " Show help message.\n\n"
146 : : " --log-file <filename.log>\n"
147 [ + - ][ + - ]: 4 : " Specify log filename, default: " + logfile + ".\n\n"
[ - + ][ - + ]
[ - - ][ - - ]
148 : : " --log-level <[0-4]>\n"
149 : : " Specify log level: 0: minimum, 4: maximum.\n\n"
150 : : " --max-log-file-size <size-in-bytes> \n"
151 [ + - ][ - + ]: 4 : " Specify maximum log file size in bytes. Default: " +
[ - - ]
152 [ + - ][ + - ]: 8 : std::to_string( MAX_LOG_FILE_SIZE ) + ". Once the log file\n"
[ - + ][ - + ]
[ - - ][ - - ]
153 : : " grows past that limit, the next log file is created with "
154 : : "a UTC timestamp postfix\n"
155 [ + - ]: 2 : " -YYYY-MM-DD-HH-MM-SS. Set --max-log-file-size 0 to prevent "
156 [ + - ][ + - ]: 8 : + piac::cli_executable() + " from managing\n"
[ - + ][ - + ]
[ - + ][ - - ]
[ - - ][ - - ]
157 : : " the log files.\n\n"
158 : : " --max-log-files <num> \n"
159 [ + - ][ - + ]: 4 : " Specify a limit on the number of log files. Default: " +
[ - - ]
160 [ + - ][ + - ]: 8 : std::to_string( MAX_LOG_FILES ) + ". The oldest log files\n"
[ - + ][ - + ]
[ - - ][ - - ]
161 : : " are removed. In production deployments, you would "
162 : : "probably prefer to use\n"
163 : : " established solutions like logrotate instead.\n\n"
164 : : " --peer <hostname>[:port]\n"
165 : : " Specify a peer to connect to.\n\n"
166 : : " --rpc-bind-port <port>\n"
167 [ + - ]: 2 : " Listen on RPC port given, default: "
168 [ + - ][ + - ]: 8 : + std::to_string( rpc_port ) + ".\n\n"
[ - + ][ - + ]
[ - + ][ - - ]
[ - - ][ - - ]
169 : : " --rpc-secure\n"
170 : : " Enable secure connection to clients.\n\n"
171 : : " --rpc-server-public-key-file <filename>\n"
172 : : " Load server public key from file. Need to also set "
173 : : "--rpc-secure.\n\n"
174 : : " --rpc-server-secret-key-file <filename>\n"
175 : : " Load server secret key from file. Need to also set "
176 : : "--rpc-secure.\n\n"
177 : : " --rpc-authorized-clients-file <filename>\n"
178 : : " Only allow client connections with public keys read "
179 : : "from this file. Need to also\n"
180 : : " set --rpc-secure.\n\n"
181 : : " --rpc-server-save-public-key-file <filename>\n"
182 [ + - ]: 2 : " Save self-generated server public key to file. Default: "
183 [ + - ][ - + ]: 4 : + rpc_server_save_public_key_file + ". Need to\n"
[ - + ][ - - ]
[ - - ]
184 : : " also set --rpc-secure.\n\n"
185 : : " --p2p-bind-port <port>\n"
186 [ + - ]: 2 : " Listen on P2P port given, default: "
187 [ + - ][ - + ]: 6 : + std::to_string( p2p_port ) + ".\n\n"
[ - - ]
188 : : " --version\n"
189 [ + - ]: 4 : " Show version information.\n\n";
190 : : }
191 : :
192 : : } // piac::
193 : :
194 : : int
195 : 17 : main( int argc, char **argv )
196 : : // *****************************************************************************
197 : : //! Piac daemon main function
198 : : //! \param[in] argc Number of command line arguments passed from shell
199 : : //! \param[in] argv List of command line arguments passed from shell
200 : : //! \return Error code to return to shell
201 : : // *****************************************************************************
202 : : {
203 : : // save command line
204 : 34 : std::vector< std::string > args( argv, argv+argc );
205 [ + - ]: 34 : std::stringstream cmdline;
206 [ + + ]: 138 : for (const auto& a : args) cmdline << a << ' ';
207 : :
208 : : // defaults
209 : 17 : int rpc_port = 55090; // for client/server communication
210 : 17 : int default_p2p_port = 65090; // for peer-to-peer communication
211 : 17 : int p2p_port = default_p2p_port;
212 : 17 : bool use_strict_ports = false;
213 [ + - ]: 17 : std::string db_name( "piac.db" );
214 [ + - ][ + - ]: 17 : std::string logfile( piac::daemon_executable() + ".log" );
[ - - ]
215 [ + - ]: 17 : std::string log_level( "4" );
216 : 17 : std::size_t max_log_file_size = MAX_LOG_FILE_SIZE;
217 : 17 : std::size_t max_log_files = MAX_LOG_FILES;
218 [ + - ][ + - ]: 34 : std::string version( "piac: " + piac::daemon_executable() + " v"
[ + - ][ - + ]
[ - + ][ - + ]
[ - - ][ - - ]
[ - - ]
219 [ + - ][ + - ]: 68 : + piac::project_version() + "-" + piac::build_type() );
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ][ - + ]
[ + - ][ - - ]
[ - - ][ - - ]
[ - - ]
220 : 17 : std::vector< std::string > peers;
221 : : std::string rpc_server_public_key_file;
222 : : std::string rpc_server_secret_key_file;
223 : : std::string rpc_authorized_clients_file;
224 : 17 : std::vector< std::string > rpc_authorized_clients;
225 [ + - ]: 17 : std::string rpc_server_save_public_key_file = "stonehouse.pub";
226 : :
227 : : // Process command line arguments
228 : : int c;
229 : 17 : int option_index = 0;
230 : 17 : int detach = 0;
231 : 17 : int rpc_secure = 0;
232 : : int num_err = 0;
233 : : const int ARG_DB = 1000;
234 : : const int ARG_HELP = 1001;
235 : : const int ARG_LOG_FILE = 1002;
236 : : const int ARG_LOG_LEVEL = 1003;
237 : : const int ARG_MAX_LOG_FILE_SIZE = 1004;
238 : : const int ARG_MAX_LOG_FILES = 1005;
239 : : const int ARG_PEER = 1006;
240 : : const int ARG_RPC_PORT = 1007;
241 : : const int ARG_RPC_SERVER_PUBLIC_KEY_FILE = 1008;
242 : : const int ARG_RPC_SERVER_SECRET_KEY_FILE = 1009;
243 : : const int ARG_RPC_AUTHORIZED_CLIENTS_FILE = 1010;
244 : : const int ARG_RPC_SERVER_SAVE_PUBLIC_KEY_FILE = 1011;
245 : : const int ARG_P2P_PORT = 1012;
246 : : const int ARG_VERSION = 1013;
247 : : static struct option long_options[] =
248 : : {
249 : : { "db", required_argument, nullptr, ARG_DB },
250 : : { "detach", no_argument, &detach, 1 },
251 : : { "help", no_argument, nullptr, ARG_HELP },
252 : : { "log-file", required_argument, nullptr, ARG_LOG_FILE },
253 : : { "log-level", required_argument, nullptr, ARG_LOG_LEVEL },
254 : : { "max-log-file-size", required_argument, nullptr, ARG_MAX_LOG_FILE_SIZE },
255 : : { "max-log-files", required_argument, nullptr, ARG_MAX_LOG_FILES },
256 : : { "peer", required_argument, nullptr, ARG_PEER },
257 : : { "rpc-bind-port", required_argument, nullptr, ARG_RPC_PORT },
258 : : { "rpc-secure", no_argument, &rpc_secure, 1 },
259 : : { "rpc-server-public-key-file", required_argument, nullptr,
260 : : ARG_RPC_SERVER_PUBLIC_KEY_FILE },
261 : : { "rpc-server-secret-key-file", required_argument, nullptr,
262 : : ARG_RPC_SERVER_SECRET_KEY_FILE },
263 : : { "rpc-authorized-clients-file", required_argument, nullptr,
264 : : ARG_RPC_AUTHORIZED_CLIENTS_FILE },
265 : : { "rpc-server-save-public-key-file", required_argument, nullptr,
266 : : ARG_RPC_SERVER_SAVE_PUBLIC_KEY_FILE },
267 : : { "p2p-bind-port", required_argument, nullptr, ARG_P2P_PORT },
268 : : { "version", no_argument, nullptr, ARG_VERSION },
269 : : { nullptr, 0, nullptr, 0 }
270 [ + - ][ + - ]: 17 : };
271 : :
272 [ + + ]: 73 : while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
273 [ + + ][ + + ]: 60 : switch (c) {
[ + + ][ + + ]
[ + + ][ + - ]
[ - - ][ + - ]
274 : :
275 : 2 : case ARG_DB: {
276 [ + - ]: 2 : db_name = optarg;
277 : : break;
278 : : }
279 : :
280 : : case ARG_HELP: {
281 : : std::cout << version << "\n\n" <<
282 : 2 : piac::usage( db_name, logfile, rpc_server_save_public_key_file,
283 [ + - ]: 2 : rpc_port, p2p_port );
284 : 2 : return EXIT_SUCCESS;
285 : : }
286 : :
287 : : case ARG_PEER: {
288 [ + - ][ - - ]: 8 : peers.push_back( optarg );
289 : 4 : break;
290 : : }
291 : :
292 : 11 : case ARG_RPC_PORT: {
293 : 11 : rpc_port = atoi( optarg );
294 : 11 : use_strict_ports = true;
295 : 11 : break;
296 : : }
297 : :
298 : 2 : case ARG_RPC_SERVER_PUBLIC_KEY_FILE: {
299 [ + - ]: 2 : rpc_server_public_key_file = optarg;
300 : : break;
301 : : }
302 : :
303 : 2 : case ARG_RPC_SERVER_SECRET_KEY_FILE: {
304 [ + - ]: 2 : rpc_server_secret_key_file = optarg;
305 : : break;
306 : : }
307 : :
308 : 1 : case ARG_RPC_AUTHORIZED_CLIENTS_FILE: {
309 [ + - ]: 1 : rpc_authorized_clients_file = optarg;
310 : : break;
311 : : }
312 : :
313 : 1 : case ARG_RPC_SERVER_SAVE_PUBLIC_KEY_FILE: {
314 [ + - ]: 1 : rpc_server_save_public_key_file = optarg;
315 : : break;
316 : : }
317 : :
318 : 11 : case ARG_P2P_PORT: {
319 : 11 : default_p2p_port = atoi( optarg );
320 : 11 : p2p_port = default_p2p_port;
321 : 11 : use_strict_ports = true;
322 : 11 : break;
323 : : }
324 : :
325 : 8 : case ARG_LOG_FILE: {
326 [ + - ]: 8 : logfile = optarg;
327 : : break;
328 : : }
329 : :
330 : 0 : case ARG_LOG_LEVEL: {
331 [ - - ]: 0 : std::stringstream s;
332 [ - - ]: 0 : s << optarg;
333 : : int level;
334 [ - - ]: 0 : s >> level;
335 [ - - ]: 0 : if (level < 0) level = 0;
336 [ - - ]: 0 : if (level > 4) level = 4;
337 [ - - ]: 0 : log_level = std::to_string( level );
338 : : break;
339 : : }
340 : :
341 : 0 : case ARG_MAX_LOG_FILE_SIZE: {
342 [ - - ]: 0 : std::stringstream s;
343 [ - - ]: 0 : s << optarg;
344 : : s >> max_log_file_size;
345 : : break;
346 : : }
347 : :
348 : 0 : case ARG_MAX_LOG_FILES: {
349 [ - - ]: 0 : std::stringstream s;
350 [ - - ]: 0 : s << optarg;
351 : : s >> max_log_files;
352 : : break;
353 : : }
354 : :
355 : : case ARG_VERSION: {
356 : 2 : std::cout << version << '\n';
357 : 2 : return EXIT_SUCCESS;
358 : : }
359 : :
360 : 0 : case '?': {
361 : 0 : ++num_err;
362 : 0 : break;
363 : : }
364 : : }
365 : : }
366 : :
367 [ + + ]: 13 : if (optind < argc) {
368 [ + - ]: 2 : printf( "%s: invalid options -- ", argv[0] );
369 [ + + ][ + - ]: 4 : while (optind < argc) printf( "%s ", argv[optind++] );
370 [ + - ]: 2 : printf( "\n" );
371 : : return EXIT_FAILURE;
372 : : }
373 : :
374 [ - + ]: 11 : if (num_err) {
375 : : std::cerr << "Erros during parsing command line\n"
376 [ - - ][ - - ]: 0 : << "Command line: " + cmdline.str() << '\n'
[ - - ]
377 [ - - ][ - - ]: 0 : << piac::usage( db_name, logfile,rpc_server_save_public_key_file,
378 [ - - ]: 0 : rpc_port, p2p_port );
379 : 0 : return EXIT_FAILURE;
380 : : }
381 : :
382 [ + - ]: 9 : if ((not rpc_server_public_key_file.empty() ||
383 [ - + ]: 9 : not rpc_server_secret_key_file.empty() ||
384 [ + + ]: 11 : not rpc_authorized_clients_file.empty()) &&
385 [ - + ]: 2 : not rpc_secure)
386 : : {
387 [ - - ]: 0 : std::cerr << "Need --rpc-secure to secure RPC channel.\n";
388 : : return EXIT_FAILURE;
389 : : }
390 : :
391 [ + - ]: 2 : if ((not rpc_server_public_key_file.empty() &&
392 [ + + ][ + + ]: 13 : rpc_server_secret_key_file.empty()) ||
393 [ - + ]: 9 : (rpc_server_public_key_file.empty() &&
394 : : not rpc_server_secret_key_file.empty()))
395 : : {
396 : : std::cerr << "Need --rpc-authorized-clients-file for authorized RPC "
397 [ - - ]: 0 : "clients.\n";
398 : : return EXIT_FAILURE;
399 : : }
400 : :
401 [ + - ]: 11 : if (detach) {
402 : : // Fork the current process. The parent process continues with a process ID
403 : : // greater than 0. A process ID lower than 0 indicates a failure in either
404 : : // process.
405 : 11 : pid_t pid = fork();
406 [ + + ]: 22 : if (pid > 0) {
407 : : std::cout << "Running in daemon mode. Forked PID: " << pid
408 [ + - ]: 11 : << ". See the log file for details." << std::endl;
409 : : return EXIT_SUCCESS;
410 [ + - ]: 11 : } else if (pid < 0) {
411 : : return EXIT_FAILURE;
412 : : }
413 : :
414 : : // Generate a session ID for the child process and ensure it is valid.
415 [ - + ]: 11 : if (setsid() < 0) {
416 : : // Log failure and exit
417 [ - - ]: 0 : std::cerr << "Could not generate session ID for child process\n";
418 : : // If a new session ID could not be generated, we must terminate the child
419 : : // process or it will be orphaned.
420 : : return EXIT_FAILURE;
421 : : }
422 : :
423 : : // A daemon cannot use the terminal, so close standard file descriptors for
424 : : // security reasons and also because ctest hangs in daemon mode waiting for
425 : : // stdout and stderr to be closed.
426 [ + - ]: 11 : close( STDIN_FILENO );
427 [ + - ]: 11 : close( STDOUT_FILENO );
428 [ + - ]: 11 : close( STDERR_FILENO );
429 : :
430 : 11 : s_catch_signals();
431 : : }
432 : :
433 [ + - ]: 11 : epee::set_console_color( epee::console_color_green, /* bright = */ false );
434 : 11 : std::cout << version << '\n';
435 [ + - ]: 11 : epee::set_console_color( epee::console_color_default, /* bright = */ false );
436 : : std::cout <<
437 : : "Welcome to piac, where anyone can buy and sell anything privately and\n"
438 : : "securely using the private digital cash, monero. For more information\n"
439 : : "on monero, see https://getmonero.org. This is the server of piac. It\n"
440 : : "can run standalone or as a daemon in the background using --detach.\n"
441 [ + - ][ + - ]: 22 : "You can use " + piac::cli_executable() + " to interact with it.\n";
[ + - ][ - + ]
[ - + ][ - - ]
[ - - ]
442 : :
443 [ + - ]: 11 : piac::setup_logging( logfile, log_level, /* console_logging = */ false,
444 : : max_log_file_size, max_log_files );
445 : :
446 [ + - ][ + - ]: 44 : MINFO( "Command line: " + cmdline.str() );
[ + - ][ + - ]
[ - + ][ - - ]
[ - - ]
447 : :
448 : : // setup RPC security
449 : : int rpc_ironhouse = 1;
450 : 0 : zmqpp::curve::keypair rpc_server_keys;
451 [ + + ]: 11 : if (rpc_secure) {
452 [ + - ]: 3 : piac::load_server_key( rpc_server_public_key_file,
453 : : rpc_server_keys.public_key );
454 [ + - ]: 3 : piac::load_server_key( rpc_server_secret_key_file,
455 : : rpc_server_keys.secret_key );
456 [ + - ]: 3 : piac::load_client_keys( rpc_authorized_clients_file,
457 : : rpc_authorized_clients );
458 : : // fallback to stonehouse if needed
459 [ + - ]: 2 : if (rpc_server_keys.secret_key.empty() ||
460 [ + + ][ + + ]: 5 : rpc_server_keys.public_key.empty() ||
461 : : rpc_authorized_clients.empty())
462 : : {
463 : : rpc_ironhouse = 0;
464 [ + + ][ - + ]: 2 : if (rpc_server_keys.secret_key.empty() ||
465 : : rpc_server_keys.public_key.empty())
466 : : {
467 [ + - ]: 2 : rpc_server_keys = zmqpp::curve::generate_keypair();
468 [ + - ]: 1 : piac::save_public_key( rpc_server_save_public_key_file,
469 : : rpc_server_keys.public_key );
470 : : }
471 : : rpc_authorized_clients.clear();
472 : : }
473 : : }
474 : :
475 : : // echo RPC security configured
476 [ + + ]: 11 : if (rpc_secure) {
477 [ + + ]: 3 : if (rpc_ironhouse) {
478 [ + - ]: 1 : epee::set_console_color( epee::console_color_green, /*bright=*/ false );
479 : : std::string ironhouse( "Connections to this server are secure: "
480 [ + - ]: 1 : "Only authenticated connections are accepted." );
481 : 1 : std::cout << ironhouse << '\n';
482 [ + - ]: 1 : epee::set_console_color( epee::console_color_white, /*bright=*/false );
483 [ + - ][ + - ]: 2 : MINFO( ironhouse );
[ + - ][ - - ]
484 : : } else {
485 : : std::string stonehouse( "Connections to this server are secure but not "
486 [ + - ]: 2 : "authenticated: ALL client connections are accepted." );
487 [ + - ]: 2 : epee::set_console_color( epee::console_color_yellow, /*bright=*/ false );
488 : 2 : std::cout << stonehouse << '\n';
489 [ + - ]: 2 : epee::set_console_color( epee::console_color_white, /*bright=*/false );
490 [ + - ][ + - ]: 4 : MINFO( stonehouse );
[ + - ][ - - ]
491 : : std::cout << "RPC server public key: "
492 [ + - ]: 2 : << rpc_server_keys.public_key << '\n';
493 : : }
494 : : } else {
495 [ + - ]: 8 : epee::set_console_color( epee::console_color_red, /* bright = */ false );
496 : : std::string grasslands( "WARNING: Connections to this server are not "
497 [ + - ]: 8 : "secure" );
498 : 8 : std::cout << grasslands << '\n';
499 [ + - ][ + - ]: 16 : MWARNING( grasslands );
[ + - ][ - - ]
500 : : }
501 [ + - ]: 11 : epee::set_console_color( epee::console_color_default, /* bright = */false );
502 : :
503 [ + + ]: 11 : if (rpc_secure) {
504 [ + - ][ + - ]: 6 : MINFO( "RPC server public key: " << rpc_server_keys.public_key );
[ + - ]
505 : : }
506 : :
507 [ + - ]: 11 : if (detach) {
508 [ + - ][ + - ]: 33 : MINFO( "Forked PID: " << getpid() );
[ + - ]
509 : : }
510 : :
511 : : // initialize (thread-safe) zmq contexts
512 [ + - ]: 11 : zmqpp::context ctx_p2p; // for p2p comm
513 [ + - ]: 11 : zmqpp::context ctx_db; // for inproc comm
514 : :
515 : : // add initial peers
516 : : std::unordered_map< std::string, zmqpp::socket > my_peers;
517 [ + + ]: 15 : for (const auto& p : peers)
518 [ + - ]: 8 : my_peers.emplace( p, zmqpp::socket( ctx_p2p, zmqpp::socket_type::dealer ) );
519 : :
520 : : // will store db entry hashes
521 : : std::unordered_set< std::string > my_hashes;
522 : :
523 : : // start threads
524 : 0 : std::vector< std::thread > threads;
525 : :
526 : : threads.emplace_back( piac::p2p_thread,
527 : 22 : std::ref(ctx_p2p), std::ref(ctx_db), std::ref(my_peers),
528 [ + - ]: 11 : std::ref(my_hashes), default_p2p_port, p2p_port, use_strict_ports );
529 : :
530 : : threads.emplace_back( piac::db_thread,
531 : 22 : std::ref(ctx_db), db_name, rpc_port, use_strict_ports, std::ref(my_peers),
532 : 22 : std::ref(my_hashes), rpc_secure, std::ref(rpc_server_keys),
533 [ + - ]: 11 : std::ref(rpc_authorized_clients) );
534 : :
535 : : // wait for all threads to finish
536 [ + - ][ - - ]: 11 : for (auto& t : threads) t.join();
537 : :
538 [ - - ][ - - ]: 0 : MDEBUG( "graceful exit" );
[ - - ]
539 : :
540 : : // Terminate the child process when the daemon completes
541 : : return EXIT_SUCCESS;
542 : : }
|