Skip to content

Commit e64e5a3

Browse files
Enhancing the support for query of /etc/hosts and simplifying the code. (#4349)
* enhance the query of /etc/hosts * change if statement position * comparison of integer expressions of different signedness * comparison of integer expressions of different signedness * unit test * repeat declare * hook.cpp * debug * cancel debug * unit test * unit test * unit test * remove nullptr * unit test * unit test * unit test * unit test * unit test * unit test * unit test * unit test * unit test * unit test * unit test change sstream to fstream * unit test * remove ofstream::out * change string to char * test * test * add rename exception * add rename * unit test * unit test * unit test * add ON_SCOPE_EXIT * add ; * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * clang format * optimize get_ip_by_hosts * add domains.clear() * add swoole_set_hosts_path api and optimize code. * add swoole_set_hosts_path api and optimize code. * clang-format
1 parent bc1f5c7 commit e64e5a3

File tree

4 files changed

+76
-137
lines changed

4 files changed

+76
-137
lines changed

core-tests/include/test_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <thread>
1515
#include <mutex>
1616
#include <unordered_map>
17+
#include <fstream>
18+
1719

1820
#define TEST_HOST "127.0.0.1"
1921
#define TEST_PORT 9501

core-tests/src/network/dns.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
#include "swoole_socket.h"
2323

24+
#include "swoole_util.h"
25+
2426
using namespace swoole;
2527
using swoole::coroutine::Socket;
2628
using swoole::coroutine::System;
@@ -61,7 +63,7 @@ TEST(dns, cancel) {
6163
// swoole_set_log_level(SW_LOG_TRACE);
6264
test::coroutine::run([](void *arg) {
6365
auto co = Coroutine::get_current_safe();
64-
Coroutine::create([co](void *){
66+
Coroutine::create([co](void *) {
6567
System::sleep(0.002);
6668
co->cancel();
6769
});
@@ -99,9 +101,41 @@ TEST(dns, load_resolv_conf) {
99101
}
100102

101103
TEST(dns, gethosts) {
104+
char hosts_file[] = "/tmp/swoole_hosts";
105+
ofstream file(hosts_file);
106+
if (!file.is_open()) {
107+
std::cout << std::string("file open failed: ") + std::string(strerror(errno)) << std::endl;
108+
throw strerror(errno);
109+
}
110+
111+
ON_SCOPE_EXIT {
112+
unlink(hosts_file);
113+
};
114+
115+
file << "\n";
116+
file << "127.0.0.1\n";
117+
file << "127.0.0.1 localhost\n";
118+
file << "# 127.0.0.1 aaa.com\n";
119+
file << " 127.0.0.1 bbb.com ccc.com #ddd.com\n";
120+
file.close();
121+
122+
swoole::coroutine::swoole_set_hosts_path(hosts_file);
123+
102124
std::string ip = swoole::coroutine::get_ip_by_hosts("localhost");
103125
ASSERT_EQ(ip, "127.0.0.1");
104126

127+
ip = swoole::coroutine::get_ip_by_hosts("aaa.com");
128+
ASSERT_EQ(ip, "");
129+
130+
ip = swoole::coroutine::get_ip_by_hosts("bbb.com");
131+
ASSERT_EQ(ip, "127.0.0.1");
132+
133+
ip = swoole::coroutine::get_ip_by_hosts("ccc.com");
134+
ASSERT_EQ(ip, "127.0.0.1");
135+
136+
ip = swoole::coroutine::get_ip_by_hosts("ddd.com");
137+
ASSERT_EQ(ip, "");
138+
105139
ip = swoole::coroutine::get_ip_by_hosts("non.exist.com");
106140
ASSERT_EQ(ip, "");
107141
}

include/swoole_coroutine_socket.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ class ProtocolSwitch {
587587
bool ori_open_length_check;
588588
Protocol ori_protocol;
589589
Socket *socket_;
590+
590591
public:
591592
ProtocolSwitch(Socket *socket) {
592593
ori_open_eof_check = socket->open_eof_check;
@@ -608,7 +609,8 @@ std::vector<std::string> dns_lookup_impl_with_socket(const char *domain, int fam
608609
#ifdef SW_USE_CARES
609610
std::vector<std::string> dns_lookup_impl_with_cares(const char *domain, int family, double timeout);
610611
#endif
611-
std::string get_ip_by_hosts(std::string domain);
612+
std::string get_ip_by_hosts(const std::string &domain);
613+
void swoole_set_hosts_path(char *hosts_file);
612614
//-------------------------------------------------------------------------------
613615
} // namespace coroutine
614616
} // namespace swoole

src/network/dns.cc

Lines changed: 36 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
#include <string>
2222
#include <iostream>
2323
#include <vector>
24+
#include <unordered_map>
25+
#include <sstream>
26+
#include <fstream>
2427

2528
#define SW_PATH_HOSTS "/etc/hosts"
2629

@@ -101,165 +104,63 @@ struct RR_FLAGS {
101104
};
102105

103106
static uint16_t dns_request_id = 1;
107+
char *swoole_hosts = nullptr;
104108

105109
static int domain_encode(const char *src, int n, char *dest);
106110
static void domain_decode(char *str);
107111
static std::string parse_ip_address(void *vaddr, int type);
108112

109-
static int read_line(FILE *fp, char **buf, size_t *bufsize) {
110-
char *newbuf;
111-
size_t offset = 0;
112-
size_t len;
113-
114-
if (*buf == nullptr) {
115-
*buf = (char *) malloc(128);
116-
if (!*buf) {
117-
return SW_ERR;
118-
}
119-
*bufsize = 128;
120-
}
121-
122-
for (;;) {
123-
int bytestoread = *bufsize - offset;
124-
if (!fgets(*buf + offset, bytestoread, fp)) {
125-
return SW_ERR;
126-
}
127-
128-
len = offset + strlen(*buf + offset);
129-
if ((*buf)[len - 1] == '\n') {
130-
(*buf)[len - 1] = 0;
131-
break;
132-
}
133-
offset = len;
134-
if (len < *bufsize - 1) {
135-
continue;
136-
}
137-
newbuf = (char *) realloc(*buf, *bufsize * 2);
138-
if (!newbuf) {
139-
free(*buf);
140-
*buf = nullptr;
141-
return SW_ERR;
142-
}
143-
*buf = newbuf;
144-
*bufsize *= 2;
113+
std::string get_ip_by_hosts(const std::string &search_domain) {
114+
std::ifstream file(swoole_hosts ? swoole_hosts : SW_PATH_HOSTS);
115+
if (!file.is_open()) {
116+
return "";
145117
}
146118

147-
return SW_OK;
148-
}
149-
150-
static std::pair<std::string, std::string> get_hostent(FILE *fp) {
151-
char *line = nullptr, *p, *q;
152-
char *txtaddr, *txthost, *txtalias;
153-
int status;
154-
size_t linesize, naliases;
155-
156-
std::pair<std::string, std::string> result{};
157-
158-
while ((status = read_line(fp, &line, &linesize)) == SW_OK) {
159-
p = line;
160-
while (*p && (*p != '#')) {
161-
p++;
162-
}
163-
*p = '\0';
119+
std::string line;
120+
std::string domain;
121+
std::string txtaddr;
122+
std::vector<std::string> domains;
123+
std::unordered_map<std::string, std::string> result{};
164124

165-
q = p - 1;
166-
while ((q >= line) && isspace(*q)) {
167-
q--;
125+
while (getline(file, line)) {
126+
std::string::size_type ops = line.find_first_of('#');
127+
if (ops != std::string::npos) {
128+
line[ops] = '\0';
168129
}
169-
*++q = '\0';
170130

171-
p = line;
172-
while (*p && isspace(*q)) {
173-
q--;
174-
}
175-
if (!*p) {
176-
continue;
177-
}
178-
179-
txtaddr = p;
180-
181-
while (*p && !isspace(*p)) {
182-
p++;
183-
}
184-
if (!*p) {
131+
if (line[0] == '\n' || line[0] == '\0' || line[0] == '\r') {
185132
continue;
186133
}
187134

188-
*p = '\0';
189-
190-
p++;
191-
while (*p && isspace(*p)) {
192-
p++;
135+
std::istringstream stream(line);
136+
while (stream >> domain) {
137+
domains.push_back(domain);
193138
}
194-
if (!*p) {
139+
if (domains.empty() || domains.size() == 1) {
140+
domains.clear();
195141
continue;
196142
}
197143

198-
txthost = p;
199-
200-
while (*p && !isspace(*p)) {
201-
p++;
144+
txtaddr = domains[0];
145+
for (size_t i = 1; i < domains.size(); i++) {
146+
result.insert(std::make_pair(domains[i], txtaddr));
202147
}
203148

204-
txtalias = nullptr;
205-
if (*p) {
206-
q = p + 1;
207-
while (*q && isspace(*q)) {
208-
q++;
209-
}
210-
if (*q) {
211-
txtalias = q;
212-
}
213-
}
214-
215-
*p = '\0';
216-
217-
naliases = 0;
218-
if (txtalias) {
219-
p = txtalias;
220-
while (*p) {
221-
while (*p && !isspace(*p)) {
222-
p++;
223-
}
224-
while (*p && isspace(*p)) {
225-
p++;
226-
}
227-
naliases++;
228-
}
149+
auto iter = result.find(search_domain);
150+
if (iter != result.end()) {
151+
return iter->second;
152+
} else {
153+
result.clear();
154+
domains.clear();
155+
continue;
229156
}
230-
231-
result.first = txthost;
232-
result.second = txtaddr;
233-
234-
free(line);
235-
236-
return result;
237157
}
238158

239-
if (line) free(line);
240-
241-
return result;
159+
return "";
242160
}
243161

244-
std::string get_ip_by_hosts(std::string domain) {
245-
std::unordered_map<std::string, std::string> _map;
246-
auto fp = fopen(SW_PATH_HOSTS, "r");
247-
if (fp == nullptr) {
248-
return "";
249-
}
250-
ON_SCOPE_EXIT {
251-
fclose(fp);
252-
};
253-
while (1) {
254-
auto result = get_hostent(fp);
255-
if (result.first == "") {
256-
break;
257-
}
258-
if (result.first == domain) {
259-
return result.second;
260-
}
261-
}
262-
return "";
162+
void swoole_set_hosts_path(char *hosts_file) {
163+
swoole_hosts = hosts_file;
263164
}
264165

265166
static std::string parse_ip_address(void *vaddr, int type) {

0 commit comments

Comments
 (0)