mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-27 06:51:04 +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
|
||||
} else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) {
|
||||
dm->addr.is_ip6 = true;
|
||||
memcpy(&dm->addr.ip6, &buf[ofs - 16], 16);
|
||||
memcpy(&dm->addr.ip, &buf[ofs - 16], 16);
|
||||
dm->resolved = true;
|
||||
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) {
|
||||
uint32_t localhost = mg_htonl(0x7f000001);
|
||||
if (mg_vcasecmp(&str, "localhost") != 0) return false;
|
||||
addr->ip = mg_htonl(0x7f000001);
|
||||
memcpy(addr->ip, &localhost, sizeof(uint32_t));
|
||||
addr->is_ip6 = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
|
||||
if (str.len > 0) return false;
|
||||
addr->ip = 0;
|
||||
memset(addr->ip, 0, sizeof(addr->ip));
|
||||
addr->is_ip6 = false;
|
||||
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) {
|
||||
int i;
|
||||
uint32_t ipv4;
|
||||
if (str.len < 14) return false;
|
||||
if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false;
|
||||
for (i = 2; i < 6; i++) {
|
||||
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;
|
||||
memset(addr->ip6, 0, sizeof(addr->ip6));
|
||||
addr->ip6[10] = addr->ip6[11] = 255;
|
||||
memcpy(&addr->ip6[12], &addr->ip, 4);
|
||||
memcpy(&ipv4, addr->ip, sizeof(ipv4));
|
||||
memset(addr->ip, 0, sizeof(addr->ip));
|
||||
addr->ip[10] = addr->ip[11] = 255;
|
||||
memcpy(&addr->ip[12], &ipv4, 4);
|
||||
addr->is_ip6 = 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;
|
||||
// MG_DEBUG(("%zu %zu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j]));
|
||||
val = mg_unhexn(&str.ptr[j], i - j + 1);
|
||||
addr->ip6[n] = (uint8_t) ((val >> 8) & 255);
|
||||
addr->ip6[n + 1] = (uint8_t) (val & 255);
|
||||
addr->ip[n] = (uint8_t) ((val >> 8) & 255);
|
||||
addr->ip[n + 1] = (uint8_t) (val & 255);
|
||||
} else if (str.ptr[i] == ':') {
|
||||
j = 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;
|
||||
}
|
||||
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 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (n < 14 && dc == 42) return false;
|
||||
if (n < 14) {
|
||||
memmove(&addr->ip6[dc + (14 - n)], &addr->ip6[dc], n - dc + 2);
|
||||
memset(&addr->ip6[dc], 0, 14 - n);
|
||||
memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2);
|
||||
memset(&addr->ip[dc], 0, 14 - n);
|
||||
}
|
||||
|
||||
addr->is_ip6 = 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4446,12 +4451,12 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) {
|
||||
memset(usa, 0, sizeof(*usa));
|
||||
usa->sin.sin_family = AF_INET;
|
||||
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 (a->is_ip6) {
|
||||
usa->sin.sin_family = AF_INET6;
|
||||
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);
|
||||
}
|
||||
#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) {
|
||||
a->is_ip6 = is_ip6;
|
||||
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 (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;
|
||||
}
|
||||
#endif
|
||||
@ -7776,7 +7781,7 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
if (c != NULL && c->is_arplooking) {
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
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));
|
||||
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.
|
||||
} else {
|
||||
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);
|
||||
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
||||
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);
|
||||
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
||||
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;
|
||||
MG_DEBUG(("%lu accepted %M", c->id, mg_print_ip_port, &c->rem));
|
||||
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) {
|
||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
uint32_t rem_ip;
|
||||
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||
if (c->is_udp) {
|
||||
size_t max_headers_len = 14 + 24 /* max IP */ + 8 /* UDP */;
|
||||
if (len + max_headers_len > ifp->tx.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 {
|
||||
size_t max_headers_len = 14 + 24 /* max IP */ + 60 /* max TCP */;
|
||||
if (len + max_headers_len > ifp->tx.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) {
|
||||
s->seq += (uint32_t) len;
|
||||
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_connecting || c->is_resolving) continue;
|
||||
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 (s->ttype == MIP_TTYPE_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);
|
||||
} else {
|
||||
if (s->tmiss++ > 2) {
|
||||
mg_error(c, "keepalive");
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -8339,32 +8348,36 @@ static void send_syn(struct mg_connection *c) {
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
|
||||
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);
|
||||
}
|
||||
|
||||
void mg_connect_resolved(struct mg_connection *c) {
|
||||
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;
|
||||
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++);
|
||||
MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
|
||||
&c->rem));
|
||||
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!
|
||||
MG_DEBUG(("%lu ARP lookup...", c->id));
|
||||
arp_ask(ifp, c->rem.ip);
|
||||
arp_ask(ifp, rem_ip);
|
||||
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);
|
||||
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
|
||||
uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group
|
||||
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;
|
||||
} else {
|
||||
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) {
|
||||
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
|
||||
if (c->is_udp == false && c->is_listening == false) { // For TCP conns,
|
||||
struct mg_tcpip_if *ifp =
|
||||
(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_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) {
|
||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||
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) {
|
||||
mg_error(c, "net down");
|
||||
} else if (c->is_udp) {
|
||||
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;
|
||||
} else {
|
||||
res = mg_iobuf_add(&c->send, c->send.len, buf, len);
|
||||
|
@ -1137,10 +1137,9 @@ struct mg_dns {
|
||||
};
|
||||
|
||||
struct mg_addr {
|
||||
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
|
||||
uint8_t ip[16]; // Holds IPv4 or IPv6 address, in network byte order
|
||||
uint16_t port; // TCP or UDP port in network byte order
|
||||
bool is_ip6; // True when address is IPv6 address
|
||||
};
|
||||
|
||||
struct mg_mgr {
|
||||
@ -1152,6 +1151,7 @@ struct mg_mgr {
|
||||
unsigned long nextid; // Next connection ID
|
||||
unsigned long timerid; // Next timer ID
|
||||
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
|
||||
void *active_dns_requests; // DNS requests in progress
|
||||
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
|
||||
} else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) {
|
||||
dm->addr.is_ip6 = true;
|
||||
memcpy(&dm->addr.ip6, &buf[ofs - 16], 16);
|
||||
memcpy(&dm->addr.ip, &buf[ofs - 16], 16);
|
||||
dm->resolved = true;
|
||||
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) {
|
||||
uint32_t localhost = mg_htonl(0x7f000001);
|
||||
if (mg_vcasecmp(&str, "localhost") != 0) return false;
|
||||
addr->ip = mg_htonl(0x7f000001);
|
||||
memcpy(addr->ip, &localhost, sizeof(uint32_t));
|
||||
addr->is_ip6 = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
|
||||
if (str.len > 0) return false;
|
||||
addr->ip = 0;
|
||||
memset(addr->ip, 0, sizeof(addr->ip));
|
||||
addr->is_ip6 = false;
|
||||
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) {
|
||||
int i;
|
||||
uint32_t ipv4;
|
||||
if (str.len < 14) return false;
|
||||
if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false;
|
||||
for (i = 2; i < 6; i++) {
|
||||
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;
|
||||
memset(addr->ip6, 0, sizeof(addr->ip6));
|
||||
addr->ip6[10] = addr->ip6[11] = 255;
|
||||
memcpy(&addr->ip6[12], &addr->ip, 4);
|
||||
memcpy(&ipv4, addr->ip, sizeof(ipv4));
|
||||
memset(addr->ip, 0, sizeof(addr->ip));
|
||||
addr->ip[10] = addr->ip[11] = 255;
|
||||
memcpy(&addr->ip[12], &ipv4, 4);
|
||||
addr->is_ip6 = 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;
|
||||
// MG_DEBUG(("%zu %zu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j]));
|
||||
val = mg_unhexn(&str.ptr[j], i - j + 1);
|
||||
addr->ip6[n] = (uint8_t) ((val >> 8) & 255);
|
||||
addr->ip6[n + 1] = (uint8_t) (val & 255);
|
||||
addr->ip[n] = (uint8_t) ((val >> 8) & 255);
|
||||
addr->ip[n + 1] = (uint8_t) (val & 255);
|
||||
} else if (str.ptr[i] == ':') {
|
||||
j = 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;
|
||||
}
|
||||
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 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (n < 14 && dc == 42) return false;
|
||||
if (n < 14) {
|
||||
memmove(&addr->ip6[dc + (14 - n)], &addr->ip6[dc], n - dc + 2);
|
||||
memset(&addr->ip6[dc], 0, 14 - n);
|
||||
memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2);
|
||||
memset(&addr->ip[dc], 0, 14 - n);
|
||||
}
|
||||
|
||||
addr->is_ip6 = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -13,10 +13,9 @@ struct mg_dns {
|
||||
};
|
||||
|
||||
struct mg_addr {
|
||||
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
|
||||
uint8_t ip[16]; // Holds IPv4 or IPv6 address, in network byte order
|
||||
uint16_t port; // TCP or UDP port in network byte order
|
||||
bool is_ip6; // True when address is IPv6 address
|
||||
};
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -57,12 +57,12 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) {
|
||||
memset(usa, 0, sizeof(*usa));
|
||||
usa->sin.sin_family = AF_INET;
|
||||
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 (a->is_ip6) {
|
||||
usa->sin.sin_family = AF_INET6;
|
||||
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);
|
||||
}
|
||||
#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) {
|
||||
a->is_ip6 = is_ip6;
|
||||
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 (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;
|
||||
}
|
||||
#endif
|
||||
|
@ -308,7 +308,7 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
if (c != NULL && c->is_arplooking) {
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
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));
|
||||
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.
|
||||
} else {
|
||||
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);
|
||||
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
||||
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);
|
||||
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
||||
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;
|
||||
MG_DEBUG(("%lu accepted %M", c->id, mg_print_ip_port, &c->rem));
|
||||
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) {
|
||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
uint32_t rem_ip;
|
||||
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||
if (c->is_udp) {
|
||||
size_t max_headers_len = 14 + 24 /* max IP */ + 8 /* UDP */;
|
||||
if (len + max_headers_len > ifp->tx.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 {
|
||||
size_t max_headers_len = 14 + 24 /* max IP */ + 60 /* max TCP */;
|
||||
if (len + max_headers_len > ifp->tx.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) {
|
||||
s->seq += (uint32_t) len;
|
||||
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_connecting || c->is_resolving) continue;
|
||||
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 (s->ttype == MIP_TTYPE_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);
|
||||
} else {
|
||||
if (s->tmiss++ > 2) {
|
||||
mg_error(c, "keepalive");
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -871,32 +875,36 @@ static void send_syn(struct mg_connection *c) {
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
|
||||
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);
|
||||
}
|
||||
|
||||
void mg_connect_resolved(struct mg_connection *c) {
|
||||
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;
|
||||
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++);
|
||||
MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
|
||||
&c->rem));
|
||||
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!
|
||||
MG_DEBUG(("%lu ARP lookup...", c->id));
|
||||
arp_ask(ifp, c->rem.ip);
|
||||
arp_ask(ifp, rem_ip);
|
||||
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);
|
||||
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
|
||||
uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group
|
||||
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;
|
||||
} else {
|
||||
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) {
|
||||
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
|
||||
if (c->is_udp == false && c->is_listening == false) { // For TCP conns,
|
||||
struct mg_tcpip_if *ifp =
|
||||
(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_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) {
|
||||
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
|
||||
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) {
|
||||
mg_error(c, "net down");
|
||||
} else if (c->is_udp) {
|
||||
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;
|
||||
} else {
|
||||
res = mg_iobuf_add(&c->send, c->send.len, buf, len);
|
||||
|
@ -1887,12 +1887,20 @@ static void test_str(void) {
|
||||
|
||||
{
|
||||
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(strcmp(buf, "2.0.0.1 7") == 0);
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%M %d", mg_print_ip_port, &a, 7) ==
|
||||
11);
|
||||
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;
|
||||
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);
|
||||
@ -1980,6 +1988,7 @@ static void test_dns(void) {
|
||||
static void test_util(void) {
|
||||
char buf[100], *p, *s;
|
||||
struct mg_addr a;
|
||||
uint32_t ipv4;
|
||||
memset(&a, 0, sizeof(a));
|
||||
ASSERT(mg_file_printf(&mg_fs_posix, "data.txt", "%s", "hi") == true);
|
||||
// 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("127.0.0.1"), &a) == true);
|
||||
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(a.is_ip6 == true);
|
||||
ASSERT(
|
||||
memcmp(a.ip6,
|
||||
memcmp(a.ip,
|
||||
"\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(a.is_ip6 == true);
|
||||
ASSERT(
|
||||
memcmp(a.ip6,
|
||||
memcmp(a.ip,
|
||||
"\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(a.is_ip6 == true);
|
||||
ASSERT(memcmp(a.ip6,
|
||||
ASSERT(memcmp(a.ip,
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\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(a.is_ip6 == true);
|
||||
ASSERT(
|
||||
memcmp(a.ip6,
|
||||
memcmp(a.ip,
|
||||
"\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(a.is_ip6 == true);
|
||||
ASSERT(
|
||||
memcmp(a.ip6,
|
||||
memcmp(a.ip,
|
||||
"\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(a.is_ip6 == true);
|
||||
ASSERT(
|
||||
memcmp(a.ip6,
|
||||
memcmp(a.ip,
|
||||
"\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(mg_url_decode("a=%", 3, buf, sizeof(buf), 0) < 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user