Fix #1888: add %I *printf specifier for IP address. Remove mg_ntoa, mg_straddr

This commit is contained in:
cpq 2022-12-03 14:08:10 +00:00
parent 89fb3a3d6e
commit b01989f041
12 changed files with 105 additions and 144 deletions

View File

@ -687,27 +687,6 @@ Usage example:
mg_printf(c, "Hello, %s!", "world"); // Add "Hello, world!" to output buffer
```
### mg\_straddr
```c
char *mg_straddr(struct mg_addr *addr, char *buf, size_t len);
```
Write stringified IP address, associated with given connection to `buf` (maximum size `len`)
Parameters:
- `addr` - A address pointer
- `buf` - A pointer to a buffer that will hold stringified address
- `len` - A buffer size
Return value: `buf` value
Usage example:
```c
char buf[100];
LOG(LL_INFO, ("%s", mg_straddr(&c->peer, buf, sizeof(buf))));
```
### mg\_wrapfd()
@ -2610,6 +2589,7 @@ Supported format specifiers:
- `q` - expect `char *`, outputs JSON-escaped string (extension)
- `Q` - expect `char *`, outputs double-quoted JSON-escaped string (extension)
- `H` - expect `int`, `void *`, outputs double-quoted hex string (extension)
- `I` - expect `int` (4 or 6), `void *`, outputs IP address (extension)
- `V` - expect `int`, `void *`, outputs double-quoted base64 string (extension)
- `M` - expect `mg_pfn_t`, calls another print function (extension)
- `g`, `f` - expect `double`
@ -2638,6 +2618,7 @@ mg_snprintf(buf, sizeof(buf), "%05x", 123); // 00123
mg_snprintf(buf, sizeof(buf), "%%-%3s", "a"); // %- a
mg_snprintf(buf, sizeof(buf), "hi, %Q", "a"); // hi, "a"
mg_snprintf(buf, sizeof(buf), "r: %M, %d", f,1,2,7); // r: 3, 7
mg_snprintf(buf, sizeof(buf), "%I", 4, "abcd"); // 97.98.99.100
// Printing sub-function for %M specifier. Grabs two int parameters
size_t f(void (*out)(char, void *), void *ptr, va_list *ap) {
@ -2754,28 +2735,6 @@ if (mg_aton(mg_str("127.0.0.1"), &addr)) {
}
```
### mg\_ntoa()
```c
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
```
Stringify IP address `ipaddr` into a buffer `buf`, `len`
Parameters:
- `addr` - Address to stringify
- `buf` - Pointer to output buffer
- `len` - Output buffer size
Return value: `buf` value
Usage example:
```c
char buf[100];
mg_ntoa(&c->peer, buf, sizeof(buf));
```
## JSON
Note that Mongoose's printing functions support non-standard format specifiers `%Q` and `%M`,

View File

@ -35,14 +35,12 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
mg_http_printf_chunk(c, "ID PROTO TYPE LOCAL REMOTE\n");
for (struct mg_connection *t = c->mgr->conns; t != NULL; t = t->next) {
char loc[40], rem[40];
mg_http_printf_chunk(c, "%-3lu %4s %s %-15s %s\n", t->id,
mg_http_printf_chunk(c, "%-3lu %4s %s %I %I\n", t->id,
t->is_udp ? "UDP" : "TCP",
t->is_listening ? "LISTENING"
: t->is_accepted ? "ACCEPTED "
: "CONNECTED",
mg_straddr(&t->loc, loc, sizeof(loc)),
mg_straddr(&t->rem, rem, sizeof(rem)));
4, &t->loc.ip, 4, &t->rem.ip);
}
mg_http_printf_chunk(c, ""); // Don't forget the last empty chunk
} else if (mg_http_match_uri(hm, "/api/f2/*")) {

View File

@ -42,6 +42,42 @@ static size_t pcap_rx(void *buf, size_t len, void *userdata) {
return received;
}
static void fn2(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
MG_DEBUG(("Got response (%d) %.*s...", (int) hm->message.len, 12,
hm->message.ptr));
c->is_closing = 1;
} else if (ev == MG_EV_CONNECT) {
mg_printf(c, "GET %s HTTP/1.1\r\n\r\n", mg_url_uri((char *) fn_data));
} else if (ev == MG_EV_CLOSE) {
free(fn_data);
}
}
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_http_match_uri(hm, "/api/debug")) {
int level = mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
mg_log_set(level);
mg_http_reply(c, 200, "", "Debug level set to %d\n", level);
} else if (mg_http_match_uri(hm, "/api/url")) {
char *url = mg_json_get_str(hm->body, "$.url");
if (url == NULL) {
mg_http_reply(c, 200, NULL, "no url, rl %d\r\n", (int) c->recv.len);
} else {
mg_http_connect(c->mgr, url, fn2, url);
mg_http_reply(c, 200, NULL, "ok\r\n");
}
} else {
mg_http_reply(c, 200, NULL, "%.*s\r\n", (int) hm->message.len,
hm->message.ptr);
}
}
(void) ev_data, (void) fn_data;
}
int main(int argc, char *argv[]) {
const char *iface = "lo0"; // Network iface
const char *mac = "02:00:01:02:03:77"; // MAC address
@ -94,6 +130,7 @@ int main(int argc, char *argv[]) {
struct mg_mgr mgr; // Event manager
mg_mgr_init(&mgr); // Initialise event manager
mg_log_set(MG_LL_DEBUG); // Set log level
struct mip_driver driver = {.tx = pcap_tx, .up = pcap_up, .rx = pcap_rx};
struct mip_if mif = {.use_dhcp = true, .driver = &driver, .driver_data = ph};
@ -102,8 +139,9 @@ int main(int argc, char *argv[]) {
mip_init(&mgr, &mif);
MG_INFO(("Init done, starting main loop"));
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *);
mg_http_listen(&mgr, "http://0.0.0.0:8000", device_dashboard_fn, &mgr);
// extern void device_dashboard_fn(struct mg_connection *, int, void *, void
// *);
mg_http_listen(&mgr, "http://0.0.0.0:8000", fn, &mgr);
while (s_signo == 0) mg_mgr_poll(&mgr, 100); // Infinite event loop

View File

@ -24,14 +24,12 @@ static void wcb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
mg_http_printf_chunk(c, "ID PROTO TYPE LOCAL REMOTE\n");
for (struct mg_connection *t = c->mgr->conns; t != NULL; t = t->next) {
char loc[40], rem[40];
mg_http_printf_chunk(c, "%-3lu %4s %s %-15s %s\n", t->id,
mg_http_printf_chunk(c, "%-3lu %4s %s %I %I\n", t->id,
t->is_udp ? "UDP" : "TCP",
t->is_listening ? "LISTENING"
: t->is_accepted ? "ACCEPTED "
: "CONNECTED",
mg_straddr(&t->loc, loc, sizeof(loc)),
mg_straddr(&t->rem, rem, sizeof(rem)));
4, &t->loc.ip, 4, &t->rem.ip);
}
mg_http_printf_chunk(c, ""); // Don't forget the last empty chunk
} else {

View File

@ -271,11 +271,11 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
if (dm.txnid != d->txnid) continue;
if (d->c->is_resolving) {
if (dm.resolved) {
char buf[100];
dm.addr.port = d->c->rem.port; // Save port
d->c->rem = dm.addr; // Copy resolved address
MG_DEBUG(("%lu %s is %s", d->c->id, dm.name,
mg_ntoa(&d->c->rem, buf, sizeof(buf))));
MG_DEBUG(
("%lu %s is %I", d->c->id, dm.name, d->c->rem.is_ip6 ? 16 : 4,
d->c->rem.is_ip6 ? &d->c->rem.ip6 : (void *) &d->c->rem.ip));
mg_connect_resolved(d->c);
#if MG_ENABLE_IPV6
} else if (dm.addr.is_ip6 == false && dm.name[0] != '\0' &&
@ -351,7 +351,6 @@ static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
mg_error(c, "resolve OOM");
} else {
struct dns_data *reqs = (struct dns_data *) c->mgr->active_dns_requests;
char buf[100];
d->txnid = reqs ? (uint16_t) (reqs->txnid + 1) : 1;
d->next = (struct dns_data *) c->mgr->active_dns_requests;
c->mgr->active_dns_requests = d;
@ -359,7 +358,7 @@ static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
d->c = c;
c->is_resolving = 1;
MG_VERBOSE(("%lu resolving %.*s @ %s, txnid %hu", c->id, (int) name->len,
name->ptr, mg_ntoa(&dnsc->c->rem, buf, sizeof(buf)), d->txnid));
name->ptr, &dnsc->url, d->txnid));
if (!mg_dns_send(dnsc->c, name, d->txnid, ipv6)) {
mg_error(dnsc->c, "DNS send");
}
@ -412,6 +411,7 @@ void mg_error(struct mg_connection *c, const char *fmt, ...) {
static void mg_pfn_iobuf_private(char ch, void *param, bool expand) {
struct mg_iobuf *io = (struct mg_iobuf *) param;
if (expand && io->len + 2 > io->size) mg_iobuf_resize(io, io->len + 2);
@ -720,6 +720,20 @@ size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt,
n += scpy(out, param, (char *) &hex[p[j] & 15], 1);
}
n += scpy(out, param, (char *) &dquote, 1);
} else if (c == 'I') {
// Print IPv4 or IPv6 address
size_t len = (size_t) va_arg(*ap, int); // Length 16 means IPv6 address
uint8_t *buf = va_arg(*ap, uint8_t *); // Pointer to the IP address
if (len == 6) {
uint16_t *p = (uint16_t *) buf;
n += mg_xprintf(out, param, "%x:%x:%x:%x:%x:%x:%x:%x", mg_htons(p[0]),
mg_htons(p[1]), mg_htons(p[2]), mg_htons(p[3]),
mg_htons(p[4]), mg_htons(p[5]), mg_htons(p[6]),
mg_htons(p[7]));
} else {
n += mg_xprintf(out, param, "%d.%d.%d.%d", (int) buf[0], (int) buf[1],
(int) buf[2], (int) buf[3]);
}
} else if (c == 'V') {
// Print base64-encoded double-quoted string
size_t len = (size_t) va_arg(*ap, int);
@ -3313,29 +3327,6 @@ size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
return len;
}
char *mg_straddr(struct mg_addr *a, char *buf, size_t len) {
char tmp[40];
const char *fmt = a->is_ip6 ? "[%s]:%d" : "%s:%d";
mg_ntoa(a, tmp, sizeof(tmp));
mg_snprintf(buf, len, fmt, tmp, (int) mg_ntohs(a->port));
return buf;
}
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len) {
if (addr->is_ip6) {
uint16_t *p = (uint16_t *) addr->ip6;
mg_snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x", mg_htons(p[0]),
mg_htons(p[1]), mg_htons(p[2]), mg_htons(p[3]), mg_htons(p[4]),
mg_htons(p[5]), mg_htons(p[6]), mg_htons(p[7]));
} else {
uint8_t p[4];
memcpy(p, &addr->ip, sizeof(p));
mg_snprintf(buf, len, "%d.%d.%d.%d", (int) p[0], (int) p[1], (int) p[2],
(int) p[3]);
}
return buf;
}
static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
if (mg_vcasecmp(&str, "localhost") != 0) return false;
addr->ip = mg_htonl(0x7f000001);
@ -4063,16 +4054,10 @@ static void iolog(struct mg_connection *c, char *buf, long n, bool r) {
} else if (n > 0) {
if (c->is_hexdumping) {
union usa usa;
char t1[50], t2[50];
socklen_t slen = sizeof(usa.sin);
struct mg_addr a;
memset(&usa, 0, sizeof(usa));
memset(&a, 0, sizeof(a));
if (getsockname(FD(c), &usa.sa, &slen) < 0) (void) 0; // Ignore result
tomgaddr(&usa, &a, c->rem.is_ip6);
MG_INFO(("\n-- %lu %s %s %s %s %ld", c->id,
mg_straddr(&a, t1, sizeof(t1)), r ? "<-" : "->",
mg_straddr(&c->rem, t2, sizeof(t2)), c->label, n));
MG_INFO(("\n-- %lu %I %s %I %s %ld", c->id, 4, &usa.sin.sin_addr,
r ? "<-" : "->", 4, &c->rem.ip, c->label, n));
mg_hexdump(buf, (size_t) n);
}
@ -4327,7 +4312,7 @@ void mg_connect_resolved(struct mg_connection *c) {
if ((rc = connect(FD(c), &usa.sa, slen)) == 0) {
mg_call(c, MG_EV_CONNECT, NULL);
} else if (mg_sock_would_block()) {
MG_DEBUG(("%lu %p -> %x:%hu pend", c->id, c->fd, mg_ntohl(c->rem.ip),
MG_DEBUG(("%lu %p -> %I:%hu pend", c->id, c->fd, 4, &c->rem.ip,
mg_ntohs(c->rem.port)));
c->is_connecting = 1;
} else {
@ -4370,9 +4355,7 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
MG_ERROR(("%lu OOM", lsn->id));
closesocket(fd);
} else {
// char buf[40];
tomgaddr(&usa, &c->rem, sa_len != sizeof(usa.sin));
// mg_straddr(&c->rem, buf, sizeof(buf));
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
c->fd = S2PTR(fd);
MG_EPOLL_ADD(c);
@ -4385,9 +4368,8 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
c->pfn_data = lsn->pfn_data;
c->fn = lsn->fn;
c->fn_data = lsn->fn_data;
MG_DEBUG(("%lu %p accepted %x.%hu -> %x.%hu", c->id, c->fd,
mg_ntohl(c->rem.ip), mg_ntohs(c->rem.port), mg_ntohl(c->loc.ip),
mg_ntohs(c->loc.port)));
MG_DEBUG(("%lu %p accepted %I.%hu -> %I.%hu", c->id, c->fd, 4, &c->rem.ip,
mg_ntohs(c->rem.port), 4, &c->loc.ip, mg_ntohs(c->loc.port)));
mg_call(c, MG_EV_OPEN, NULL);
mg_call(c, MG_EV_ACCEPT, NULL);
}

View File

@ -1088,9 +1088,7 @@ void mg_connect_resolved(struct mg_connection *);
bool mg_send(struct mg_connection *, const void *, size_t);
size_t mg_printf(struct mg_connection *, const char *fmt, ...);
size_t mg_vprintf(struct mg_connection *, const char *fmt, va_list *ap);
char *mg_straddr(struct mg_addr *, char *, size_t);
bool mg_aton(struct mg_str str, struct mg_addr *addr);
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
int mg_mkpipe(struct mg_mgr *, mg_event_handler_t, void *, bool udp);
// These functions are used to integrate with custom network stacks

View File

@ -159,11 +159,11 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
if (dm.txnid != d->txnid) continue;
if (d->c->is_resolving) {
if (dm.resolved) {
char buf[100];
dm.addr.port = d->c->rem.port; // Save port
d->c->rem = dm.addr; // Copy resolved address
MG_DEBUG(("%lu %s is %s", d->c->id, dm.name,
mg_ntoa(&d->c->rem, buf, sizeof(buf))));
MG_DEBUG(
("%lu %s is %I", d->c->id, dm.name, d->c->rem.is_ip6 ? 16 : 4,
d->c->rem.is_ip6 ? &d->c->rem.ip6 : (void *) &d->c->rem.ip));
mg_connect_resolved(d->c);
#if MG_ENABLE_IPV6
} else if (dm.addr.is_ip6 == false && dm.name[0] != '\0' &&
@ -239,7 +239,6 @@ static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
mg_error(c, "resolve OOM");
} else {
struct dns_data *reqs = (struct dns_data *) c->mgr->active_dns_requests;
char buf[100];
d->txnid = reqs ? (uint16_t) (reqs->txnid + 1) : 1;
d->next = (struct dns_data *) c->mgr->active_dns_requests;
c->mgr->active_dns_requests = d;
@ -247,7 +246,7 @@ static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
d->c = c;
c->is_resolving = 1;
MG_VERBOSE(("%lu resolving %.*s @ %s, txnid %hu", c->id, (int) name->len,
name->ptr, mg_ntoa(&dnsc->c->rem, buf, sizeof(buf)), d->txnid));
name->ptr, &dnsc->url, d->txnid));
if (!mg_dns_send(dnsc->c, name, d->txnid, ipv6)) {
mg_error(dnsc->c, "DNS send");
}

View File

@ -1,5 +1,6 @@
#include "fmt.h"
#include "iobuf.h"
#include "util.h"
static void mg_pfn_iobuf_private(char ch, void *param, bool expand) {
struct mg_iobuf *io = (struct mg_iobuf *) param;
@ -309,6 +310,20 @@ size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt,
n += scpy(out, param, (char *) &hex[p[j] & 15], 1);
}
n += scpy(out, param, (char *) &dquote, 1);
} else if (c == 'I') {
// Print IPv4 or IPv6 address
size_t len = (size_t) va_arg(*ap, int); // Length 16 means IPv6 address
uint8_t *buf = va_arg(*ap, uint8_t *); // Pointer to the IP address
if (len == 6) {
uint16_t *p = (uint16_t *) buf;
n += mg_xprintf(out, param, "%x:%x:%x:%x:%x:%x:%x:%x", mg_htons(p[0]),
mg_htons(p[1]), mg_htons(p[2]), mg_htons(p[3]),
mg_htons(p[4]), mg_htons(p[5]), mg_htons(p[6]),
mg_htons(p[7]));
} else {
n += mg_xprintf(out, param, "%d.%d.%d.%d", (int) buf[0], (int) buf[1],
(int) buf[2], (int) buf[3]);
}
} else if (c == 'V') {
// Print base64-encoded double-quoted string
size_t len = (size_t) va_arg(*ap, int);

View File

@ -20,29 +20,6 @@ size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
return len;
}
char *mg_straddr(struct mg_addr *a, char *buf, size_t len) {
char tmp[40];
const char *fmt = a->is_ip6 ? "[%s]:%d" : "%s:%d";
mg_ntoa(a, tmp, sizeof(tmp));
mg_snprintf(buf, len, fmt, tmp, (int) mg_ntohs(a->port));
return buf;
}
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len) {
if (addr->is_ip6) {
uint16_t *p = (uint16_t *) addr->ip6;
mg_snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x", mg_htons(p[0]),
mg_htons(p[1]), mg_htons(p[2]), mg_htons(p[3]), mg_htons(p[4]),
mg_htons(p[5]), mg_htons(p[6]), mg_htons(p[7]));
} else {
uint8_t p[4];
memcpy(p, &addr->ip, sizeof(p));
mg_snprintf(buf, len, "%d.%d.%d.%d", (int) p[0], (int) p[1], (int) p[2],
(int) p[3]);
}
return buf;
}
static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
if (mg_vcasecmp(&str, "localhost") != 0) return false;
addr->ip = mg_htonl(0x7f000001);

View File

@ -87,9 +87,7 @@ void mg_connect_resolved(struct mg_connection *);
bool mg_send(struct mg_connection *, const void *, size_t);
size_t mg_printf(struct mg_connection *, const char *fmt, ...);
size_t mg_vprintf(struct mg_connection *, const char *fmt, va_list *ap);
char *mg_straddr(struct mg_addr *, char *, size_t);
bool mg_aton(struct mg_str str, struct mg_addr *addr);
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
int mg_mkpipe(struct mg_mgr *, mg_event_handler_t, void *, bool udp);
// These functions are used to integrate with custom network stacks

View File

@ -99,16 +99,10 @@ static void iolog(struct mg_connection *c, char *buf, long n, bool r) {
} else if (n > 0) {
if (c->is_hexdumping) {
union usa usa;
char t1[50], t2[50];
socklen_t slen = sizeof(usa.sin);
struct mg_addr a;
memset(&usa, 0, sizeof(usa));
memset(&a, 0, sizeof(a));
if (getsockname(FD(c), &usa.sa, &slen) < 0) (void) 0; // Ignore result
tomgaddr(&usa, &a, c->rem.is_ip6);
MG_INFO(("\n-- %lu %s %s %s %s %ld", c->id,
mg_straddr(&a, t1, sizeof(t1)), r ? "<-" : "->",
mg_straddr(&c->rem, t2, sizeof(t2)), c->label, n));
MG_INFO(("\n-- %lu %I %s %I %s %ld", c->id, 4, &usa.sin.sin_addr,
r ? "<-" : "->", 4, &c->rem.ip, c->label, n));
mg_hexdump(buf, (size_t) n);
}
@ -363,7 +357,7 @@ void mg_connect_resolved(struct mg_connection *c) {
if ((rc = connect(FD(c), &usa.sa, slen)) == 0) {
mg_call(c, MG_EV_CONNECT, NULL);
} else if (mg_sock_would_block()) {
MG_DEBUG(("%lu %p -> %x:%hu pend", c->id, c->fd, mg_ntohl(c->rem.ip),
MG_DEBUG(("%lu %p -> %I:%hu pend", c->id, c->fd, 4, &c->rem.ip,
mg_ntohs(c->rem.port)));
c->is_connecting = 1;
} else {
@ -406,9 +400,7 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
MG_ERROR(("%lu OOM", lsn->id));
closesocket(fd);
} else {
// char buf[40];
tomgaddr(&usa, &c->rem, sa_len != sizeof(usa.sin));
// mg_straddr(&c->rem, buf, sizeof(buf));
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
c->fd = S2PTR(fd);
MG_EPOLL_ADD(c);
@ -421,9 +413,8 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
c->pfn_data = lsn->pfn_data;
c->fn = lsn->fn;
c->fn_data = lsn->fn_data;
MG_DEBUG(("%lu %p accepted %x.%hu -> %x.%hu", c->id, c->fd,
mg_ntohl(c->rem.ip), mg_ntohs(c->rem.port), mg_ntohl(c->loc.ip),
mg_ntohs(c->loc.port)));
MG_DEBUG(("%lu %p accepted %I.%hu -> %I.%hu", c->id, c->fd, 4, &c->rem.ip,
mg_ntohs(c->rem.port), 4, &c->loc.ip, mg_ntohs(c->loc.port)));
mg_call(c, MG_EV_OPEN, NULL);
mg_call(c, MG_EV_ACCEPT, NULL);
}

View File

@ -1637,6 +1637,15 @@ static void test_str(void) {
ASSERT(strcmp(tmp, "01") == 0);
ASSERT(tmp[2] == '\0');
}
{
char buf[100];
struct mg_addr a = {0, mg_htonl(0x10111213), {1, 100, 33}, false};
ASSERT(mg_snprintf(buf, sizeof(buf), "%I", 4, &a.ip) == 11);
ASSERT(strcmp(buf, "16.17.18.19") == 0);
ASSERT(mg_snprintf(buf, sizeof(buf), "%I", 6, &a.ip6) == 20);
ASSERT(strcmp(buf, "164:2100:0:0:0:0:0:0") == 0);
}
}
static void fn1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
@ -1729,7 +1738,6 @@ static void test_util(void) {
ASSERT(mg_aton(mg_str("127.0.0.1"), &a) == true);
ASSERT(a.is_ip6 == false);
ASSERT(a.ip == mg_htonl(0x7f000001));
ASSERT(strcmp(mg_ntoa(&a, buf, sizeof(buf)), "127.0.0.1") == 0);
ASSERT(mg_aton(mg_str("1:2:3:4:5:6:7:8"), &a) == true);
ASSERT(a.is_ip6 == true);