mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-27 06:51:04 +08:00
IPv6 related refactoring
This commit is contained in:
parent
d7abd53062
commit
29534218d7
@ -1126,16 +1126,16 @@ Parse 64-bit integer value held by string `s`.
|
||||
### mg\_aton()
|
||||
|
||||
```
|
||||
bool mg_aton(const char *s, uint32_t *ipaddr);
|
||||
bool mg_aton(struct mg_str str, uint32_t *ipaddr);
|
||||
```
|
||||
|
||||
Parse IP address held by `s` and store it in `ipaddr`. Return true on success.
|
||||
Parse IP address held by `str` and store it in `ipaddr`. Return true on success.
|
||||
|
||||
|
||||
### mg\_ntoa()
|
||||
|
||||
```c
|
||||
char *mg_ntoa(uint32_t ipaddr, char *buf, size_t len);
|
||||
char *mg_ntoa(const struct mg_addr *, char *buf, size_t len);
|
||||
```
|
||||
|
||||
Stringify IP address `ipaddr` into a buffer `buf`, `len`. Return `buf`.
|
||||
|
113
mongoose.c
113
mongoose.c
@ -194,32 +194,43 @@ static size_t mg_dns_parse_name(const uint8_t *s, const uint8_t *e, size_t off,
|
||||
// 0000 00 01 81 80 00 01 00 01 00 00 00 00 07 63 65 73 .............ces
|
||||
// 0010 61 6e 74 61 03 63 6f 6d 00 00 01 00 01 c0 0c 00 anta.com........
|
||||
// 0020 01 00 01 00 00 02 57 00 04 94 fb 36 ec ......W....6.
|
||||
int mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
||||
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
||||
struct mg_dns_header *h = (struct mg_dns_header *) buf;
|
||||
const uint8_t *s = buf + sizeof(*h), *e = &buf[len];
|
||||
uint16_t atype, aclass;
|
||||
size_t i, j = 0, n;
|
||||
memset(dm, 0, sizeof(*dm));
|
||||
if (len < sizeof(*h)) return 0; // Too small, headers dont fit
|
||||
if (len > 512) return 0; // Too large, we don't expect that
|
||||
if (mg_ntohs(h->num_questions) > 2) return 0; // Sanity
|
||||
if (mg_ntohs(h->num_answers) > 5) return 0; // Sanity
|
||||
dm->txnid = mg_ntohs(h->transaction_id);
|
||||
{
|
||||
// char *s = mg_hexdump(buf, len);
|
||||
// LOG(LL_DEBUG, ("--\n%s\n--\n", s));
|
||||
// free(s);
|
||||
}
|
||||
for (i = 0; i < mg_ntohs(h->num_questions); i++) {
|
||||
j += mg_dns_parse_name(s, e, j, dm->name, sizeof(dm->name), 0) + 5;
|
||||
// LOG(LL_INFO, ("QUE %zu %zu [%s]", i, j, dm->name));
|
||||
}
|
||||
for (i = 0; i < mg_ntohs(h->num_answers); i++) {
|
||||
j += mg_dns_parse_name(s, e, j, dm->name, sizeof(dm->name), 0) + 9;
|
||||
// LOG(LL_DEBUG, ("NAME %s", dm->name));
|
||||
if (&s[j] + 2 > e) break;
|
||||
atype = ((int) s[j - 8] << 8) | s[j - 7];
|
||||
aclass = ((int) s[j - 6] << 8) | s[j - 5];
|
||||
n = ((int) s[j] << 8) | s[j + 1];
|
||||
// LOG(LL_DEBUG,
|
||||
//("NAME %s, IP len %zu t: %hu, c: %hu", dm->name, n, atype, aclass));
|
||||
if (&s[j] + 2 + n > e) break;
|
||||
if (n == 4) {
|
||||
dm->txnid = mg_ntohs(h->transaction_id);
|
||||
if (n == 4 && atype == 1 && aclass == 1) {
|
||||
memcpy(&dm->ipaddr, &s[j + 2], 4);
|
||||
return 1; // Return success
|
||||
dm->resolved = true;
|
||||
break; // Return success
|
||||
}
|
||||
j += 2 + n;
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
@ -235,15 +246,23 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
} else if (ev == MG_EV_READ) {
|
||||
struct mg_dns_message dm;
|
||||
int resolved = 0;
|
||||
if (mg_dns_parse(c->recv.buf, c->recv.len, &dm)) {
|
||||
if (mg_dns_parse(c->recv.buf, c->recv.len, &dm) == false) {
|
||||
char *s = mg_hexdump(c->recv.buf, c->recv.len);
|
||||
LOG(LL_ERROR, ("Unexpected DNS response:\n%s\n", s));
|
||||
free(s);
|
||||
} else {
|
||||
for (d = (struct dns_data *) c->pfn_data; d != NULL; d = tmp) {
|
||||
tmp = d->next;
|
||||
// LOG(LL_INFO, ("d %p %p", d, tmp));
|
||||
// LOG(LL_INFO, ("d %p %hu %hu", d, d->txnid, dm.txnid));
|
||||
if (dm.txnid != d->txnid) continue;
|
||||
if (d->c->is_resolving) {
|
||||
d->c->is_resolving = 0;
|
||||
d->c->peer.ip = dm.ipaddr;
|
||||
mg_connect_resolved(d->c);
|
||||
if (dm.resolved) {
|
||||
d->c->peer.ip = dm.ipaddr;
|
||||
mg_connect_resolved(d->c);
|
||||
} else {
|
||||
mg_error(d->c, "%s DNS lookup failed", dm.name);
|
||||
}
|
||||
mg_dns_free(head, d);
|
||||
} else {
|
||||
LOG(LL_ERROR, ("%p already resolved", d->c->fd));
|
||||
@ -271,7 +290,7 @@ void mg_dns_send(struct mg_connection *c, const struct mg_str *name,
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.header.transaction_id = mg_htons(txnid);
|
||||
pkt.header.flags = mg_htons(0x100);
|
||||
pkt.header.num_questions = mg_htons(1);
|
||||
pkt.header.num_questions = mg_htons(2);
|
||||
for (i = n = 0; i < sizeof(pkt.data) - 5; i++) {
|
||||
if (name->ptr[i] == '.' || i >= name->len) {
|
||||
pkt.data[n] = (uint8_t)(i - n);
|
||||
@ -282,6 +301,8 @@ void mg_dns_send(struct mg_connection *c, const struct mg_str *name,
|
||||
}
|
||||
memcpy(&pkt.data[n], "\x00\x00\x01\x00\x01", 5); // A query
|
||||
n += 5;
|
||||
memcpy(&pkt.data[n], "\xc0\x0c\x00\x1c\x00\x01", 6); // AAAA query
|
||||
n += 6;
|
||||
mg_send(c, &pkt, sizeof(pkt.header) + n);
|
||||
#if 0
|
||||
// Immediately after A query, send AAAA query. Whatever reply comes first,
|
||||
@ -295,15 +316,7 @@ void mg_dns_send(struct mg_connection *c, const struct mg_str *name,
|
||||
void mg_resolve(struct mg_mgr *mgr, struct mg_connection *c,
|
||||
struct mg_str *name, int ms) {
|
||||
struct dns_data *d = NULL;
|
||||
int resolved = mg_aton(name->ptr, &c->peer.ip);
|
||||
|
||||
// Try to parse name as IP address
|
||||
if (mg_vcmp(name, "localhost") == 0) {
|
||||
resolved = 1;
|
||||
c->peer.ip = mg_htonl(0x7f000001);
|
||||
}
|
||||
|
||||
if (resolved) {
|
||||
if (mg_aton(*name, &c->peer)) {
|
||||
// name is an IP address, do not fire name resolution
|
||||
mg_connect_resolved(c);
|
||||
} else {
|
||||
@ -1928,6 +1941,44 @@ char *mg_straddr(struct mg_connection *c, char *buf, size_t len) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len) {
|
||||
uint8_t p[4];
|
||||
memcpy(p, &addr->ip, sizeof(p));
|
||||
snprintf(buf, len, "%hhu.%hhu.%hhu.%hhu", p[0], p[1], p[2], p[3]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool mg_aton(struct mg_str str, struct mg_addr *addr) {
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
// LOG(LL_INFO, ("[%.*s]", (int) str.len, str.ptr));
|
||||
if (!mg_casecmp(str.ptr, "localhost")) {
|
||||
addr->ip = mg_htonl(0x7f000001);
|
||||
return true;
|
||||
} else if (addr->is_ip6) {
|
||||
return false;
|
||||
} else {
|
||||
size_t i, num_octets = 0;
|
||||
// LOG(LL_DEBUG, ("[%.*s]", (int) str.len, str.ptr));
|
||||
for (i = 0; i < str.len; i++) {
|
||||
// LOG(LL_DEBUG,
|
||||
//(" %c %zu %hhu %zu", str.ptr[i], i, data[num_octets], num_octets));
|
||||
if (str.ptr[i] >= '0' && str.ptr[i] <= '9') {
|
||||
int octet = data[num_octets] * 10 + (str.ptr[i] - '0');
|
||||
if (octet > 255) return false;
|
||||
data[num_octets] = octet;
|
||||
} else if (str.ptr[i] == '.') {
|
||||
if (num_octets >= 3 || i == 0 || str.ptr[i - 1] == '.') return false;
|
||||
num_octets++;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (num_octets != 3 || str.ptr[i - 1] == '.') return false;
|
||||
memcpy(&addr->ip, data, sizeof(data));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
#line 1 "src/sha1.c"
|
||||
#endif
|
||||
@ -2424,15 +2475,20 @@ SOCKET mg_open_listener(const char *ip, uint16_t port, int is_udp) {
|
||||
int on = 1;
|
||||
int proto = is_udp ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
int type = is_udp ? SOCK_DGRAM : SOCK_STREAM;
|
||||
struct mg_addr addr;
|
||||
SOCKET fd;
|
||||
|
||||
memset(&usa, 0, sizeof(usa));
|
||||
usa.sin.sin_family = AF_INET;
|
||||
usa.sin.sin_port = mg_htons(port);
|
||||
mg_aton(mg_url_host(ip), &addr);
|
||||
*(uint32_t *) &usa.sin.sin_addr = addr.ip;
|
||||
#if 0
|
||||
mg_aton(ip, (uint32_t *) &usa.sin.sin_addr);
|
||||
if (!mg_casecmp(ip, "localhost")) {
|
||||
*(uint32_t *) &usa.sin.sin_addr = mg_htonl(0x7f000001);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fd = socket(AF_INET, type, proto)) != INVALID_SOCKET &&
|
||||
#if !defined(_WIN32) || !defined(SO_EXCLUSIVEADDRUSE)
|
||||
@ -3607,23 +3663,6 @@ int64_t mg_to64(const char *s) {
|
||||
return result * neg;
|
||||
}
|
||||
|
||||
bool mg_aton(const char *s, uint32_t *ip) {
|
||||
uint8_t data[4] = {0, 0, 0, 0}, ok = 0;
|
||||
if (s != NULL && sscanf(s, "%hhu.%hhu.%hhu.%hhu", &data[0], &data[1],
|
||||
&data[2], &data[3]) == 4) {
|
||||
memcpy(ip, data, sizeof(data));
|
||||
ok = 1;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
char *mg_ntoa(uint32_t ipaddr, char *buf, size_t len) {
|
||||
uint8_t p[4];
|
||||
memcpy(p, &ipaddr, sizeof(p));
|
||||
snprintf(buf, len, "%hhu.%hhu.%hhu.%hhu", p[0], p[1], p[2], p[3]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
double mg_time(void) {
|
||||
#if MG_ARCH == MG_ARCH_WIN32
|
||||
SYSTEMTIME sysnow;
|
||||
|
13
mongoose.h
13
mongoose.h
@ -428,8 +428,6 @@ unsigned long mg_unhexn(const char *s, int len);
|
||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
int64_t mg_to64(const char *s);
|
||||
bool mg_aton(const char *s, uint32_t *ipaddr);
|
||||
char *mg_ntoa(uint32_t ipaddr, char *buf, size_t len);
|
||||
double mg_time(void);
|
||||
unsigned long mg_millis(void);
|
||||
void mg_usleep(unsigned long usecs);
|
||||
@ -594,8 +592,10 @@ struct mg_mgr {
|
||||
};
|
||||
|
||||
struct mg_addr {
|
||||
uint16_t port; // TCP or UDP port in network byte order
|
||||
uint32_t ip; // IP address in network byte order
|
||||
uint16_t port; // TCP or UDP port in network byte order
|
||||
uint32_t ip; // IP address in network byte order
|
||||
uint8_t ip6[16]; // IPv6 address
|
||||
bool is_ip6; // True when address is IPv6 address
|
||||
};
|
||||
|
||||
struct mg_connection {
|
||||
@ -640,6 +640,8 @@ int mg_printf(struct mg_connection *, const char *fmt, ...);
|
||||
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||
char *mg_straddr(struct mg_connection *, char *, size_t);
|
||||
bool mg_socketpair(int *s1, int *s2);
|
||||
bool mg_aton(struct mg_str str, struct mg_addr *addr);
|
||||
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
|
||||
|
||||
|
||||
|
||||
@ -797,10 +799,11 @@ int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
||||
|
||||
struct mg_dns_message {
|
||||
uint16_t txnid; // Transaction ID
|
||||
bool resolved; // Resolve successful, ipaddr is set
|
||||
uint32_t ipaddr; // Resolved IPv4 address
|
||||
char name[256]; // Host name
|
||||
};
|
||||
|
||||
void mg_resolve(struct mg_mgr *, struct mg_connection *, struct mg_str *, int);
|
||||
void mg_resolve_cancel(struct mg_mgr *, struct mg_connection *);
|
||||
int mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
|
||||
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
|
||||
|
53
src/dns.c
53
src/dns.c
@ -68,32 +68,43 @@ static size_t mg_dns_parse_name(const uint8_t *s, const uint8_t *e, size_t off,
|
||||
// 0000 00 01 81 80 00 01 00 01 00 00 00 00 07 63 65 73 .............ces
|
||||
// 0010 61 6e 74 61 03 63 6f 6d 00 00 01 00 01 c0 0c 00 anta.com........
|
||||
// 0020 01 00 01 00 00 02 57 00 04 94 fb 36 ec ......W....6.
|
||||
int mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
||||
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
||||
struct mg_dns_header *h = (struct mg_dns_header *) buf;
|
||||
const uint8_t *s = buf + sizeof(*h), *e = &buf[len];
|
||||
uint16_t atype, aclass;
|
||||
size_t i, j = 0, n;
|
||||
memset(dm, 0, sizeof(*dm));
|
||||
if (len < sizeof(*h)) return 0; // Too small, headers dont fit
|
||||
if (len > 512) return 0; // Too large, we don't expect that
|
||||
if (mg_ntohs(h->num_questions) > 2) return 0; // Sanity
|
||||
if (mg_ntohs(h->num_answers) > 5) return 0; // Sanity
|
||||
dm->txnid = mg_ntohs(h->transaction_id);
|
||||
{
|
||||
// char *s = mg_hexdump(buf, len);
|
||||
// LOG(LL_DEBUG, ("--\n%s\n--\n", s));
|
||||
// free(s);
|
||||
}
|
||||
for (i = 0; i < mg_ntohs(h->num_questions); i++) {
|
||||
j += mg_dns_parse_name(s, e, j, dm->name, sizeof(dm->name), 0) + 5;
|
||||
// LOG(LL_INFO, ("QUE %zu %zu [%s]", i, j, dm->name));
|
||||
}
|
||||
for (i = 0; i < mg_ntohs(h->num_answers); i++) {
|
||||
j += mg_dns_parse_name(s, e, j, dm->name, sizeof(dm->name), 0) + 9;
|
||||
// LOG(LL_DEBUG, ("NAME %s", dm->name));
|
||||
if (&s[j] + 2 > e) break;
|
||||
atype = ((int) s[j - 8] << 8) | s[j - 7];
|
||||
aclass = ((int) s[j - 6] << 8) | s[j - 5];
|
||||
n = ((int) s[j] << 8) | s[j + 1];
|
||||
// LOG(LL_DEBUG,
|
||||
//("NAME %s, IP len %zu t: %hu, c: %hu", dm->name, n, atype, aclass));
|
||||
if (&s[j] + 2 + n > e) break;
|
||||
if (n == 4) {
|
||||
dm->txnid = mg_ntohs(h->transaction_id);
|
||||
if (n == 4 && atype == 1 && aclass == 1) {
|
||||
memcpy(&dm->ipaddr, &s[j + 2], 4);
|
||||
return 1; // Return success
|
||||
dm->resolved = true;
|
||||
break; // Return success
|
||||
}
|
||||
j += 2 + n;
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
@ -109,15 +120,23 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
} else if (ev == MG_EV_READ) {
|
||||
struct mg_dns_message dm;
|
||||
int resolved = 0;
|
||||
if (mg_dns_parse(c->recv.buf, c->recv.len, &dm)) {
|
||||
if (mg_dns_parse(c->recv.buf, c->recv.len, &dm) == false) {
|
||||
char *s = mg_hexdump(c->recv.buf, c->recv.len);
|
||||
LOG(LL_ERROR, ("Unexpected DNS response:\n%s\n", s));
|
||||
free(s);
|
||||
} else {
|
||||
for (d = (struct dns_data *) c->pfn_data; d != NULL; d = tmp) {
|
||||
tmp = d->next;
|
||||
// LOG(LL_INFO, ("d %p %p", d, tmp));
|
||||
// LOG(LL_INFO, ("d %p %hu %hu", d, d->txnid, dm.txnid));
|
||||
if (dm.txnid != d->txnid) continue;
|
||||
if (d->c->is_resolving) {
|
||||
d->c->is_resolving = 0;
|
||||
d->c->peer.ip = dm.ipaddr;
|
||||
mg_connect_resolved(d->c);
|
||||
if (dm.resolved) {
|
||||
d->c->peer.ip = dm.ipaddr;
|
||||
mg_connect_resolved(d->c);
|
||||
} else {
|
||||
mg_error(d->c, "%s DNS lookup failed", dm.name);
|
||||
}
|
||||
mg_dns_free(head, d);
|
||||
} else {
|
||||
LOG(LL_ERROR, ("%p already resolved", d->c->fd));
|
||||
@ -145,7 +164,7 @@ void mg_dns_send(struct mg_connection *c, const struct mg_str *name,
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.header.transaction_id = mg_htons(txnid);
|
||||
pkt.header.flags = mg_htons(0x100);
|
||||
pkt.header.num_questions = mg_htons(1);
|
||||
pkt.header.num_questions = mg_htons(2);
|
||||
for (i = n = 0; i < sizeof(pkt.data) - 5; i++) {
|
||||
if (name->ptr[i] == '.' || i >= name->len) {
|
||||
pkt.data[n] = (uint8_t)(i - n);
|
||||
@ -156,6 +175,8 @@ void mg_dns_send(struct mg_connection *c, const struct mg_str *name,
|
||||
}
|
||||
memcpy(&pkt.data[n], "\x00\x00\x01\x00\x01", 5); // A query
|
||||
n += 5;
|
||||
memcpy(&pkt.data[n], "\xc0\x0c\x00\x1c\x00\x01", 6); // AAAA query
|
||||
n += 6;
|
||||
mg_send(c, &pkt, sizeof(pkt.header) + n);
|
||||
#if 0
|
||||
// Immediately after A query, send AAAA query. Whatever reply comes first,
|
||||
@ -169,15 +190,7 @@ void mg_dns_send(struct mg_connection *c, const struct mg_str *name,
|
||||
void mg_resolve(struct mg_mgr *mgr, struct mg_connection *c,
|
||||
struct mg_str *name, int ms) {
|
||||
struct dns_data *d = NULL;
|
||||
int resolved = mg_aton(name->ptr, &c->peer.ip);
|
||||
|
||||
// Try to parse name as IP address
|
||||
if (mg_vcmp(name, "localhost") == 0) {
|
||||
resolved = 1;
|
||||
c->peer.ip = mg_htonl(0x7f000001);
|
||||
}
|
||||
|
||||
if (resolved) {
|
||||
if (mg_aton(*name, &c->peer)) {
|
||||
// name is an IP address, do not fire name resolution
|
||||
mg_connect_resolved(c);
|
||||
} else {
|
||||
|
@ -5,10 +5,11 @@
|
||||
|
||||
struct mg_dns_message {
|
||||
uint16_t txnid; // Transaction ID
|
||||
bool resolved; // Resolve successful, ipaddr is set
|
||||
uint32_t ipaddr; // Resolved IPv4 address
|
||||
char name[256]; // Host name
|
||||
};
|
||||
|
||||
void mg_resolve(struct mg_mgr *, struct mg_connection *, struct mg_str *, int);
|
||||
void mg_resolve_cancel(struct mg_mgr *, struct mg_connection *);
|
||||
int mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
|
||||
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
|
||||
|
40
src/net.c
40
src/net.c
@ -1,5 +1,5 @@
|
||||
#include "net.h"
|
||||
#include "log.h"
|
||||
#include "net.h"
|
||||
#include "util.h"
|
||||
|
||||
int mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
|
||||
@ -25,3 +25,41 @@ char *mg_straddr(struct mg_connection *c, char *buf, size_t len) {
|
||||
mg_ntohs(c->peer.port));
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len) {
|
||||
uint8_t p[4];
|
||||
memcpy(p, &addr->ip, sizeof(p));
|
||||
snprintf(buf, len, "%hhu.%hhu.%hhu.%hhu", p[0], p[1], p[2], p[3]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool mg_aton(struct mg_str str, struct mg_addr *addr) {
|
||||
uint8_t data[4] = {0, 0, 0, 0};
|
||||
// LOG(LL_INFO, ("[%.*s]", (int) str.len, str.ptr));
|
||||
if (!mg_casecmp(str.ptr, "localhost")) {
|
||||
addr->ip = mg_htonl(0x7f000001);
|
||||
return true;
|
||||
} else if (addr->is_ip6) {
|
||||
return false;
|
||||
} else {
|
||||
size_t i, num_octets = 0;
|
||||
// LOG(LL_DEBUG, ("[%.*s]", (int) str.len, str.ptr));
|
||||
for (i = 0; i < str.len; i++) {
|
||||
// LOG(LL_DEBUG,
|
||||
//(" %c %zu %hhu %zu", str.ptr[i], i, data[num_octets], num_octets));
|
||||
if (str.ptr[i] >= '0' && str.ptr[i] <= '9') {
|
||||
int octet = data[num_octets] * 10 + (str.ptr[i] - '0');
|
||||
if (octet > 255) return false;
|
||||
data[num_octets] = octet;
|
||||
} else if (str.ptr[i] == '.') {
|
||||
if (num_octets >= 3 || i == 0 || str.ptr[i - 1] == '.') return false;
|
||||
num_octets++;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (num_octets != 3 || str.ptr[i - 1] == '.') return false;
|
||||
memcpy(&addr->ip, data, sizeof(data));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,10 @@ struct mg_mgr {
|
||||
};
|
||||
|
||||
struct mg_addr {
|
||||
uint16_t port; // TCP or UDP port in network byte order
|
||||
uint32_t ip; // IP address in network byte order
|
||||
uint16_t port; // TCP or UDP port in network byte order
|
||||
uint32_t ip; // IP address in network byte order
|
||||
uint8_t ip6[16]; // IPv6 address
|
||||
bool is_ip6; // True when address is IPv6 address
|
||||
};
|
||||
|
||||
struct mg_connection {
|
||||
@ -61,3 +63,5 @@ int mg_printf(struct mg_connection *, const char *fmt, ...);
|
||||
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||
char *mg_straddr(struct mg_connection *, char *, size_t);
|
||||
bool mg_socketpair(int *s1, int *s2);
|
||||
bool mg_aton(struct mg_str str, struct mg_addr *addr);
|
||||
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
|
||||
|
@ -157,15 +157,20 @@ SOCKET mg_open_listener(const char *ip, uint16_t port, int is_udp) {
|
||||
int on = 1;
|
||||
int proto = is_udp ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
int type = is_udp ? SOCK_DGRAM : SOCK_STREAM;
|
||||
struct mg_addr addr;
|
||||
SOCKET fd;
|
||||
|
||||
memset(&usa, 0, sizeof(usa));
|
||||
usa.sin.sin_family = AF_INET;
|
||||
usa.sin.sin_port = mg_htons(port);
|
||||
mg_aton(mg_url_host(ip), &addr);
|
||||
*(uint32_t *) &usa.sin.sin_addr = addr.ip;
|
||||
#if 0
|
||||
mg_aton(ip, (uint32_t *) &usa.sin.sin_addr);
|
||||
if (!mg_casecmp(ip, "localhost")) {
|
||||
*(uint32_t *) &usa.sin.sin_addr = mg_htonl(0x7f000001);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fd = socket(AF_INET, type, proto)) != INVALID_SOCKET &&
|
||||
#if !defined(_WIN32) || !defined(SO_EXCLUSIVEADDRUSE)
|
||||
|
17
src/util.c
17
src/util.c
@ -227,23 +227,6 @@ int64_t mg_to64(const char *s) {
|
||||
return result * neg;
|
||||
}
|
||||
|
||||
bool mg_aton(const char *s, uint32_t *ip) {
|
||||
uint8_t data[4] = {0, 0, 0, 0}, ok = 0;
|
||||
if (s != NULL && sscanf(s, "%hhu.%hhu.%hhu.%hhu", &data[0], &data[1],
|
||||
&data[2], &data[3]) == 4) {
|
||||
memcpy(ip, data, sizeof(data));
|
||||
ok = 1;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
char *mg_ntoa(uint32_t ipaddr, char *buf, size_t len) {
|
||||
uint8_t p[4];
|
||||
memcpy(p, &ipaddr, sizeof(p));
|
||||
snprintf(buf, len, "%hhu.%hhu.%hhu.%hhu", p[0], p[1], p[2], p[3]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
double mg_time(void) {
|
||||
#if MG_ARCH == MG_ARCH_WIN32
|
||||
SYSTEMTIME sysnow;
|
||||
|
@ -18,8 +18,6 @@ unsigned long mg_unhexn(const char *s, int len);
|
||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
int64_t mg_to64(const char *s);
|
||||
bool mg_aton(const char *s, uint32_t *ipaddr);
|
||||
char *mg_ntoa(uint32_t ipaddr, char *buf, size_t len);
|
||||
double mg_time(void);
|
||||
unsigned long mg_millis(void);
|
||||
void mg_usleep(unsigned long usecs);
|
||||
|
@ -623,6 +623,17 @@ static void test_http_client(void) {
|
||||
ASSERT(ok == 200);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MG_ENABLE_IPV6
|
||||
ok = 0;
|
||||
c = mg_http_connect(&mgr, "http://ipv6.google.com", f3, &ok);
|
||||
ASSERT(c != NULL);
|
||||
for (i = 0; i < 500 && ok <= 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
// ASSERT(ok == 200);
|
||||
// LOG(LL_DEBUG, (""));
|
||||
// exit(0);
|
||||
#endif
|
||||
|
||||
mg_mgr_free(&mgr);
|
||||
ASSERT(mgr.conns == NULL);
|
||||
}
|
||||
@ -984,10 +995,19 @@ static void test_dns(void) {
|
||||
|
||||
static void test_util(void) {
|
||||
char buf[100], *s = mg_hexdump("abc", 3);
|
||||
struct mg_addr a;
|
||||
ASSERT(s != NULL);
|
||||
free(s);
|
||||
memset(&a, 0, sizeof(a));
|
||||
ASSERT(mg_file_write("data.txt", "%s", "hi") == 2);
|
||||
ASSERT(strcmp(mg_ntoa(0x100007f, buf, sizeof(buf)), "127.0.0.1") == 0);
|
||||
ASSERT(mg_aton(mg_str("0"), &a) == false);
|
||||
ASSERT(mg_aton(mg_str("0.0.0."), &a) == false);
|
||||
ASSERT(mg_aton(mg_str("0.0.0.256"), &a) == false);
|
||||
ASSERT(mg_aton(mg_str("0.0.0.-1"), &a) == false);
|
||||
ASSERT(mg_aton(mg_str("127.0.0.1"), &a) == true);
|
||||
ASSERT(a.is_ip6 == 0);
|
||||
ASSERT(a.ip == 0x100007f);
|
||||
ASSERT(strcmp(mg_ntoa(&a, buf, sizeof(buf)), "127.0.0.1") == 0);
|
||||
ASSERT(strcmp(mg_hex("abc", 3, buf), "616263") == 0);
|
||||
ASSERT(mg_url_decode("a=%", 3, buf, sizeof(buf), 0) < 0);
|
||||
ASSERT(mg_url_decode("&&&a=%", 6, buf, sizeof(buf), 0) < 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user