Skip to content

Commit 4b9839d

Browse files
authored
Support query /etc/hosts (swoole#4341)
* Support query /etc/hosts * Change NULL to nullptr
1 parent 067f594 commit 4b9839d

File tree

6 files changed

+190
-2
lines changed

6 files changed

+190
-2
lines changed

.github/workflows/lib.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ jobs:
3434
sudo make install
3535

3636
- name: make test
37-
run: cd core-tests && ./run.sh
37+
run:
38+
cd core-tests && ./run.sh
3839

3940
- name: run coverage
4041
shell: bash

core-tests/src/network/dns.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,11 @@ TEST(dns, load_resolv_conf) {
9797
ASSERT_FALSE(dns_server.first.empty());
9898
ASSERT_NE(dns_server.second, 0);
9999
}
100+
101+
TEST(dns, gethosts) {
102+
std::string ip = swoole::coroutine::get_ip_by_hosts("localhost");
103+
ASSERT_EQ(ip, "127.0.0.1");
104+
105+
ip = swoole::coroutine::get_ip_by_hosts("non.exist.com");
106+
ASSERT_EQ(ip, "");
107+
}

include/swoole_coroutine_socket.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ std::vector<std::string> dns_lookup_impl_with_socket(const char *domain, int fam
596596
#ifdef SW_USE_CARES
597597
std::vector<std::string> dns_lookup_impl_with_cares(const char *domain, int family, double timeout);
598598
#endif
599+
std::string get_ip_by_hosts(std::string domain);
599600
//-------------------------------------------------------------------------------
600601
} // namespace coroutine
601602
} // namespace swoole

include/swoole_socket.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,4 @@ network::Socket *make_server_socket(enum swSocket_type socket_type,
595595
int backlog = SW_BACKLOG);
596596
bool verify_ip(int __af, const std::string &str);
597597
} // namespace swoole
598+

src/network/dns.cc

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@
1616

1717
#include "swoole.h"
1818
#include "swoole_coroutine_socket.h"
19+
#include "swoole_util.h"
1920

2021
#include <string>
2122
#include <iostream>
2223
#include <vector>
2324

25+
#define SW_PATH_HOSTS "/etc/hosts"
26+
2427
#ifdef SW_USE_CARES
2528
#include <ares.h>
2629
#endif
@@ -103,6 +106,162 @@ static int domain_encode(const char *src, int n, char *dest);
103106
static void domain_decode(char *str);
104107
static std::string parse_ip_address(void *vaddr, int type);
105108

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;
145+
}
146+
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';
164+
165+
q = p - 1;
166+
while ((q >= line) && isspace(*q)) {
167+
q--;
168+
}
169+
*++q = '\0';
170+
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) {
185+
continue;
186+
}
187+
188+
*p = '\0';
189+
190+
p++;
191+
while (*p && isspace(*p)) {
192+
p++;
193+
}
194+
if (!*p) {
195+
continue;
196+
}
197+
198+
txthost = p;
199+
200+
while (*p && !isspace(*p)) {
201+
p++;
202+
}
203+
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+
}
229+
}
230+
231+
result.first = txthost;
232+
result.second = txtaddr;
233+
234+
free(line);
235+
236+
return result;
237+
}
238+
239+
if (line) free(line);
240+
241+
return result;
242+
}
243+
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 "";
263+
}
264+
106265
static std::string parse_ip_address(void *vaddr, int type) {
107266
auto addr = reinterpret_cast<unsigned char *>(vaddr);
108267
std::string ip_addr;
@@ -199,7 +358,7 @@ std::vector<std::string> dns_lookup_impl_with_socket(const char *domain, int fam
199358

200359
auto ret = _sock.recv(packet, sizeof(packet) - 1);
201360
if (ret <= 0) {
202-
swoole_set_last_error(_sock.errCode == ECANCELED ? SW_ERROR_CO_CANCELED: SW_ERROR_DNSLOOKUP_RESOLVE_FAILED);
361+
swoole_set_last_error(_sock.errCode == ECANCELED ? SW_ERROR_CO_CANCELED : SW_ERROR_DNSLOOKUP_RESOLVE_FAILED);
203362
return result;
204363
}
205364

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
swoole_coroutine: dnslookup query hosts
3+
--SKIPIF--
4+
<?php require __DIR__ . '/../include/skipif.inc'; ?>
5+
--FILE--
6+
<?php
7+
require __DIR__ . '/../include/bootstrap.php';
8+
9+
use Swoole\Coroutine;
10+
use Swoole\Coroutine\System;
11+
use function Swoole\Coroutine\run;
12+
13+
run(function () {
14+
Assert::eq(System::dnsLookup('localhost', 3, AF_INET), '127.0.0.1');
15+
});
16+
17+
?>
18+
--EXPECT--

0 commit comments

Comments
 (0)