mirror of
https://github.com/cesanta/mongoose.git
synced 2024-11-27 20:59:00 +08:00
optimized mg_addr structure
This commit is contained in:
parent
dcfa7ad657
commit
dd32deb2ad
81
mongoose.c
81
mongoose.c
@ -238,7 +238,7 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
|||||||
break; // Return success
|
break; // Return success
|
||||||
} else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) {
|
} else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) {
|
||||||
dm->addr.is_ip6 = true;
|
dm->addr.is_ip6 = true;
|
||||||
memcpy(&dm->addr.ip6, &buf[ofs - 16], 16);
|
memcpy(&dm->addr.ip, &buf[ofs - 16], 16);
|
||||||
dm->resolved = true;
|
dm->resolved = true;
|
||||||
break; // Return success
|
break; // Return success
|
||||||
}
|
}
|
||||||
@ -3484,15 +3484,16 @@ size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
|
static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
|
||||||
|
uint32_t localhost = mg_htonl(0x7f000001);
|
||||||
if (mg_vcasecmp(&str, "localhost") != 0) return false;
|
if (mg_vcasecmp(&str, "localhost") != 0) return false;
|
||||||
addr->ip = mg_htonl(0x7f000001);
|
memcpy(addr->ip, &localhost, sizeof(uint32_t));
|
||||||
addr->is_ip6 = false;
|
addr->is_ip6 = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
|
static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
|
||||||
if (str.len > 0) return false;
|
if (str.len > 0) return false;
|
||||||
addr->ip = 0;
|
memset(addr->ip, 0, sizeof(addr->ip));
|
||||||
addr->is_ip6 = false;
|
addr->is_ip6 = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3520,15 +3521,18 @@ static bool mg_aton4(struct mg_str str, struct mg_addr *addr) {
|
|||||||
|
|
||||||
static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) {
|
static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) {
|
||||||
int i;
|
int i;
|
||||||
|
uint32_t ipv4;
|
||||||
if (str.len < 14) return false;
|
if (str.len < 14) return false;
|
||||||
if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false;
|
if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false;
|
||||||
for (i = 2; i < 6; i++) {
|
for (i = 2; i < 6; i++) {
|
||||||
if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false;
|
if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false;
|
||||||
}
|
}
|
||||||
|
//struct mg_str s = mg_str_n(&str.ptr[7], str.len - 7);
|
||||||
if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false;
|
if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false;
|
||||||
memset(addr->ip6, 0, sizeof(addr->ip6));
|
memcpy(&ipv4, addr->ip, sizeof(ipv4));
|
||||||
addr->ip6[10] = addr->ip6[11] = 255;
|
memset(addr->ip, 0, sizeof(addr->ip));
|
||||||
memcpy(&addr->ip6[12], &addr->ip, 4);
|
addr->ip[10] = addr->ip[11] = 255;
|
||||||
|
memcpy(&addr->ip[12], &ipv4, 4);
|
||||||
addr->is_ip6 = true;
|
addr->is_ip6 = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3545,8 +3549,8 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) {
|
|||||||
if (i > j + 3) return false;
|
if (i > j + 3) return false;
|
||||||
// MG_DEBUG(("%zu %zu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j]));
|
// MG_DEBUG(("%zu %zu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j]));
|
||||||
val = mg_unhexn(&str.ptr[j], i - j + 1);
|
val = mg_unhexn(&str.ptr[j], i - j + 1);
|
||||||
addr->ip6[n] = (uint8_t) ((val >> 8) & 255);
|
addr->ip[n] = (uint8_t) ((val >> 8) & 255);
|
||||||
addr->ip6[n + 1] = (uint8_t) (val & 255);
|
addr->ip[n + 1] = (uint8_t) (val & 255);
|
||||||
} else if (str.ptr[i] == ':') {
|
} else if (str.ptr[i] == ':') {
|
||||||
j = i + 1;
|
j = i + 1;
|
||||||
if (i > 0 && str.ptr[i - 1] == ':') {
|
if (i > 0 && str.ptr[i - 1] == ':') {
|
||||||
@ -3556,16 +3560,17 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) {
|
|||||||
n += 2;
|
n += 2;
|
||||||
}
|
}
|
||||||
if (n > 14) return false;
|
if (n > 14) return false;
|
||||||
addr->ip6[n] = addr->ip6[n + 1] = 0; // For trailing ::
|
addr->ip[n] = addr->ip[n + 1] = 0; // For trailing ::
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n < 14 && dc == 42) return false;
|
if (n < 14 && dc == 42) return false;
|
||||||
if (n < 14) {
|
if (n < 14) {
|
||||||
memmove(&addr->ip6[dc + (14 - n)], &addr->ip6[dc], n - dc + 2);
|
memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2);
|
||||||
memset(&addr->ip6[dc], 0, 14 - n);
|
memset(&addr->ip[dc], 0, 14 - n);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr->is_ip6 = true;
|
addr->is_ip6 = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3815,7 +3820,7 @@ size_t mg_print_ip6(void (*out)(char, void *), void *arg, va_list *ap) {
|
|||||||
|
|
||||||
size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap) {
|
size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap) {
|
||||||
struct mg_addr *addr = va_arg(*ap, struct mg_addr *);
|
struct mg_addr *addr = va_arg(*ap, struct mg_addr *);
|
||||||
if (addr->is_ip6) return print_ip6(out, arg, (uint16_t *) addr->ip6);
|
if (addr->is_ip6) return print_ip6(out, arg, (uint16_t *) addr->ip);
|
||||||
return print_ip4(out, arg, (uint8_t *) &addr->ip);
|
return print_ip4(out, arg, (uint8_t *) &addr->ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4446,12 +4451,12 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) {
|
|||||||
memset(usa, 0, sizeof(*usa));
|
memset(usa, 0, sizeof(*usa));
|
||||||
usa->sin.sin_family = AF_INET;
|
usa->sin.sin_family = AF_INET;
|
||||||
usa->sin.sin_port = a->port;
|
usa->sin.sin_port = a->port;
|
||||||
*(uint32_t *) &usa->sin.sin_addr = a->ip;
|
memcpy(&usa->sin.sin_addr, a->ip, sizeof(uint32_t));
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (a->is_ip6) {
|
if (a->is_ip6) {
|
||||||
usa->sin.sin_family = AF_INET6;
|
usa->sin.sin_family = AF_INET6;
|
||||||
usa->sin6.sin6_port = a->port;
|
usa->sin6.sin6_port = a->port;
|
||||||
memcpy(&usa->sin6.sin6_addr, a->ip6, sizeof(a->ip6));
|
memcpy(&usa->sin6.sin6_addr, a->ip, sizeof(a->ip));
|
||||||
len = sizeof(usa->sin6);
|
len = sizeof(usa->sin6);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -4461,10 +4466,10 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) {
|
|||||||
static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) {
|
static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) {
|
||||||
a->is_ip6 = is_ip6;
|
a->is_ip6 = is_ip6;
|
||||||
a->port = usa->sin.sin_port;
|
a->port = usa->sin.sin_port;
|
||||||
memcpy(&a->ip, &usa->sin.sin_addr, sizeof(a->ip));
|
memcpy(&a->ip, &usa->sin.sin_addr, sizeof(uint32_t));
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (is_ip6) {
|
if (is_ip6) {
|
||||||
memcpy(a->ip6, &usa->sin6.sin6_addr, sizeof(a->ip6));
|
memcpy(a->ip, &usa->sin6.sin6_addr, sizeof(a->ip));
|
||||||
a->port = usa->sin6.sin6_port;
|
a->port = usa->sin6.sin6_port;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -7776,7 +7781,7 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
|||||||
if (c != NULL && c->is_arplooking) {
|
if (c != NULL && c->is_arplooking) {
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
memcpy(s->mac, pkt->arp->sha, sizeof(s->mac));
|
memcpy(s->mac, pkt->arp->sha, sizeof(s->mac));
|
||||||
MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, &c->rem.ip,
|
MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, c->rem.ip,
|
||||||
mg_print_mac, s->mac));
|
mg_print_mac, s->mac));
|
||||||
c->is_arplooking = 0;
|
c->is_arplooking = 0;
|
||||||
}
|
}
|
||||||
@ -7875,7 +7880,7 @@ static void rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
|||||||
// No UDP listener on this port. Should send ICMP, but keep silent.
|
// No UDP listener on this port. Should send ICMP, but keep silent.
|
||||||
} else {
|
} else {
|
||||||
c->rem.port = pkt->udp->sport;
|
c->rem.port = pkt->udp->sport;
|
||||||
c->rem.ip = pkt->ip->src;
|
memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t));
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
||||||
if (c->recv.len >= MG_MAX_RECV_SIZE) {
|
if (c->recv.len >= MG_MAX_RECV_SIZE) {
|
||||||
@ -7949,7 +7954,7 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn,
|
|||||||
s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq);
|
s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq);
|
||||||
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
||||||
settmout(c, MIP_TTYPE_KEEPALIVE);
|
settmout(c, MIP_TTYPE_KEEPALIVE);
|
||||||
c->rem.ip = pkt->ip->src;
|
memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t));
|
||||||
c->rem.port = pkt->tcp->sport;
|
c->rem.port = pkt->tcp->sport;
|
||||||
MG_DEBUG(("%lu accepted %M", c->id, mg_print_ip_port, &c->rem));
|
MG_DEBUG(("%lu accepted %M", c->id, mg_print_ip_port, &c->rem));
|
||||||
LIST_ADD_HEAD(struct mg_connection, &lsn->mgr->conns, c);
|
LIST_ADD_HEAD(struct mg_connection, &lsn->mgr->conns, c);
|
||||||
@ -7968,17 +7973,19 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn,
|
|||||||
long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
|
long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
if (c->is_udp) {
|
if (c->is_udp) {
|
||||||
size_t max_headers_len = 14 + 24 /* max IP */ + 8 /* UDP */;
|
size_t max_headers_len = 14 + 24 /* max IP */ + 8 /* UDP */;
|
||||||
if (len + max_headers_len > ifp->tx.len) {
|
if (len + max_headers_len > ifp->tx.len) {
|
||||||
len = ifp->tx.len - max_headers_len;
|
len = ifp->tx.len - max_headers_len;
|
||||||
}
|
}
|
||||||
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, c->rem.ip, c->rem.port, buf, len);
|
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf, len);
|
||||||
} else {
|
} else {
|
||||||
size_t max_headers_len = 14 + 24 /* max IP */ + 60 /* max TCP */;
|
size_t max_headers_len = 14 + 24 /* max IP */ + 60 /* max TCP */;
|
||||||
if (len + max_headers_len > ifp->tx.len)
|
if (len + max_headers_len > ifp->tx.len)
|
||||||
len = ifp->tx.len - max_headers_len;
|
len = ifp->tx.len - max_headers_len;
|
||||||
if (tx_tcp(ifp, s->mac, c->rem.ip, TH_PUSH | TH_ACK, c->loc.port,
|
if (tx_tcp(ifp, s->mac, rem_ip, TH_PUSH | TH_ACK, c->loc.port,
|
||||||
c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), buf, len) > 0) {
|
c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), buf, len) > 0) {
|
||||||
s->seq += (uint32_t) len;
|
s->seq += (uint32_t) len;
|
||||||
if (s->ttype == MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_KEEPALIVE);
|
if (s->ttype == MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_KEEPALIVE);
|
||||||
@ -8261,17 +8268,19 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) {
|
|||||||
if (c->is_udp || c->is_listening) continue;
|
if (c->is_udp || c->is_listening) continue;
|
||||||
if (c->is_connecting || c->is_resolving) continue;
|
if (c->is_connecting || c->is_resolving) continue;
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
if (uptime_ms > s->timer) {
|
if (uptime_ms > s->timer) {
|
||||||
if (s->ttype == MIP_TTYPE_ACK) {
|
if (s->ttype == MIP_TTYPE_ACK) {
|
||||||
MG_DEBUG(("%lu ack %x %x", c->id, s->seq, s->ack));
|
MG_DEBUG(("%lu ack %x %x", c->id, s->seq, s->ack));
|
||||||
tx_tcp(ifp, s->mac, c->rem.ip, TH_ACK, c->loc.port, c->rem.port,
|
tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
|
||||||
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
||||||
} else {
|
} else {
|
||||||
if (s->tmiss++ > 2) {
|
if (s->tmiss++ > 2) {
|
||||||
mg_error(c, "keepalive");
|
mg_error(c, "keepalive");
|
||||||
} else {
|
} else {
|
||||||
MG_DEBUG(("%lu keepalive", c->id));
|
MG_DEBUG(("%lu keepalive", c->id));
|
||||||
tx_tcp(ifp, s->mac, c->rem.ip, TH_ACK, c->loc.port, c->rem.port,
|
tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
|
||||||
mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0);
|
mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8339,32 +8348,36 @@ static void send_syn(struct mg_connection *c) {
|
|||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
|
uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
|
||||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||||
tx_tcp(ifp, s->mac, c->rem.ip, TH_SYN, c->loc.port, c->rem.port, isn, 0, NULL,
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
|
tx_tcp(ifp, s->mac, rem_ip, TH_SYN, c->loc.port, c->rem.port, isn, 0, NULL,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_connect_resolved(struct mg_connection *c) {
|
void mg_connect_resolved(struct mg_connection *c) {
|
||||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||||
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
c->is_resolving = 0;
|
c->is_resolving = 0;
|
||||||
if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
|
if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
|
||||||
c->loc.ip = ifp->ip;
|
memcpy(c->loc.ip, &ifp->ip, sizeof(uint32_t));
|
||||||
c->loc.port = mg_htons(ifp->eport++);
|
c->loc.port = mg_htons(ifp->eport++);
|
||||||
MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
|
MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
|
||||||
&c->rem));
|
&c->rem));
|
||||||
mg_call(c, MG_EV_RESOLVE, NULL);
|
mg_call(c, MG_EV_RESOLVE, NULL);
|
||||||
if (((c->rem.ip & ifp->mask) == (ifp->ip & ifp->mask))) {
|
if (((rem_ip & ifp->mask) == (ifp->ip & ifp->mask))) {
|
||||||
// If we're in the same LAN, fire an ARP lookup. TODO(cpq): handle this!
|
// If we're in the same LAN, fire an ARP lookup. TODO(cpq): handle this!
|
||||||
MG_DEBUG(("%lu ARP lookup...", c->id));
|
MG_DEBUG(("%lu ARP lookup...", c->id));
|
||||||
arp_ask(ifp, c->rem.ip);
|
arp_ask(ifp, rem_ip);
|
||||||
c->is_arplooking = 1;
|
c->is_arplooking = 1;
|
||||||
} else if (c->rem.ip == (ifp->ip | ~ifp->mask)) {
|
} else if (rem_ip == (ifp->ip | ~ifp->mask)) {
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
memset(s->mac, 0xFF, sizeof(s->mac)); // local broadcast
|
memset(s->mac, 0xFF, sizeof(s->mac)); // local broadcast
|
||||||
} else if ((*((uint8_t *) &c->rem.ip) & 0xE0) == 0xE0) {
|
} else if ((*((uint8_t *) &rem_ip) & 0xE0) == 0xE0) {
|
||||||
struct connstate *s = (struct connstate *) (c + 1); // 224 to 239, E0 to EF
|
struct connstate *s = (struct connstate *) (c + 1); // 224 to 239, E0 to EF
|
||||||
uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group
|
uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group
|
||||||
memcpy(s->mac, mcastp, 3);
|
memcpy(s->mac, mcastp, 3);
|
||||||
memcpy(s->mac + 3, ((uint8_t *) &c->rem.ip) + 1, 3); // 23 LSb
|
memcpy(s->mac + 3, ((uint8_t *) &rem_ip) + 1, 3); // 23 LSb
|
||||||
s->mac[3] &= 0x7F;
|
s->mac[3] &= 0x7F;
|
||||||
} else {
|
} else {
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
@ -8394,11 +8407,13 @@ static void write_conn(struct mg_connection *c) {
|
|||||||
|
|
||||||
static void close_conn(struct mg_connection *c) {
|
static void close_conn(struct mg_connection *c) {
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
mg_iobuf_free(&s->raw); // For TLS connections, release raw data
|
mg_iobuf_free(&s->raw); // For TLS connections, release raw data
|
||||||
if (c->is_udp == false && c->is_listening == false) { // For TCP conns,
|
if (c->is_udp == false && c->is_listening == false) { // For TCP conns,
|
||||||
struct mg_tcpip_if *ifp =
|
struct mg_tcpip_if *ifp =
|
||||||
(struct mg_tcpip_if *) c->mgr->priv; // send TCP FIN
|
(struct mg_tcpip_if *) c->mgr->priv; // send TCP FIN
|
||||||
tx_tcp(ifp, s->mac, c->rem.ip, TH_FIN | TH_ACK, c->loc.port, c->rem.port,
|
tx_tcp(ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port, c->rem.port,
|
||||||
mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
|
mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
|
||||||
}
|
}
|
||||||
mg_close_conn(c);
|
mg_close_conn(c);
|
||||||
@ -8431,11 +8446,13 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
|
|||||||
bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||||
bool res = false;
|
bool res = false;
|
||||||
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
if (ifp->ip == 0 || ifp->state != MG_TCPIP_STATE_READY) {
|
if (ifp->ip == 0 || ifp->state != MG_TCPIP_STATE_READY) {
|
||||||
mg_error(c, "net down");
|
mg_error(c, "net down");
|
||||||
} else if (c->is_udp) {
|
} else if (c->is_udp) {
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, c->rem.ip, c->rem.port, buf, len);
|
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf, len);
|
||||||
res = true;
|
res = true;
|
||||||
} else {
|
} else {
|
||||||
res = mg_iobuf_add(&c->send, c->send.len, buf, len);
|
res = mg_iobuf_add(&c->send, c->send.len, buf, len);
|
||||||
|
@ -1137,10 +1137,9 @@ struct mg_dns {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct mg_addr {
|
struct mg_addr {
|
||||||
uint16_t port; // TCP or UDP port in network byte order
|
uint8_t ip[16]; // Holds IPv4 or IPv6 address, in network byte order
|
||||||
uint32_t ip; // IP address in network byte order
|
uint16_t port; // TCP or UDP port in network byte order
|
||||||
uint8_t ip6[16]; // IPv6 address
|
bool is_ip6; // True when address is IPv6 address
|
||||||
bool is_ip6; // True when address is IPv6 address
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_mgr {
|
struct mg_mgr {
|
||||||
@ -1152,6 +1151,7 @@ struct mg_mgr {
|
|||||||
unsigned long nextid; // Next connection ID
|
unsigned long nextid; // Next connection ID
|
||||||
unsigned long timerid; // Next timer ID
|
unsigned long timerid; // Next timer ID
|
||||||
void *userdata; // Arbitrary user data pointer
|
void *userdata; // Arbitrary user data pointer
|
||||||
|
void *tls_ctx; // TLS context shared by all TLS sessions
|
||||||
uint16_t mqtt_id; // MQTT IDs for pub/sub
|
uint16_t mqtt_id; // MQTT IDs for pub/sub
|
||||||
void *active_dns_requests; // DNS requests in progress
|
void *active_dns_requests; // DNS requests in progress
|
||||||
struct mg_timer *timers; // Active timers
|
struct mg_timer *timers; // Active timers
|
||||||
|
@ -126,7 +126,7 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
|||||||
break; // Return success
|
break; // Return success
|
||||||
} else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) {
|
} else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) {
|
||||||
dm->addr.is_ip6 = true;
|
dm->addr.is_ip6 = true;
|
||||||
memcpy(&dm->addr.ip6, &buf[ofs - 16], 16);
|
memcpy(&dm->addr.ip, &buf[ofs - 16], 16);
|
||||||
dm->resolved = true;
|
dm->resolved = true;
|
||||||
break; // Return success
|
break; // Return success
|
||||||
}
|
}
|
||||||
|
25
src/net.c
25
src/net.c
@ -22,15 +22,16 @@ size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
|
static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
|
||||||
|
uint32_t localhost = mg_htonl(0x7f000001);
|
||||||
if (mg_vcasecmp(&str, "localhost") != 0) return false;
|
if (mg_vcasecmp(&str, "localhost") != 0) return false;
|
||||||
addr->ip = mg_htonl(0x7f000001);
|
memcpy(addr->ip, &localhost, sizeof(uint32_t));
|
||||||
addr->is_ip6 = false;
|
addr->is_ip6 = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
|
static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
|
||||||
if (str.len > 0) return false;
|
if (str.len > 0) return false;
|
||||||
addr->ip = 0;
|
memset(addr->ip, 0, sizeof(addr->ip));
|
||||||
addr->is_ip6 = false;
|
addr->is_ip6 = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -58,15 +59,18 @@ static bool mg_aton4(struct mg_str str, struct mg_addr *addr) {
|
|||||||
|
|
||||||
static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) {
|
static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) {
|
||||||
int i;
|
int i;
|
||||||
|
uint32_t ipv4;
|
||||||
if (str.len < 14) return false;
|
if (str.len < 14) return false;
|
||||||
if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false;
|
if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false;
|
||||||
for (i = 2; i < 6; i++) {
|
for (i = 2; i < 6; i++) {
|
||||||
if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false;
|
if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false;
|
||||||
}
|
}
|
||||||
|
//struct mg_str s = mg_str_n(&str.ptr[7], str.len - 7);
|
||||||
if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false;
|
if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false;
|
||||||
memset(addr->ip6, 0, sizeof(addr->ip6));
|
memcpy(&ipv4, addr->ip, sizeof(ipv4));
|
||||||
addr->ip6[10] = addr->ip6[11] = 255;
|
memset(addr->ip, 0, sizeof(addr->ip));
|
||||||
memcpy(&addr->ip6[12], &addr->ip, 4);
|
addr->ip[10] = addr->ip[11] = 255;
|
||||||
|
memcpy(&addr->ip[12], &ipv4, 4);
|
||||||
addr->is_ip6 = true;
|
addr->is_ip6 = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -83,8 +87,8 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) {
|
|||||||
if (i > j + 3) return false;
|
if (i > j + 3) return false;
|
||||||
// MG_DEBUG(("%zu %zu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j]));
|
// MG_DEBUG(("%zu %zu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j]));
|
||||||
val = mg_unhexn(&str.ptr[j], i - j + 1);
|
val = mg_unhexn(&str.ptr[j], i - j + 1);
|
||||||
addr->ip6[n] = (uint8_t) ((val >> 8) & 255);
|
addr->ip[n] = (uint8_t) ((val >> 8) & 255);
|
||||||
addr->ip6[n + 1] = (uint8_t) (val & 255);
|
addr->ip[n + 1] = (uint8_t) (val & 255);
|
||||||
} else if (str.ptr[i] == ':') {
|
} else if (str.ptr[i] == ':') {
|
||||||
j = i + 1;
|
j = i + 1;
|
||||||
if (i > 0 && str.ptr[i - 1] == ':') {
|
if (i > 0 && str.ptr[i - 1] == ':') {
|
||||||
@ -94,16 +98,17 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) {
|
|||||||
n += 2;
|
n += 2;
|
||||||
}
|
}
|
||||||
if (n > 14) return false;
|
if (n > 14) return false;
|
||||||
addr->ip6[n] = addr->ip6[n + 1] = 0; // For trailing ::
|
addr->ip[n] = addr->ip[n + 1] = 0; // For trailing ::
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n < 14 && dc == 42) return false;
|
if (n < 14 && dc == 42) return false;
|
||||||
if (n < 14) {
|
if (n < 14) {
|
||||||
memmove(&addr->ip6[dc + (14 - n)], &addr->ip6[dc], n - dc + 2);
|
memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2);
|
||||||
memset(&addr->ip6[dc], 0, 14 - n);
|
memset(&addr->ip[dc], 0, 14 - n);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr->is_ip6 = true;
|
addr->is_ip6 = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,9 @@ struct mg_dns {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct mg_addr {
|
struct mg_addr {
|
||||||
uint16_t port; // TCP or UDP port in network byte order
|
uint8_t ip[16]; // Holds IPv4 or IPv6 address, in network byte order
|
||||||
uint32_t ip; // IP address in network byte order
|
uint16_t port; // TCP or UDP port in network byte order
|
||||||
uint8_t ip6[16]; // IPv6 address
|
bool is_ip6; // True when address is IPv6 address
|
||||||
bool is_ip6; // True when address is IPv6 address
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_mgr {
|
struct mg_mgr {
|
||||||
|
@ -101,7 +101,7 @@ size_t mg_print_ip6(void (*out)(char, void *), void *arg, va_list *ap) {
|
|||||||
|
|
||||||
size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap) {
|
size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap) {
|
||||||
struct mg_addr *addr = va_arg(*ap, struct mg_addr *);
|
struct mg_addr *addr = va_arg(*ap, struct mg_addr *);
|
||||||
if (addr->is_ip6) return print_ip6(out, arg, (uint16_t *) addr->ip6);
|
if (addr->is_ip6) return print_ip6(out, arg, (uint16_t *) addr->ip);
|
||||||
return print_ip4(out, arg, (uint8_t *) &addr->ip);
|
return print_ip4(out, arg, (uint8_t *) &addr->ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,12 +57,12 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) {
|
|||||||
memset(usa, 0, sizeof(*usa));
|
memset(usa, 0, sizeof(*usa));
|
||||||
usa->sin.sin_family = AF_INET;
|
usa->sin.sin_family = AF_INET;
|
||||||
usa->sin.sin_port = a->port;
|
usa->sin.sin_port = a->port;
|
||||||
*(uint32_t *) &usa->sin.sin_addr = a->ip;
|
memcpy(&usa->sin.sin_addr, a->ip, sizeof(uint32_t));
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (a->is_ip6) {
|
if (a->is_ip6) {
|
||||||
usa->sin.sin_family = AF_INET6;
|
usa->sin.sin_family = AF_INET6;
|
||||||
usa->sin6.sin6_port = a->port;
|
usa->sin6.sin6_port = a->port;
|
||||||
memcpy(&usa->sin6.sin6_addr, a->ip6, sizeof(a->ip6));
|
memcpy(&usa->sin6.sin6_addr, a->ip, sizeof(a->ip));
|
||||||
len = sizeof(usa->sin6);
|
len = sizeof(usa->sin6);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -72,10 +72,10 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) {
|
|||||||
static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) {
|
static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) {
|
||||||
a->is_ip6 = is_ip6;
|
a->is_ip6 = is_ip6;
|
||||||
a->port = usa->sin.sin_port;
|
a->port = usa->sin.sin_port;
|
||||||
memcpy(&a->ip, &usa->sin.sin_addr, sizeof(a->ip));
|
memcpy(&a->ip, &usa->sin.sin_addr, sizeof(uint32_t));
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (is_ip6) {
|
if (is_ip6) {
|
||||||
memcpy(a->ip6, &usa->sin6.sin6_addr, sizeof(a->ip6));
|
memcpy(a->ip, &usa->sin6.sin6_addr, sizeof(a->ip));
|
||||||
a->port = usa->sin6.sin6_port;
|
a->port = usa->sin6.sin6_port;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -308,7 +308,7 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
|||||||
if (c != NULL && c->is_arplooking) {
|
if (c != NULL && c->is_arplooking) {
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
memcpy(s->mac, pkt->arp->sha, sizeof(s->mac));
|
memcpy(s->mac, pkt->arp->sha, sizeof(s->mac));
|
||||||
MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, &c->rem.ip,
|
MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, c->rem.ip,
|
||||||
mg_print_mac, s->mac));
|
mg_print_mac, s->mac));
|
||||||
c->is_arplooking = 0;
|
c->is_arplooking = 0;
|
||||||
}
|
}
|
||||||
@ -407,7 +407,7 @@ static void rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
|||||||
// No UDP listener on this port. Should send ICMP, but keep silent.
|
// No UDP listener on this port. Should send ICMP, but keep silent.
|
||||||
} else {
|
} else {
|
||||||
c->rem.port = pkt->udp->sport;
|
c->rem.port = pkt->udp->sport;
|
||||||
c->rem.ip = pkt->ip->src;
|
memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t));
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
||||||
if (c->recv.len >= MG_MAX_RECV_SIZE) {
|
if (c->recv.len >= MG_MAX_RECV_SIZE) {
|
||||||
@ -481,7 +481,7 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn,
|
|||||||
s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq);
|
s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq);
|
||||||
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
||||||
settmout(c, MIP_TTYPE_KEEPALIVE);
|
settmout(c, MIP_TTYPE_KEEPALIVE);
|
||||||
c->rem.ip = pkt->ip->src;
|
memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t));
|
||||||
c->rem.port = pkt->tcp->sport;
|
c->rem.port = pkt->tcp->sport;
|
||||||
MG_DEBUG(("%lu accepted %M", c->id, mg_print_ip_port, &c->rem));
|
MG_DEBUG(("%lu accepted %M", c->id, mg_print_ip_port, &c->rem));
|
||||||
LIST_ADD_HEAD(struct mg_connection, &lsn->mgr->conns, c);
|
LIST_ADD_HEAD(struct mg_connection, &lsn->mgr->conns, c);
|
||||||
@ -500,17 +500,19 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn,
|
|||||||
long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
|
long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
if (c->is_udp) {
|
if (c->is_udp) {
|
||||||
size_t max_headers_len = 14 + 24 /* max IP */ + 8 /* UDP */;
|
size_t max_headers_len = 14 + 24 /* max IP */ + 8 /* UDP */;
|
||||||
if (len + max_headers_len > ifp->tx.len) {
|
if (len + max_headers_len > ifp->tx.len) {
|
||||||
len = ifp->tx.len - max_headers_len;
|
len = ifp->tx.len - max_headers_len;
|
||||||
}
|
}
|
||||||
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, c->rem.ip, c->rem.port, buf, len);
|
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf, len);
|
||||||
} else {
|
} else {
|
||||||
size_t max_headers_len = 14 + 24 /* max IP */ + 60 /* max TCP */;
|
size_t max_headers_len = 14 + 24 /* max IP */ + 60 /* max TCP */;
|
||||||
if (len + max_headers_len > ifp->tx.len)
|
if (len + max_headers_len > ifp->tx.len)
|
||||||
len = ifp->tx.len - max_headers_len;
|
len = ifp->tx.len - max_headers_len;
|
||||||
if (tx_tcp(ifp, s->mac, c->rem.ip, TH_PUSH | TH_ACK, c->loc.port,
|
if (tx_tcp(ifp, s->mac, rem_ip, TH_PUSH | TH_ACK, c->loc.port,
|
||||||
c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), buf, len) > 0) {
|
c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), buf, len) > 0) {
|
||||||
s->seq += (uint32_t) len;
|
s->seq += (uint32_t) len;
|
||||||
if (s->ttype == MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_KEEPALIVE);
|
if (s->ttype == MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_KEEPALIVE);
|
||||||
@ -793,17 +795,19 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) {
|
|||||||
if (c->is_udp || c->is_listening) continue;
|
if (c->is_udp || c->is_listening) continue;
|
||||||
if (c->is_connecting || c->is_resolving) continue;
|
if (c->is_connecting || c->is_resolving) continue;
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
if (uptime_ms > s->timer) {
|
if (uptime_ms > s->timer) {
|
||||||
if (s->ttype == MIP_TTYPE_ACK) {
|
if (s->ttype == MIP_TTYPE_ACK) {
|
||||||
MG_DEBUG(("%lu ack %x %x", c->id, s->seq, s->ack));
|
MG_DEBUG(("%lu ack %x %x", c->id, s->seq, s->ack));
|
||||||
tx_tcp(ifp, s->mac, c->rem.ip, TH_ACK, c->loc.port, c->rem.port,
|
tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
|
||||||
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
||||||
} else {
|
} else {
|
||||||
if (s->tmiss++ > 2) {
|
if (s->tmiss++ > 2) {
|
||||||
mg_error(c, "keepalive");
|
mg_error(c, "keepalive");
|
||||||
} else {
|
} else {
|
||||||
MG_DEBUG(("%lu keepalive", c->id));
|
MG_DEBUG(("%lu keepalive", c->id));
|
||||||
tx_tcp(ifp, s->mac, c->rem.ip, TH_ACK, c->loc.port, c->rem.port,
|
tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
|
||||||
mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0);
|
mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -871,32 +875,36 @@ static void send_syn(struct mg_connection *c) {
|
|||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
|
uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
|
||||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||||
tx_tcp(ifp, s->mac, c->rem.ip, TH_SYN, c->loc.port, c->rem.port, isn, 0, NULL,
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
|
tx_tcp(ifp, s->mac, rem_ip, TH_SYN, c->loc.port, c->rem.port, isn, 0, NULL,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_connect_resolved(struct mg_connection *c) {
|
void mg_connect_resolved(struct mg_connection *c) {
|
||||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||||
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
c->is_resolving = 0;
|
c->is_resolving = 0;
|
||||||
if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
|
if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
|
||||||
c->loc.ip = ifp->ip;
|
memcpy(c->loc.ip, &ifp->ip, sizeof(uint32_t));
|
||||||
c->loc.port = mg_htons(ifp->eport++);
|
c->loc.port = mg_htons(ifp->eport++);
|
||||||
MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
|
MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
|
||||||
&c->rem));
|
&c->rem));
|
||||||
mg_call(c, MG_EV_RESOLVE, NULL);
|
mg_call(c, MG_EV_RESOLVE, NULL);
|
||||||
if (((c->rem.ip & ifp->mask) == (ifp->ip & ifp->mask))) {
|
if (((rem_ip & ifp->mask) == (ifp->ip & ifp->mask))) {
|
||||||
// If we're in the same LAN, fire an ARP lookup. TODO(cpq): handle this!
|
// If we're in the same LAN, fire an ARP lookup. TODO(cpq): handle this!
|
||||||
MG_DEBUG(("%lu ARP lookup...", c->id));
|
MG_DEBUG(("%lu ARP lookup...", c->id));
|
||||||
arp_ask(ifp, c->rem.ip);
|
arp_ask(ifp, rem_ip);
|
||||||
c->is_arplooking = 1;
|
c->is_arplooking = 1;
|
||||||
} else if (c->rem.ip == (ifp->ip | ~ifp->mask)) {
|
} else if (rem_ip == (ifp->ip | ~ifp->mask)) {
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
memset(s->mac, 0xFF, sizeof(s->mac)); // local broadcast
|
memset(s->mac, 0xFF, sizeof(s->mac)); // local broadcast
|
||||||
} else if ((*((uint8_t *) &c->rem.ip) & 0xE0) == 0xE0) {
|
} else if ((*((uint8_t *) &rem_ip) & 0xE0) == 0xE0) {
|
||||||
struct connstate *s = (struct connstate *) (c + 1); // 224 to 239, E0 to EF
|
struct connstate *s = (struct connstate *) (c + 1); // 224 to 239, E0 to EF
|
||||||
uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group
|
uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group
|
||||||
memcpy(s->mac, mcastp, 3);
|
memcpy(s->mac, mcastp, 3);
|
||||||
memcpy(s->mac + 3, ((uint8_t *) &c->rem.ip) + 1, 3); // 23 LSb
|
memcpy(s->mac + 3, ((uint8_t *) &rem_ip) + 1, 3); // 23 LSb
|
||||||
s->mac[3] &= 0x7F;
|
s->mac[3] &= 0x7F;
|
||||||
} else {
|
} else {
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
@ -926,11 +934,13 @@ static void write_conn(struct mg_connection *c) {
|
|||||||
|
|
||||||
static void close_conn(struct mg_connection *c) {
|
static void close_conn(struct mg_connection *c) {
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
mg_iobuf_free(&s->raw); // For TLS connections, release raw data
|
mg_iobuf_free(&s->raw); // For TLS connections, release raw data
|
||||||
if (c->is_udp == false && c->is_listening == false) { // For TCP conns,
|
if (c->is_udp == false && c->is_listening == false) { // For TCP conns,
|
||||||
struct mg_tcpip_if *ifp =
|
struct mg_tcpip_if *ifp =
|
||||||
(struct mg_tcpip_if *) c->mgr->priv; // send TCP FIN
|
(struct mg_tcpip_if *) c->mgr->priv; // send TCP FIN
|
||||||
tx_tcp(ifp, s->mac, c->rem.ip, TH_FIN | TH_ACK, c->loc.port, c->rem.port,
|
tx_tcp(ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port, c->rem.port,
|
||||||
mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
|
mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
|
||||||
}
|
}
|
||||||
mg_close_conn(c);
|
mg_close_conn(c);
|
||||||
@ -963,11 +973,13 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
|
|||||||
bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||||
bool res = false;
|
bool res = false;
|
||||||
|
uint32_t rem_ip;
|
||||||
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
if (ifp->ip == 0 || ifp->state != MG_TCPIP_STATE_READY) {
|
if (ifp->ip == 0 || ifp->state != MG_TCPIP_STATE_READY) {
|
||||||
mg_error(c, "net down");
|
mg_error(c, "net down");
|
||||||
} else if (c->is_udp) {
|
} else if (c->is_udp) {
|
||||||
struct connstate *s = (struct connstate *) (c + 1);
|
struct connstate *s = (struct connstate *) (c + 1);
|
||||||
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, c->rem.ip, c->rem.port, buf, len);
|
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf, len);
|
||||||
res = true;
|
res = true;
|
||||||
} else {
|
} else {
|
||||||
res = mg_iobuf_add(&c->send, c->send.len, buf, len);
|
res = mg_iobuf_add(&c->send, c->send.len, buf, len);
|
||||||
|
@ -1887,12 +1887,20 @@ static void test_str(void) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
char buf[100];
|
char buf[100];
|
||||||
struct mg_addr a = {mg_htons(3), mg_htonl(0x2000001), {1, 100, 33}, false};
|
struct mg_addr a;
|
||||||
|
uint32_t addr = mg_htonl(0x2000001);
|
||||||
|
memcpy(a.ip, &addr, sizeof(uint32_t));
|
||||||
|
a.port = mg_htons(3);
|
||||||
|
a.is_ip6 = false;
|
||||||
|
|
||||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%M %d", mg_print_ip, &a, 7) == 9);
|
ASSERT(mg_snprintf(buf, sizeof(buf), "%M %d", mg_print_ip, &a, 7) == 9);
|
||||||
ASSERT(strcmp(buf, "2.0.0.1 7") == 0);
|
ASSERT(strcmp(buf, "2.0.0.1 7") == 0);
|
||||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%M %d", mg_print_ip_port, &a, 7) ==
|
ASSERT(mg_snprintf(buf, sizeof(buf), "%M %d", mg_print_ip_port, &a, 7) ==
|
||||||
11);
|
11);
|
||||||
ASSERT(strcmp(buf, "2.0.0.1:3 7") == 0);
|
ASSERT(strcmp(buf, "2.0.0.1:3 7") == 0);
|
||||||
|
|
||||||
|
memset(a.ip, 0, sizeof(a.ip));
|
||||||
|
a.ip[0] = 1, a.ip[1] = 100, a.ip[2] = 33;
|
||||||
a.is_ip6 = true;
|
a.is_ip6 = true;
|
||||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%M %d", mg_print_ip, &a, 7) == 24);
|
ASSERT(mg_snprintf(buf, sizeof(buf), "%M %d", mg_print_ip, &a, 7) == 24);
|
||||||
ASSERT(strcmp(buf, "[164:2100:0:0:0:0:0:0] 7") == 0);
|
ASSERT(strcmp(buf, "[164:2100:0:0:0:0:0:0] 7") == 0);
|
||||||
@ -1980,6 +1988,7 @@ static void test_dns(void) {
|
|||||||
static void test_util(void) {
|
static void test_util(void) {
|
||||||
char buf[100], *p, *s;
|
char buf[100], *p, *s;
|
||||||
struct mg_addr a;
|
struct mg_addr a;
|
||||||
|
uint32_t ipv4;
|
||||||
memset(&a, 0, sizeof(a));
|
memset(&a, 0, sizeof(a));
|
||||||
ASSERT(mg_file_printf(&mg_fs_posix, "data.txt", "%s", "hi") == true);
|
ASSERT(mg_file_printf(&mg_fs_posix, "data.txt", "%s", "hi") == true);
|
||||||
// if (system("ls -l") != 0) (void) 0;
|
// if (system("ls -l") != 0) (void) 0;
|
||||||
@ -1993,54 +2002,55 @@ static void test_util(void) {
|
|||||||
ASSERT(mg_aton(mg_str("0.0.0.-1"), &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(mg_aton(mg_str("127.0.0.1"), &a) == true);
|
||||||
ASSERT(a.is_ip6 == false);
|
ASSERT(a.is_ip6 == false);
|
||||||
ASSERT(a.ip == mg_htonl(0x7f000001));
|
memcpy(&ipv4, a.ip, sizeof(ipv4));
|
||||||
|
ASSERT(ipv4 == mg_htonl(0x7f000001));
|
||||||
|
|
||||||
ASSERT(mg_aton(mg_str("1:2:3:4:5:6:7:8"), &a) == true);
|
ASSERT(mg_aton(mg_str("1:2:3:4:5:6:7:8"), &a) == true);
|
||||||
ASSERT(a.is_ip6 == true);
|
ASSERT(a.is_ip6 == true);
|
||||||
ASSERT(
|
ASSERT(
|
||||||
memcmp(a.ip6,
|
memcmp(a.ip,
|
||||||
"\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08",
|
"\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08",
|
||||||
sizeof(a.ip6)) == 0);
|
sizeof(a.ip)) == 0);
|
||||||
|
|
||||||
memset(a.ip6, 0xaa, sizeof(a.ip6));
|
memset(a.ip, 0xaa, sizeof(a.ip));
|
||||||
ASSERT(mg_aton(mg_str("1::1"), &a) == true);
|
ASSERT(mg_aton(mg_str("1::1"), &a) == true);
|
||||||
ASSERT(a.is_ip6 == true);
|
ASSERT(a.is_ip6 == true);
|
||||||
ASSERT(
|
ASSERT(
|
||||||
memcmp(a.ip6,
|
memcmp(a.ip,
|
||||||
"\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01",
|
"\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01",
|
||||||
sizeof(a.ip6)) == 0);
|
sizeof(a.ip)) == 0);
|
||||||
|
|
||||||
memset(a.ip6, 0xaa, sizeof(a.ip6));
|
memset(a.ip, 0xaa, sizeof(a.ip));
|
||||||
ASSERT(mg_aton(mg_str("::fFff:1.2.3.4"), &a) == true);
|
ASSERT(mg_aton(mg_str("::fFff:1.2.3.4"), &a) == true);
|
||||||
ASSERT(a.is_ip6 == true);
|
ASSERT(a.is_ip6 == true);
|
||||||
ASSERT(memcmp(a.ip6,
|
ASSERT(memcmp(a.ip,
|
||||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
"\x00\x00\xff\xff\x01\x02\x03\x04",
|
"\x00\x00\xff\xff\x01\x02\x03\x04",
|
||||||
sizeof(a.ip6)) == 0);
|
sizeof(a.ip)) == 0);
|
||||||
|
|
||||||
memset(a.ip6, 0xaa, sizeof(a.ip6));
|
memset(a.ip, 0xaa, sizeof(a.ip));
|
||||||
ASSERT(mg_aton(mg_str("::1"), &a) == true);
|
ASSERT(mg_aton(mg_str("::1"), &a) == true);
|
||||||
ASSERT(a.is_ip6 == true);
|
ASSERT(a.is_ip6 == true);
|
||||||
ASSERT(
|
ASSERT(
|
||||||
memcmp(a.ip6,
|
memcmp(a.ip,
|
||||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01",
|
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01",
|
||||||
sizeof(a.ip6)) == 0);
|
sizeof(a.ip)) == 0);
|
||||||
|
|
||||||
memset(a.ip6, 0xaa, sizeof(a.ip6));
|
memset(a.ip, 0xaa, sizeof(a.ip));
|
||||||
ASSERT(mg_aton(mg_str("1::"), &a) == true);
|
ASSERT(mg_aton(mg_str("1::"), &a) == true);
|
||||||
ASSERT(a.is_ip6 == true);
|
ASSERT(a.is_ip6 == true);
|
||||||
ASSERT(
|
ASSERT(
|
||||||
memcmp(a.ip6,
|
memcmp(a.ip,
|
||||||
"\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
"\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
||||||
sizeof(a.ip6)) == 0);
|
sizeof(a.ip)) == 0);
|
||||||
|
|
||||||
memset(a.ip6, 0xaa, sizeof(a.ip6));
|
memset(a.ip, 0xaa, sizeof(a.ip));
|
||||||
ASSERT(mg_aton(mg_str("2001:4860:4860::8888"), &a) == true);
|
ASSERT(mg_aton(mg_str("2001:4860:4860::8888"), &a) == true);
|
||||||
ASSERT(a.is_ip6 == true);
|
ASSERT(a.is_ip6 == true);
|
||||||
ASSERT(
|
ASSERT(
|
||||||
memcmp(a.ip6,
|
memcmp(a.ip,
|
||||||
"\x20\x01\x48\x60\x48\x60\x00\x00\x00\x00\x00\x00\x00\x00\x88\x88",
|
"\x20\x01\x48\x60\x48\x60\x00\x00\x00\x00\x00\x00\x00\x00\x88\x88",
|
||||||
sizeof(a.ip6)) == 0);
|
sizeof(a.ip)) == 0);
|
||||||
|
|
||||||
ASSERT(strcmp(mg_hex("abc", 3, buf), "616263") == 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=%", 3, buf, sizeof(buf), 0) < 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user