-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.cpp
executable file
·121 lines (109 loc) · 3.49 KB
/
client.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "include/dns_resolver.h"
#include "thread_pool.h"
#include <asio.hpp>
#include <fmt/core.h>
#include <memory>
#define THREAD_NUM 3
#define LINE_BUFFER_LEN 1024
std::shared_ptr<asio::io_context> context;
std::shared_ptr<dns::resolver<thread_pool>> resolver;
std::vector<std::thread> threads;
char line[LINE_BUFFER_LEN];
void print(dns::result err, std::string domain, std::vector<std::string> res)
{
if (err.is_ok()) {
std::cout << "domain: " << domain << std::endl;
for (auto ip : res) {
std::cout << "ip: " << ip << std::endl;
}
} else {
std::cout << err.message() << std::endl;
}
}
void print_usage(std::string program_name)
{
std::cout << fmt::format("Usage: {:s} <dns_server_ip>\n", program_name);
}
void print_help()
{
std::cout << "Please input the domain. If you input 'quit', the program will quit.\
If you input 'clear', the console will be clear. If you input 'usage', the usage will be shown.\n";
}
void handle_close()
{
std::cout << "The program will quit." << std::endl;
if (context) {
context->stop();
}
for (auto& thread : threads) {
thread.join();
}
resolver.reset();
context.reset();
exit(0);
}
int main(int argc, char const* argv[])
{
try {
signal(SIGINT, [](int sig) {
handle_close();
});
std::string program_name { argv[0] };
if (argc != 2) {
print_usage(program_name);
return 0;
}
std::string address { argv[1] };
context.reset(new asio::io_context(THREAD_NUM));
resolver.reset(new dns::resolver<thread_pool>(context, address,
std::shared_ptr<thread_pool> { new thread_pool { 1 } }));
for (auto i = 0; i != THREAD_NUM; i++) {
threads.push_back(std::thread([]() {
context->run();
}));
}
print_help();
typedef enum resolve_mode {
domain = 0,
ipaddr = 1,
} resolve_mode;
resolve_mode m = resolve_mode::domain;
while (true) {
std::cin.getline(line, LINE_BUFFER_LEN);
std::string in { line };
if (in == "quit") {
handle_close();
break;
} else if (in == "help") {
print_help();
} else if (in == "usage") {
print_usage(program_name);
} else if (in == "clear") {
system("clear");
} else if (in.starts_with("switch ")) {
std::string mode = in.substr(7);
if (mode == "d" || mode == "domain") {
m = resolve_mode::domain;
std::cout << "switch to domain mode" << std::endl;
} else if (mode == "ip") {
m = resolve_mode::ipaddr;
std::cout << "switch to ipaddr mode" << std::endl;
} else {
std::cout << "invalid mode:" << mode << std::endl;
}
} else {
if (m == resolve_mode::domain) {
resolver->resolve_domain(std::move(in), print);
} else if (m == resolve_mode::ipaddr) {
resolver->resolve_ipaddr(std::move(in), print);
} else {
std::cout << "wrong mode" << std::endl;
}
}
}
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
handle_close();
}
return 0;
}