blob: 677477f2c3bb27c2d6c2153a569d1c97c2a0a8ad [file] [log] [blame]
Amna38768302023-08-21 11:51:56 -04001/*
2 * Copyright (C) 2004-2023 Savoir-faire Linux Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#include "dnc.h"
18#include "common.h"
Adrien Béraudc1cac452023-08-22 20:32:36 -040019
Amna38768302023-08-21 11:51:56 -040020#include <string>
21#include <vector>
22#include <iostream>
23#include <unistd.h>
24#include <getopt.h>
Amnab31c3742023-08-28 13:58:31 -040025#if __has_include(<fmt/std.h>)
Adrien Béraudecde63f2023-08-26 18:11:21 -040026#include <fmt/std.h>
Amnab31c3742023-08-28 13:58:31 -040027#else
28#include <fmt/ostream.h>
29#endif
Amna38768302023-08-21 11:51:56 -040030#include <netinet/in.h>
31
32struct dhtnc_params
33{
34 bool help {false};
35 bool version {false};
36 bool listen {false};
Adrien Béraudecde63f2023-08-26 18:11:21 -040037 bool verbose {false};
38 std::filesystem::path path {};
39 std::string bootstrap {};
40 std::string remote_host {};
41 in_port_t remote_port {};
Amna38768302023-08-21 11:51:56 -040042 dht::InfoHash peer_id {};
43};
44
45static const constexpr struct option long_options[]
46 = {{"help", no_argument, nullptr, 'h'},
Adrien Béraudecde63f2023-08-26 18:11:21 -040047 {"version", no_argument, nullptr, 'V'},
48 {"verbose", no_argument, nullptr, 'v'},
Amna38768302023-08-21 11:51:56 -040049 {"port", required_argument, nullptr, 'p'},
50 {"ip", required_argument, nullptr, 'i'},
51 {"listen", no_argument, nullptr, 'l'},
Adrien Béraudecde63f2023-08-26 18:11:21 -040052 {"bootstrap", required_argument, nullptr, 'b'},
53 {"id_path", required_argument, nullptr, 'I'},
Amna38768302023-08-21 11:51:56 -040054 {nullptr, 0, nullptr, 0}};
55
56dhtnc_params
57parse_args(int argc, char** argv)
58{
59 dhtnc_params params;
60 int opt;
Amnab31c3742023-08-28 13:58:31 -040061 while ((opt = getopt_long(argc, argv, "hvVlI:b:p:i:", long_options, nullptr)) != -1) {
62 // fmt::print("opt: {} {}\n", opt, optarg);
Amna38768302023-08-21 11:51:56 -040063 switch (opt) {
64 case 'h':
65 params.help = true;
66 break;
Adrien Béraudecde63f2023-08-26 18:11:21 -040067 case 'V':
Amna38768302023-08-21 11:51:56 -040068 params.version = true;
69 break;
Adrien Béraudecde63f2023-08-26 18:11:21 -040070 case 'v':
71 params.verbose = true;
72 break;
Amna38768302023-08-21 11:51:56 -040073 case 'p':
Adrien Béraudecde63f2023-08-26 18:11:21 -040074 params.remote_port = std::stoi(optarg);
Amna38768302023-08-21 11:51:56 -040075 break;
76 case 'i':
Adrien Béraudecde63f2023-08-26 18:11:21 -040077 params.remote_host = optarg;
Amna38768302023-08-21 11:51:56 -040078 break;
79 case 'l':
80 params.listen = true;
81 break;
82 case 'b':
Adrien Béraudecde63f2023-08-26 18:11:21 -040083 params.bootstrap = optarg;
Amna38768302023-08-21 11:51:56 -040084 break;
Adrien Béraudecde63f2023-08-26 18:11:21 -040085 case 'I':
86 params.path = optarg;
Amna38768302023-08-21 11:51:56 -040087 break;
88 default:
89 std::cerr << "Invalid option" << std::endl;
90 exit(EXIT_FAILURE);
91 }
92 }
93
94 // If not listening, the peer_id argument is required
95 if (!params.listen) {
96 if (optind < argc) {
97 params.peer_id = dht::InfoHash(argv[optind]);
98 optind++; // Move to the next argument
99 } else {
100 std::cerr << "Error: Missing peer_id argument.\n";
101 exit(EXIT_FAILURE);
102 }
103 }
104
105 // default values
Adrien Béraudecde63f2023-08-26 18:11:21 -0400106 if (params.remote_port == 0)
Amnab31c3742023-08-28 13:58:31 -0400107 params.remote_port = 22;
Adrien Béraudecde63f2023-08-26 18:11:21 -0400108 if (params.remote_host.empty())
109 params.remote_host = "127.0.0.1";
110 if (params.bootstrap.empty())
111 params.bootstrap = "bootstrap.jami.net";
112 if (params.path.empty())
113 params.path = std::filesystem::path(getenv("HOME")) / ".dhtnet";
Amna38768302023-08-21 11:51:56 -0400114 return params;
115}
116
117static void
118setSipLogLevel()
119{
Amna38768302023-08-21 11:51:56 -0400120 int level = 0;
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400121 if (char* envvar = getenv("SIPLOGLEVEL")) {
Amna38768302023-08-21 11:51:56 -0400122 // From 0 (min) to 6 (max)
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400123 level = std::clamp(std::stoi(envvar), 0, 6);
Amna38768302023-08-21 11:51:56 -0400124 }
125
126 pj_log_set_level(level);
127 pj_log_set_log_func([](int level, const char* data, int /*len*/) {
128 });
129}
130
131int
132main(int argc, char** argv)
133{
Adrien Béraudecde63f2023-08-26 18:11:21 -0400134 fmt::print("dnc 1.0\n");
Amna38768302023-08-21 11:51:56 -0400135 setSipLogLevel();
136 auto params = parse_args(argc, argv);
Adrien Béraudecde63f2023-08-26 18:11:21 -0400137 auto identity = dhtnet::loadIdentity(params.path);
138 fmt::print("Loaded identity: {} from {}\n", identity.second->getId(), params.path);
Amna38768302023-08-21 11:51:56 -0400139
140 std::unique_ptr<dhtnet::Dnc> dhtnc;
141 if (params.listen) {
Amna38768302023-08-21 11:51:56 -0400142 // create dnc instance
Adrien Béraudecde63f2023-08-26 18:11:21 -0400143 dhtnc = std::make_unique<dhtnet::Dnc>(params.path, identity, params.bootstrap);
Amna38768302023-08-21 11:51:56 -0400144 } else {
Adrien Béraudecde63f2023-08-26 18:11:21 -0400145 dhtnc = std::make_unique<dhtnet::Dnc>(params.path,
146 identity,
147 params.bootstrap,
Amna38768302023-08-21 11:51:56 -0400148 params.peer_id,
Adrien Béraudecde63f2023-08-26 18:11:21 -0400149 params.remote_host,
150 params.remote_port);
Amna38768302023-08-21 11:51:56 -0400151 }
152 dhtnc->run();
153}