fix gw ARP on startup

This commit is contained in:
Sergio R. Caprile 2024-10-09 16:12:39 -03:00
parent 32d90c38db
commit 504ef9422e
5 changed files with 73 additions and 76 deletions

View File

@ -5127,6 +5127,8 @@ static void onstatechange(struct mg_tcpip_if *ifp) {
MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip)); MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw)); MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw));
MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac)); MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac));
} else if (ifp->state == MG_TCPIP_STATE_IP) {
MG_ERROR(("Got IP"));
mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request
} else if (ifp->state == MG_TCPIP_STATE_UP) { } else if (ifp->state == MG_TCPIP_STATE_UP) {
MG_ERROR(("Link up")); MG_ERROR(("Link up"));
@ -5277,8 +5279,12 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
} else if (pkt->arp->op == mg_htons(2)) { } else if (pkt->arp->op == mg_htons(2)) {
if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return; if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return;
if (pkt->arp->spa == ifp->gw) { if (pkt->arp->spa == ifp->gw) {
// Got response for the GW ARP request. Set ifp->gwmac // Got response for the GW ARP request. Set ifp->gwmac and IP -> READY
memcpy(ifp->gwmac, pkt->arp->sha, sizeof(ifp->gwmac)); memcpy(ifp->gwmac, pkt->arp->sha, sizeof(ifp->gwmac));
if (ifp->state == MG_TCPIP_STATE_IP) {
ifp->state = MG_TCPIP_STATE_READY;
onstatechange(ifp);
}
} else { } else {
struct mg_connection *c = getpeer(ifp->mgr, pkt, false); struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
if (c != NULL && c->is_arplooking) { if (c != NULL && c->is_arplooking) {
@ -5353,7 +5359,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
// assume DHCP server = router until ARP resolves // assume DHCP server = router until ARP resolves
memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac)); memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
ifp->ip = ip, ifp->gw = gw, ifp->mask = mask; ifp->ip = ip, ifp->gw = gw, ifp->mask = mask;
ifp->state = MG_TCPIP_STATE_READY; // BOUND state ifp->state = MG_TCPIP_STATE_IP; // BOUND state
uint64_t rand; uint64_t rand;
mg_random(&rand, sizeof(rand)); mg_random(&rand, sizeof(rand));
srand((unsigned int) (rand + mg_millis())); srand((unsigned int) (rand + mg_millis()));
@ -5401,7 +5407,7 @@ static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) {
res.magic = pkt->dhcp->magic; res.magic = pkt->dhcp->magic;
res.xid = pkt->dhcp->xid; res.xid = pkt->dhcp->xid;
if (ifp->enable_get_gateway) { if (ifp->enable_get_gateway) {
ifp->gw = res.yiaddr; ifp->gw = res.yiaddr; // set gw IP, best-effort gwmac as DHCP server's
memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac)); memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
} }
tx_udp(ifp, pkt->eth->src, ifp->ip, mg_htons(67), tx_udp(ifp, pkt->eth->src, ifp->ip, mg_htons(67),
@ -5818,12 +5824,17 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
#if MG_ENABLE_TCPIP_PRINT_DEBUG_STATS #if MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
if (expired_1000ms) { if (expired_1000ms) {
const char *names[] = {"down", "up", "req", "ready"}; const char *names[] = {"down", "up", "req", "ip", "ready"};
MG_INFO(("Status: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u", MG_INFO(("Status: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u",
names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent, names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent,
ifp->ndrop, ifp->nerr)); ifp->ndrop, ifp->nerr));
} }
#endif #endif
// Handle gw ARP request timeout, order is important
if (expired_1000ms && ifp->state == MG_TCPIP_STATE_IP) {
ifp->state = MG_TCPIP_STATE_READY; // keep best-effort MAC
onstatechange(ifp);
}
// Handle physical interface up/down status // Handle physical interface up/down status
if (expired_1000ms && ifp->driver->up) { if (expired_1000ms && ifp->driver->up) {
bool up = ifp->driver->up(ifp); bool up = ifp->driver->up(ifp);
@ -5833,11 +5844,11 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
ifp->state = up == false ? MG_TCPIP_STATE_DOWN ifp->state = up == false ? MG_TCPIP_STATE_DOWN
: ifp->enable_dhcp_client || ifp->ip == 0 : ifp->enable_dhcp_client || ifp->ip == 0
? MG_TCPIP_STATE_UP ? MG_TCPIP_STATE_UP
: MG_TCPIP_STATE_READY; : MG_TCPIP_STATE_IP;
onstatechange(ifp); onstatechange(ifp);
} else if (!ifp->enable_dhcp_client && ifp->state == MG_TCPIP_STATE_UP && } else if (!ifp->enable_dhcp_client && ifp->state == MG_TCPIP_STATE_UP &&
ifp->ip) { ifp->ip) {
ifp->state = MG_TCPIP_STATE_READY; // ifp->fn has set an IP ifp->state = MG_TCPIP_STATE_IP; // ifp->fn has set an IP
onstatechange(ifp); onstatechange(ifp);
} }
if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down")); if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down"));
@ -5953,7 +5964,7 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
ifp->mtu = MG_TCPIP_MTU_DEFAULT; ifp->mtu = MG_TCPIP_MTU_DEFAULT;
mgr->extraconnsize = sizeof(struct connstate); mgr->extraconnsize = sizeof(struct connstate);
if (ifp->ip == 0) ifp->enable_dhcp_client = true; if (ifp->ip == 0) ifp->enable_dhcp_client = true;
memset(ifp->gwmac, 255, sizeof(ifp->gwmac)); // Set to broadcast memset(ifp->gwmac, 255, sizeof(ifp->gwmac)); // Set best-effort to bcast
mg_random(&ifp->eport, sizeof(ifp->eport)); // Random from 0 to 65535 mg_random(&ifp->eport, sizeof(ifp->eport)); // Random from 0 to 65535
ifp->eport |= MG_EPHEMERAL_PORT_BASE; // Random from ifp->eport |= MG_EPHEMERAL_PORT_BASE; // Random from
// MG_EPHEMERAL_PORT_BASE to 65535 // MG_EPHEMERAL_PORT_BASE to 65535

View File

@ -2777,8 +2777,9 @@ struct mg_tcpip_if {
uint8_t state; // Current state uint8_t state; // Current state
#define MG_TCPIP_STATE_DOWN 0 // Interface is down #define MG_TCPIP_STATE_DOWN 0 // Interface is down
#define MG_TCPIP_STATE_UP 1 // Interface is up #define MG_TCPIP_STATE_UP 1 // Interface is up
#define MG_TCPIP_STATE_REQ 2 // Interface is up and has requested an IP #define MG_TCPIP_STATE_REQ 2 // Interface is up, DHCP REQUESTING state
#define MG_TCPIP_STATE_READY 3 // Interface is up and has an IP assigned #define MG_TCPIP_STATE_IP 3 // Interface is up and has an IP assigned
#define MG_TCPIP_STATE_READY 4 // Interface has fully come up, ready to work
}; };
void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *); void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);

View File

@ -205,6 +205,8 @@ static void onstatechange(struct mg_tcpip_if *ifp) {
MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip)); MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw)); MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw));
MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac)); MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac));
} else if (ifp->state == MG_TCPIP_STATE_IP) {
MG_ERROR(("Got IP"));
mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request
} else if (ifp->state == MG_TCPIP_STATE_UP) { } else if (ifp->state == MG_TCPIP_STATE_UP) {
MG_ERROR(("Link up")); MG_ERROR(("Link up"));
@ -355,8 +357,12 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
} else if (pkt->arp->op == mg_htons(2)) { } else if (pkt->arp->op == mg_htons(2)) {
if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return; if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return;
if (pkt->arp->spa == ifp->gw) { if (pkt->arp->spa == ifp->gw) {
// Got response for the GW ARP request. Set ifp->gwmac // Got response for the GW ARP request. Set ifp->gwmac and IP -> READY
memcpy(ifp->gwmac, pkt->arp->sha, sizeof(ifp->gwmac)); memcpy(ifp->gwmac, pkt->arp->sha, sizeof(ifp->gwmac));
if (ifp->state == MG_TCPIP_STATE_IP) {
ifp->state = MG_TCPIP_STATE_READY;
onstatechange(ifp);
}
} else { } else {
struct mg_connection *c = getpeer(ifp->mgr, pkt, false); struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
if (c != NULL && c->is_arplooking) { if (c != NULL && c->is_arplooking) {
@ -431,7 +437,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
// assume DHCP server = router until ARP resolves // assume DHCP server = router until ARP resolves
memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac)); memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
ifp->ip = ip, ifp->gw = gw, ifp->mask = mask; ifp->ip = ip, ifp->gw = gw, ifp->mask = mask;
ifp->state = MG_TCPIP_STATE_READY; // BOUND state ifp->state = MG_TCPIP_STATE_IP; // BOUND state
uint64_t rand; uint64_t rand;
mg_random(&rand, sizeof(rand)); mg_random(&rand, sizeof(rand));
srand((unsigned int) (rand + mg_millis())); srand((unsigned int) (rand + mg_millis()));
@ -479,7 +485,7 @@ static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) {
res.magic = pkt->dhcp->magic; res.magic = pkt->dhcp->magic;
res.xid = pkt->dhcp->xid; res.xid = pkt->dhcp->xid;
if (ifp->enable_get_gateway) { if (ifp->enable_get_gateway) {
ifp->gw = res.yiaddr; ifp->gw = res.yiaddr; // set gw IP, best-effort gwmac as DHCP server's
memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac)); memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
} }
tx_udp(ifp, pkt->eth->src, ifp->ip, mg_htons(67), tx_udp(ifp, pkt->eth->src, ifp->ip, mg_htons(67),
@ -896,12 +902,17 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
#if MG_ENABLE_TCPIP_PRINT_DEBUG_STATS #if MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
if (expired_1000ms) { if (expired_1000ms) {
const char *names[] = {"down", "up", "req", "ready"}; const char *names[] = {"down", "up", "req", "ip", "ready"};
MG_INFO(("Status: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u", MG_INFO(("Status: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u",
names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent, names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent,
ifp->ndrop, ifp->nerr)); ifp->ndrop, ifp->nerr));
} }
#endif #endif
// Handle gw ARP request timeout, order is important
if (expired_1000ms && ifp->state == MG_TCPIP_STATE_IP) {
ifp->state = MG_TCPIP_STATE_READY; // keep best-effort MAC
onstatechange(ifp);
}
// Handle physical interface up/down status // Handle physical interface up/down status
if (expired_1000ms && ifp->driver->up) { if (expired_1000ms && ifp->driver->up) {
bool up = ifp->driver->up(ifp); bool up = ifp->driver->up(ifp);
@ -911,11 +922,11 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
ifp->state = up == false ? MG_TCPIP_STATE_DOWN ifp->state = up == false ? MG_TCPIP_STATE_DOWN
: ifp->enable_dhcp_client || ifp->ip == 0 : ifp->enable_dhcp_client || ifp->ip == 0
? MG_TCPIP_STATE_UP ? MG_TCPIP_STATE_UP
: MG_TCPIP_STATE_READY; : MG_TCPIP_STATE_IP;
onstatechange(ifp); onstatechange(ifp);
} else if (!ifp->enable_dhcp_client && ifp->state == MG_TCPIP_STATE_UP && } else if (!ifp->enable_dhcp_client && ifp->state == MG_TCPIP_STATE_UP &&
ifp->ip) { ifp->ip) {
ifp->state = MG_TCPIP_STATE_READY; // ifp->fn has set an IP ifp->state = MG_TCPIP_STATE_IP; // ifp->fn has set an IP
onstatechange(ifp); onstatechange(ifp);
} }
if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down")); if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down"));
@ -1031,7 +1042,7 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
ifp->mtu = MG_TCPIP_MTU_DEFAULT; ifp->mtu = MG_TCPIP_MTU_DEFAULT;
mgr->extraconnsize = sizeof(struct connstate); mgr->extraconnsize = sizeof(struct connstate);
if (ifp->ip == 0) ifp->enable_dhcp_client = true; if (ifp->ip == 0) ifp->enable_dhcp_client = true;
memset(ifp->gwmac, 255, sizeof(ifp->gwmac)); // Set to broadcast memset(ifp->gwmac, 255, sizeof(ifp->gwmac)); // Set best-effort to bcast
mg_random(&ifp->eport, sizeof(ifp->eport)); // Random from 0 to 65535 mg_random(&ifp->eport, sizeof(ifp->eport)); // Random from 0 to 65535
ifp->eport |= MG_EPHEMERAL_PORT_BASE; // Random from ifp->eport |= MG_EPHEMERAL_PORT_BASE; // Random from
// MG_EPHEMERAL_PORT_BASE to 65535 // MG_EPHEMERAL_PORT_BASE to 65535

View File

@ -60,8 +60,9 @@ struct mg_tcpip_if {
uint8_t state; // Current state uint8_t state; // Current state
#define MG_TCPIP_STATE_DOWN 0 // Interface is down #define MG_TCPIP_STATE_DOWN 0 // Interface is down
#define MG_TCPIP_STATE_UP 1 // Interface is up #define MG_TCPIP_STATE_UP 1 // Interface is up
#define MG_TCPIP_STATE_REQ 2 // Interface is up and has requested an IP #define MG_TCPIP_STATE_REQ 2 // Interface is up, DHCP REQUESTING state
#define MG_TCPIP_STATE_READY 3 // Interface is up and has an IP assigned #define MG_TCPIP_STATE_IP 3 // Interface is up and has an IP assigned
#define MG_TCPIP_STATE_READY 4 // Interface has fully come up, ready to work
}; };
void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *); void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);

View File

@ -1,7 +1,8 @@
// Copyright (c) 2022 Cesanta Software Limited // Copyright (c) 2022-24 Cesanta Software Limited
// All rights reserved // All rights reserved
// //
// SNTP example using MIP and pcap driver // example using MIP and pcap driver
// make CFLAGS_EXTRA="-DMG_TLS=MG_TLS_BUILTIN -DDISABLE_DHCP" for "auto-IP"
#include <pcap.h> #include <pcap.h>
#include "mongoose.h" #include "mongoose.h"
@ -10,7 +11,6 @@
#define MQTTS_URL "mqtts://mongoose.ws:8883" // HiveMQ does not TLS1.3 #define MQTTS_URL "mqtts://mongoose.ws:8883" // HiveMQ does not TLS1.3
#define MQTT_TOPIC "mg/rx" // Topic to subscribe to #define MQTT_TOPIC "mg/rx" // Topic to subscribe to
// // Taken from broker.emqx.io
static const char *s_ca_cert = static const char *s_ca_cert =
"-----BEGIN CERTIFICATE-----\n" "-----BEGIN CERTIFICATE-----\n"
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n"
@ -44,29 +44,6 @@ static const char *s_ca_cert =
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n"
"-----END CERTIFICATE-----\n"; "-----END CERTIFICATE-----\n";
// "-----BEGIN CERTIFICATE-----\n"
// "MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh"
// "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
// "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
// "MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n"
// "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
// "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n"
// "9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n"
// "2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n"
// "1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n"
// "q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n"
// "tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n"
// "vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n"
// "BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n"
// "5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n"
// "1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n"
// "NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n"
// "Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n"
// "8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n"
// "pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n"
// "MrY=\n"
// "-----END CERTIFICATE-----\n";
static const char *s_tls_cert = static const char *s_tls_cert =
"-----BEGIN CERTIFICATE-----\n" "-----BEGIN CERTIFICATE-----\n"
"MIIBMTCB2aADAgECAgkAluqkgeuV/zUwCgYIKoZIzj0EAwIwEzERMA8GA1UEAwwI\n" "MIIBMTCB2aADAgECAgkAluqkgeuV/zUwCgYIKoZIzj0EAwIwEzERMA8GA1UEAwwI\n"
@ -165,8 +142,6 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
(void) ev_data; (void) ev_data;
} }
static struct mg_connection *mqtt_conn = NULL;
static void mqtt_ev_handler(struct mg_connection *c, int ev, void *ev_data) { static void mqtt_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_OPEN) { if (ev == MG_EV_OPEN) {
MG_INFO(("%lu CREATED", c->id)); MG_INFO(("%lu CREATED", c->id));
@ -191,21 +166,15 @@ static void mqtt_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
mm->data.buf, (int) mm->topic.len, mm->topic.buf)); mm->data.buf, (int) mm->topic.len, mm->topic.buf));
} else if (ev == MG_EV_CLOSE) { } else if (ev == MG_EV_CLOSE) {
MG_INFO(("%lu CLOSED", c->id)); MG_INFO(("%lu CLOSED", c->id));
mqtt_conn = NULL; // Mark that we're closed
} }
} }
static void if_ev_handler(struct mg_tcpip_if *ifp, int ev, void *ev_data) { static void if_ev_handler(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
// Trigger MQTT connection when we have an IP address // Trigger MQTT connection when we have an IP address
if (ifp->state == MG_TCPIP_STATE_READY && if (ifp->state == MG_TCPIP_STATE_READY && ev == MG_TCPIP_EV_ST_CHG) {
(ev == MG_TCPIP_EV_ST_CHG || ev == MG_TCPIP_EV_TIMER_1S)) {
struct mg_mqtt_opts opts = {.clean = true}; struct mg_mqtt_opts opts = {.clean = true};
if (mqtt_conn == NULL) { // mg_mqtt_connect(ifp->mgr, MQTT_URL, &opts, mqtt_ev_handler, NULL);
// mqtt_conn = mg_mqtt_connect(ifp->mgr, MQTT_URL, &opts, mqtt_ev_handler, mg_mqtt_connect(ifp->mgr, MQTTS_URL, &opts, mqtt_ev_handler, "tls enabled");
// NULL);
mqtt_conn = mg_mqtt_connect(ifp->mgr, MQTTS_URL, &opts, mqtt_ev_handler,
"tls enabled");
}
} }
#if defined(DISABLE_DHCP) #if defined(DISABLE_DHCP)
@ -216,9 +185,12 @@ static void if_ev_handler(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
if (ip == 0) ip = MG_IPV4(169, 254, 2, 100); if (ip == 0) ip = MG_IPV4(169, 254, 2, 100);
// restart process on link change // restart process on link change
if (ev == MG_TCPIP_EV_ST_CHG && ifp->state == MG_TCPIP_STATE_DOWN) if (ev == MG_TCPIP_EV_ST_CHG && ifp->state == MG_TCPIP_STATE_DOWN) {
ifp->ip = 0; ifp->ip = 0;
counter = 0;
}
if (ifp->state == MG_TCPIP_STATE_UP) {
// Catch ARP packets. Parse them yourself, that's easy. // Catch ARP packets. Parse them yourself, that's easy.
if (ev == MG_TCPIP_EV_ARP) { if (ev == MG_TCPIP_EV_ARP) {
struct mg_str *frame = ev_data; struct mg_str *frame = ev_data;
@ -228,18 +200,19 @@ static void if_ev_handler(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
} }
// Catch 1 second timer events // Catch 1 second timer events
if (ev == MG_TCPIP_EV_TIMER_1S && ifp->state == MG_TCPIP_STATE_UP) { if (ev == MG_TCPIP_EV_TIMER_1S) {
if (++counter <= 3) {
MG_INFO(("Sending ARP probe")); MG_INFO(("Sending ARP probe"));
mg_tcpip_arp_request(ifp, ip, NULL); mg_tcpip_arp_request(ifp, ip, NULL);
} else {
// Seems to be no conflict. Assign us an IP // Seems to be no conflict. Assign us an IP
if (counter++ > 2) { MG_INFO(("Assigning %M, sending gratuitous ARP", mg_print_ip4, &ip));
MG_INFO(("Assigning %M, sending ARP probe", mg_print_ip4, &ip)); ifp->ip = ip; // state will change to MG_TCPIP_STATE_IP on next poll
ifp->ip = ip; // state will change to MG_TCPIP_STATE_READY on next poll
mg_tcpip_arp_request(ifp, ip, ifp->mac); mg_tcpip_arp_request(ifp, ip, ifp->mac);
} }
} }
} }
}
#else #else
(void) ev_data; (void) ev_data;
#endif #endif
@ -302,17 +275,17 @@ int main(int argc, char *argv[]) {
struct mg_tcpip_driver driver = {.tx = pcap_tx, .up = pcap_up, .rx = pcap_rx}; struct mg_tcpip_driver driver = {.tx = pcap_tx, .up = pcap_up, .rx = pcap_rx};
struct mg_tcpip_if mif = {.driver = &driver, struct mg_tcpip_if mif = {.driver = &driver,
.driver_data = ph, .driver_data = ph,
.enable_mac_check = true,
#if defined(DISABLE_DHCP) #if defined(DISABLE_DHCP)
.mask = MG_IPV4(255, 255, 255, 0), .mask = MG_IPV4(255, 255, 255, 0),
.gw = MG_IPV4(169, 254, 2, 1) .gw = MG_IPV4(169, 254, 2, 1),
#endif #endif
}; .fn = if_ev_handler};
sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mif.mac[0], &mif.mac[1], sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mif.mac[0], &mif.mac[1],
&mif.mac[2], &mif.mac[3], &mif.mac[4], &mif.mac[5]); &mif.mac[2], &mif.mac[3], &mif.mac[4], &mif.mac[5]);
mg_tcpip_init(&mgr, &mif); mg_tcpip_init(&mgr, &mif);
// Call order is important: call after mg_tcpip_init() // order is important: set after calling mg_tcpip_init()
mif.fn = if_ev_handler;
#if defined(DISABLE_DHCP) #if defined(DISABLE_DHCP)
mif.enable_dhcp_client = false; mif.enable_dhcp_client = false;
#endif #endif