tools: use Log instead of fmt::print

Since fmt::print does not flush the buffer, I added a Log macro to
ensure the output is immediately flushed.
Not needed for print on stderr as std lib already flush it.

Change-Id: Ieb7c04f9f191f1982643b005fae2d4e944a3a1fa
diff --git a/tools/benchmark/main.cpp b/tools/benchmark/main.cpp
index 6823307..ff4ed72 100644
--- a/tools/benchmark/main.cpp
+++ b/tools/benchmark/main.cpp
@@ -96,7 +96,7 @@
     auto boostrap_node = std::make_shared<dht::DhtRunner>();
     boostrap_node->run(36432);
 
-    fmt::print("Generating identities…\n");
+    Log("Generating identities…\n");
     auto server = setupHandler("server", ioContext, ioContextRunner, factory, logger);
     auto client = setupHandler("client", ioContext, ioContextRunner, factory, logger);
 
@@ -110,13 +110,13 @@
         });
     server->connectionManager->onConnectionReady([&](const DeviceId& device, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
         if (socket) {
-            fmt::print("Server: Connection succeeded\n");
+            Log("Server: Connection succeeded\n");
             socket->setOnRecv([s=socket.get()](const uint8_t* data, size_t size) {
                 std::error_code ec;
                 return s->write(data, size, ec);
             });
         } else {
-            fmt::print("Server: Connection failed\n");
+            Log("Server: Connection failed\n");
         }
     });
 
@@ -129,7 +129,7 @@
     time_point start_connect, start_send;
 
     std::this_thread::sleep_for(3s);
-    fmt::print("Connecting…\n");
+    Log("Connecting…\n");
     start_connect = clock::now();
     client->connectionManager->connectDevice(server->id.second, "channelName", [&](std::shared_ptr<ChannelSocket> socket, const DeviceId&) {
         if (socket) {
@@ -138,20 +138,20 @@
                 if (rx == TX_GOAL) {
                     auto end = clock::now();
                     ret.send = end - start_send;
-                    fmt::print("Streamed {} bytes back and forth in {} ({} kBps)\n", rx, dht::print_duration(ret.send), (unsigned)(rx / (1000 * std::chrono::duration<double>(ret.send).count())));
+                    Log("Streamed {} bytes back and forth in {} ({} kBps)\n", rx, dht::print_duration(ret.send), (unsigned)(rx / (1000 * std::chrono::duration<double>(ret.send).count())));
                     cv.notify_one();
                 }
                 return size;
             });
             ret.connection = clock::now() - start_connect;
-            fmt::print("Connected in {}\n", dht::print_duration(ret.connection));
+            Log("Connected in {}\n", dht::print_duration(ret.connection));
             std::vector<uint8_t> data(TX_SIZE, (uint8_t)'y');
             std::error_code ec;
             start_send = clock::now();
             for (unsigned i = 0; i < TX_NUM; ++i) {
                 socket->write(data.data(), data.size(), ec);
                 if (ec)
-                    fmt::print("error: {}\n", ec.message());
+                    fmt::print(stderr, "error: {}\n", ec.message());
             }
         } else {
             completed = true;
@@ -183,7 +183,7 @@
     unsigned total_success = 0;
     constexpr unsigned ITERATIONS = 20;
     for (unsigned i = 0; i < ITERATIONS; ++i) {
-        fmt::print("Iteration {}\n", i);
+        Log("Iteration {}\n", i);
         auto res = runBench(ioContext, ioContextRunner, factory, logger);
         if (res.success) {
             total.connection += res.connection;
@@ -191,9 +191,9 @@
             total_success++;
         }
     }
-    fmt::print("Average connection time: {}\n", dht::print_duration(total.connection / total_success));
-    fmt::print("Average send time: {}\n", dht::print_duration(total.send / total_success));
-    fmt::print("Total success: {}\n", total_success);
+    Log("Average connection time: {}\n", dht::print_duration(total.connection / total_success));
+    Log("Average send time: {}\n", dht::print_duration(total.send / total_success));
+    Log("Total success: {}\n", total_success);
 
     std::this_thread::sleep_for(500ms);
     ioContext->stop();
diff --git a/tools/common.h b/tools/common.h
index b1bde5c..97c44c9 100644
--- a/tools/common.h
+++ b/tools/common.h
@@ -23,6 +23,8 @@
 
 namespace dhtnet {
 
+#define Log(...) do { fmt::print(__VA_ARGS__); std::fflush(stdout); } while (0)
+
 using Buffer = std::shared_ptr<std::vector<uint8_t>>;
 constexpr size_t BUFFER_SIZE = 64 * 1024;
 
diff --git a/tools/dhtnet_crtmgr/main.cpp b/tools/dhtnet_crtmgr/main.cpp
index 4ad8dfe..70e551e 100644
--- a/tools/dhtnet_crtmgr/main.cpp
+++ b/tools/dhtnet_crtmgr/main.cpp
@@ -15,7 +15,7 @@
  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
  */
 #include "dhtnet_crtmgr.h"
-
+#include"common.h"
 
 #include <iostream>
 #include <fstream>
@@ -148,7 +148,7 @@
             yaml_file << "  #   port: 443\n";
         }
         yaml_file.close();
-        fmt::print("Configuration file created in {}\n", file);
+        Log("Configuration file created in {}\n", file);
     } else {
         fmt::print(stderr, "Error: Could not create configuration file {}.\n", file);
         return 1;
@@ -174,7 +174,7 @@
         std::string line;
         while (std::getline(ssh_file, line)) {
             if (line.find("Host dnc") != std::string::npos) {
-                fmt::print("Info: dnc configuration already exists in ssh config. File is left untouched\n");
+                Log("Info: dnc configuration already exists in ssh config. File is left untouched\n");
                 return 0;
             }
         }
@@ -184,7 +184,7 @@
         ssh_file << "\nHost dnc/*\n";
         ssh_file << "    ProxyCommand dnc -d " << yaml_config << " $(basename %h)\n";
         ssh_file.close();
-        fmt::print("SSH configuration added to {}\n", ssh_config);
+        Log("SSH configuration added to {}\n", ssh_config);
     } else {
         fmt::print(stderr, "Error: Could not open ssh config file.\n");
         return 1;
@@ -207,7 +207,7 @@
     auto params = parse_args(argc, argv);
 
     if (params.help) {
-        fmt::print("Usage: dhtnet-crtmgr [options]\n"
+        Log("Usage: dhtnet-crtmgr [options]\n"
                 "\nOptions:\n"
                 "  -h, --help                Display this help message and then exit.\n"
                 "  -v, --version             Show the version of the program.\n"
@@ -222,7 +222,7 @@
     }
 
     if (params.version) {
-        fmt::print("dhtnet-crtmgr v1.0\n");
+        Log("dhtnet-crtmgr v1.0\n");
         return EXIT_SUCCESS;
     }
     // check if the public key id is requested
@@ -232,7 +232,7 @@
             exit(EXIT_FAILURE);
         }
         auto identity = dhtnet::loadIdentity(params.privatekey, params.ca);
-        fmt::print("Public key id: {}\n", identity.second->getId());
+        Log("Public key id: {}\n", identity.second->getId());
         return EXIT_SUCCESS;
     }
 
@@ -241,7 +241,7 @@
         // Ask user if he want to setup client or server config
         std::string usage = "";
         do {
-            fmt::print("Generate identity for server or client? [(C)lient/(s)erver] (default: client): ");
+            Log("Generate identity for server or client? [(C)lient/(s)erver] (default: client): ");
             std::getline(std::cin, usage);
             usage = str_tolower(usage);
             if (usage == "s") usage = "server";
@@ -253,7 +253,7 @@
         std::string use_server_ca = "";
         if (usage == "client") {
             do {
-                fmt::print("Sign client certificate using server CA? [Y/n] (default: yes): ");
+                Log("Sign client certificate using server CA? [Y/n] (default: yes): ");
                 std::getline(std::cin, use_server_ca);
                 use_server_ca = str_tolower(use_server_ca);
                 if (use_server_ca == "y") use_server_ca = "yes";
@@ -272,7 +272,7 @@
 
         // Ask where to store identity files
         std::filesystem::path folder;
-        fmt::print("Enter the path to save identities and config [{}]: ", home_dir);
+        Log("Enter the path to save identities and config [{}]: ", home_dir);
         std::getline(std::cin, input_folder);
         if (input_folder.empty()) {
             folder = home_dir;
@@ -309,7 +309,7 @@
                     fmt::print(stderr, "Error: Could not generate CA.\n");
                     return EXIT_FAILURE;
                 }
-                fmt::print("Generated CA in {}: {} {}\n", folder, "ca", ca.second->getId());
+                Log("Generated CA in {}: {} {}\n", folder, "ca", ca.second->getId());
             }
 
             // Generate client certificate
@@ -318,7 +318,7 @@
                 fmt::print(stderr, "Error: Could not generate certificate.\n");
                 return EXIT_FAILURE;
             }
-            fmt::print("Generated certificate in {}: {} {}\n", folder, "certificate", id.second->getId());
+            Log("Generated certificate in {}: {} {}\n", folder, "certificate", id.second->getId());
 
             // Create configuration file with generated keys
             std::filesystem::path yaml_config{folder / "config.yml"};
@@ -329,7 +329,7 @@
             // Ask user if he want to configure SSH
             std::string ssh_setup = "";
             do {
-                fmt::print("Configure SSH to support dnc protocol? [Y/n] (default: yes): ");
+                Log("Configure SSH to support dnc protocol? [Y/n] (default: yes): ");
                 std::getline(std::cin, ssh_setup);
                 ssh_setup = str_tolower(ssh_setup);
                 if (ssh_setup == "y") ssh_setup = "yes";
@@ -350,7 +350,7 @@
             std::string overwrite = "";
             if (std::filesystem::exists(yaml_config)) {
                 do {
-                    fmt::print("Configuration file already exists in {}. Overwrite it? [y/N] (default: no): ", yaml_config);
+                    Log("Configuration file already exists in {}. Overwrite it? [y/N] (default: no): ", yaml_config);
                     std::getline(std::cin, overwrite);
                     overwrite = str_tolower(overwrite);
                     if (overwrite == "y") overwrite = "yes";
@@ -379,7 +379,7 @@
             fmt::print(stderr, "Error: Could not generate CA.\n");
             return EXIT_FAILURE;
         }
-        fmt::print("Generated CA in {}: {} {}\n", path_ca, "ca-server", ca.second->getId());
+        Log("Generated CA in {}: {} {}\n", path_ca, "ca-server", ca.second->getId());
         // create identity with name id-server
         std::filesystem::path path_id = params.output / "id";
         auto identity = dhtnet::generateIdentity(path_id, "id-server", ca);
@@ -387,7 +387,7 @@
             fmt::print(stderr, "Error: Could not generate certificate.\n");
             return EXIT_FAILURE;
         }
-        fmt::print("Generated certificate in {}: {} {}\n", path_id,"id-server", identity.second->getId());
+        Log("Generated certificate in {}: {} {}\n", path_id,"id-server", identity.second->getId());
         return EXIT_SUCCESS;
     }
 
@@ -398,14 +398,14 @@
                 fmt::print(stderr, "Error: Could not generate CA.\n");
                 return EXIT_FAILURE;
             }
-            fmt::print("Generated certificate in {}: {} {}\n", params.output, "ca", ca.second->getId());
+            Log("Generated certificate in {}: {} {}\n", params.output, "ca", ca.second->getId());
         }else{
             auto ca = dhtnet::generateIdentity(params.output, params.name);
             if (!ca.first || !ca.second) {
                 fmt::print(stderr, "Error: Could not generate CA.\n");
                 return EXIT_FAILURE;
             }
-            fmt::print("Generated certificate in {}: {} {}\n", params.output, params.name, ca.second->getId());
+            Log("Generated certificate in {}: {} {}\n", params.output, params.name, ca.second->getId());
         }
     }else{
         auto ca = dhtnet::loadIdentity(params.privatekey, params.ca);
@@ -415,14 +415,14 @@
                 fmt::print(stderr, "Error: Could not generate certificate.\n");
                 return EXIT_FAILURE;
             }
-            fmt::print("Generated certificate in {}: {} {}\n", params.output, "certificate", id.second->getId());
+            Log("Generated certificate in {}: {} {}\n", params.output, "certificate", id.second->getId());
         }else{
             auto id = dhtnet::generateIdentity(params.output, params.name, ca);
             if (!id.first || !id.second) {
                 fmt::print(stderr, "Error: Could not generate certificate.\n");
                 return EXIT_FAILURE;
             }
-            fmt::print("Generated certificate in {}: {} {}\n", params.output, params.name, id.second->getId());
+            Log("Generated certificate in {}: {} {}\n", params.output, params.name, id.second->getId());
         }
     }
     return EXIT_SUCCESS;
diff --git a/tools/dnc/dnc.cpp b/tools/dnc/dnc.cpp
index 86bb159..18860ae 100644
--- a/tools/dnc/dnc.cpp
+++ b/tools/dnc/dnc.cpp
@@ -127,7 +127,7 @@
             auto it = authorized_services.find(ip);
             if (it == authorized_services.end()) {
                 // Reject the connection if the ip is not authorized
-                fmt::print("Rejecting connection to {}:{}", ip, port);
+                Log("Rejecting connection to {}:{}", ip, port);
                 return false;
             }
 
@@ -135,10 +135,10 @@
             const auto &ports = it->second;
             if (std::find(ports.begin(), ports.end(), port) == ports.end()) {
                 // Reject the connection if the port is not authorized
-                fmt::print("Rejecting connection to {}:{}", ip, port);
+                Log("Rejecting connection to {}:{}", ip, port);
                 return false;
             }
-            fmt::print("Accepting connection to {}:{}", ip, port);
+            Log("Accepting connection to {}:{}", ip, port);
             return true;
         });
 
@@ -151,7 +151,7 @@
         }
         try {
             auto parsedName = parseName(name);
-            fmt::print("Connecting to {}:{}", parsedName.first, parsedName.second);
+            Log("Connecting to {}:{}", parsedName.first, parsedName.second);
 
             asio::ip::tcp::resolver resolver(*ioContext);
             asio::ip::tcp::resolver::results_type endpoints = resolver.resolve(parsedName.first,
@@ -167,7 +167,7 @@
                 [this, socket, mtlxSocket](const std::error_code& error,
                                            const asio::ip::tcp::endpoint& ep) {
                     if (!error) {
-                        fmt::print("Connected!\n");
+                        Log("Connected!\n");
                         mtlxSocket->setOnRecv([socket, this](const uint8_t* data, size_t size) {
                             auto data_copy = std::make_shared<std::vector<uint8_t>>(data,
                                                                                     data + size);
@@ -176,7 +176,7 @@
                                               [data_copy, this](const std::error_code& error,
                                                                 std::size_t bytesWritten) {
                                                   if (error) {
-                                                    fmt::print("Write error: {}\n", error.message());
+                                                    Log("Write error: {}\n", error.message());
                                                   }
 
                                               });
@@ -186,13 +186,13 @@
                         auto buffer = std::make_shared<std::vector<uint8_t>>(BUFFER_SIZE);
                         readFromPipe(mtlxSocket, socket, buffer);
                     } else {
-                        fmt::print("Connection error: {}\n", error.message());
+                        Log("Connection error: {}\n", error.message());
                         mtlxSocket->shutdown();
                     }
                 });
 
         } catch (std::exception& e) {
-            fmt::print("Exception: {}\n", e.what());
+            Log("Exception: {}\n", e.what());
         }
     });
 }
@@ -211,7 +211,7 @@
 {
     std::condition_variable cv;
     auto name = fmt::format("nc://{:s}:{:d}", remote_host, remote_port);
-    fmt::print("Requesting socket: %s\n", name.c_str());
+    Log("Requesting socket: %s\n", name.c_str());
     connectionManager->connectDevice(
         peer_id, name, [&](std::shared_ptr<ChannelSocket> socket, const dht::InfoHash&) {
             if (socket) {
@@ -230,7 +230,7 @@
                 readFromPipe(socket, stdinPipe, buffer);
 
                 socket->onShutdown([this]() {
-                    fmt::print("Exit program\n");
+                    Log("Exit program\n");
                     ioContext->stop();
                 });
             }
@@ -238,7 +238,7 @@
 
     connectionManager->onConnectionReady(
         [&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> mtlxSocket) {
-            fmt::print("Connected!\n");
+            Log("Connected!\n");
         });
 }
 
diff --git a/tools/dnc/main.cpp b/tools/dnc/main.cpp
index cf98945..2e4d1bf 100644
--- a/tools/dnc/main.cpp
+++ b/tools/dnc/main.cpp
@@ -145,7 +145,7 @@
 
     // extract values from dnc yaml file
     if (!params.configuration.empty()) {
-        printf("read configuration file: %s\n", params.configuration.c_str());
+        Log("Read configuration file: {}\n", params.configuration.c_str());
         std::ifstream config_file(params.configuration);
         if (!config_file.is_open()) {
             std::cerr << "Error: Could not open configuration file.\n";
@@ -217,7 +217,7 @@
 
     pj_log_set_level(level);
     pj_log_set_log_func([](int level, const char* data, int len) {
-        fmt::print("{}", std::string_view(data, len));
+        Log("{}", std::string_view(data, len));
     });
 }
 
@@ -228,7 +228,7 @@
     auto params = parse_args(argc, argv);
 
     if (params.help) {
-        fmt::print("Usage: dnc [options] [PEER_ID]\n"
+        Log("Usage: dnc [options] [PEER_ID]\n"
                    "\nOptions:\n"
                    "  -h, --help                  Show this help message and exit.\n"
                    "  -v, --version               Display the program version.\n"
@@ -249,7 +249,7 @@
     }
 
     if (params.version) {
-        fmt::print("dnc v1.0\n");
+        Log("dnc v1.0\n");
         return EXIT_SUCCESS;
     }
 
@@ -258,9 +258,9 @@
         fmt::print(stderr, "Hint: To generate new identity files, run: dhtnet-crtmgr --interactive\n");
         return EXIT_FAILURE;
     }
-    fmt::print("Loaded identity: {}\n", identity.second->getId());
+    Log("Loaded identity: {}\n", identity.second->getId());
 
-    fmt::print("dnc 1.0\n");
+    Log("dnc 1.0\n");
     std::unique_ptr<dhtnet::Dnc> dhtnc;
     if (params.listen) {
         // create dnc instance
diff --git a/tools/dsh/main.cpp b/tools/dsh/main.cpp
index 5f6331a..4859ab1 100644
--- a/tools/dsh/main.cpp
+++ b/tools/dsh/main.cpp
@@ -196,7 +196,7 @@
     auto params = parse_args(argc, argv);
 
     if (params.help){
-        fmt::print("Usage: dsh [OPTIONS] [PEER_ID]\n"
+        Log("Usage: dsh [OPTIONS] [PEER_ID]\n"
                    "\nOptions:\n"
                    "  -h, --help                  Show this help message and exit.\n"
                    "  -v, --version               Display the program version.\n"
@@ -214,18 +214,18 @@
         return EXIT_SUCCESS;
     }
     if (params.version){
-        fmt::print("dsh v1.0\n");
+        Log("dsh v1.0\n");
         return EXIT_SUCCESS;
     }
 
-    fmt::print("dsh 1.0\n");
+    Log("dsh 1.0\n");
 
     auto identity = dhtnet::loadIdentity(params.privateKey, params.cert);
     if (!identity.first || !identity.second) {
         fmt::print(stderr, "Hint: To generate new identity files, run: dhtnet-crtmgr --interactive\n");
         return EXIT_FAILURE;
     }
-    fmt::print("Loaded identity: {} \n", identity.second->getId());
+    Log("Loaded identity: {} \n", identity.second->getId());
 
     std::unique_ptr<dhtnet::Dsh> dhtsh;
     if (params.listen) {
diff --git a/tools/dvpn/main.cpp b/tools/dvpn/main.cpp
index cd5b3df..1cf3ec9 100644
--- a/tools/dvpn/main.cpp
+++ b/tools/dvpn/main.cpp
@@ -179,7 +179,7 @@
 
     pj_log_set_level(level);
     pj_log_set_log_func([](int level, const char* data, int len) {
-        fmt::print("{}", std::string_view(data, len));
+        Log("{}", std::string_view(data, len));
     });
 }
 
@@ -190,7 +190,7 @@
     auto params = parse_args(argc, argv);
 
     if (params.help) {
-        fmt::print(
+        Log(
             "Usage: dvpn [options] [PEER_ID]\n"
             "\nOptions:\n"
             "  -h, --help                      Show this help message and exit.\n"
@@ -210,18 +210,18 @@
         return EXIT_SUCCESS;
     }
     if (params.version) {
-        fmt::print("dvpn v1.0\n");
+        Log("dvpn v1.0\n");
         return EXIT_SUCCESS;
     }
 
-    fmt::print("dvpn 1.0\n");
+    Log("dvpn 1.0\n");
 
     auto identity = dhtnet::loadIdentity(params.privateKey, params.cert);
     if (!identity.first || !identity.second) {
         fmt::print(stderr, "Hint: To generate new identity files, run: dhtnet-crtmgr --interactive\n");
         return EXIT_FAILURE;
     }
-    fmt::print("Loaded identity: {}\n", identity.second->getId());
+    Log("Loaded identity: {}\n", identity.second->getId());
 
     std::unique_ptr<dhtnet::Dvpn> dvpn;
     if (params.listen) {