diff --git a/libraries/ESP8266WiFi/src/WiFiUdp.cpp b/libraries/ESP8266WiFi/src/WiFiUdp.cpp index a0a5c1d4e4..adc6119bad 100644 --- a/libraries/ESP8266WiFi/src/WiFiUdp.cpp +++ b/libraries/ESP8266WiFi/src/WiFiUdp.cpp @@ -85,6 +85,11 @@ uint8_t WiFiUDP::begin(uint16_t port) return (_ctx->listen(IPAddress(), port)) ? 1 : 0; } +uint8_t WiFiUDP::beginMulticast(IPAddress multicast, uint16_t port) +{ + return beginMulticast(IPAddress(IP4_ADDR_ANY), multicast, port); +} + uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port) { if (_ctx) { @@ -156,11 +161,7 @@ int WiFiUDP::beginPacket(IPAddress ip, uint16_t port) int WiFiUDP::beginPacketMulticast(IPAddress multicastAddress, uint16_t port, IPAddress interfaceAddress, int ttl) { - if (!_ctx) { - _ctx = new UdpContext; - _ctx->ref(); - } - if (!_ctx->connect(multicastAddress, port)) { + if (!beginPacket(multicastAddress, port)) { return 0; } _ctx->setMulticastInterface(interfaceAddress); @@ -176,6 +177,14 @@ int WiFiUDP::endPacket() return (_ctx->send()) ? 1 : 0; } +int WiFiUDP::endPacketOverMulticast() +{ + if (!_ctx) + return 0; + + return (_ctx->send_multicast_all()) ? 1 : 0; +} + size_t WiFiUDP::write(uint8_t byte) { return write(&byte, 1); diff --git a/libraries/ESP8266WiFi/src/WiFiUdp.h b/libraries/ESP8266WiFi/src/WiFiUdp.h index a1cf42be10..428a018fb6 100644 --- a/libraries/ESP8266WiFi/src/WiFiUdp.h +++ b/libraries/ESP8266WiFi/src/WiFiUdp.h @@ -48,15 +48,18 @@ class WiFiUDP : public UDP, public SList { void stop() override; // join a multicast group and listen on the given port uint8_t beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port); + uint8_t beginMulticast(IPAddress multicast, uint16_t port); // Sending UDP packets // Start building up a packet to send to the remote host specific in ip and port // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port int beginPacket(IPAddress ip, uint16_t port) override; + // Start building up a packet to send to the remote host specific in host and port // Returns 1 if successful, 0 if there was a problem resolving the hostname or port int beginPacket(const char *host, uint16_t port) override; + // Start building up a packet to send to the multicast address // multicastAddress - muticast address to send to // interfaceAddress - the local IP address of the interface that should be used @@ -67,9 +70,14 @@ class WiFiUDP : public UDP, public SList { uint16_t port, IPAddress interfaceAddress, int ttl = 1); + // Finish off this packet and send it // Returns 1 if the packet was sent successfully, 0 if there was an error int endPacket() override; + + int beginPacketOverMulticast(const IPAddress& ip, uint16_t port) { return beginPacket(ip, port); } + int endPacketOverMulticast(); + // Write a single byte into the packet size_t write(uint8_t) override; // Write size bytes from buffer into the packet diff --git a/libraries/ESP8266WiFi/src/include/UdpContext.h b/libraries/ESP8266WiFi/src/include/UdpContext.h index a81384b2a7..c8f306d0f8 100644 --- a/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -419,7 +419,7 @@ class UdpContext return size; } - bool send(CONST ip_addr_t* addr = 0, uint16_t port = 0) + bool send(CONST ip_addr_t* addr = 0, uint16_t port = 0, bool release_source = true) { size_t data_size = _tx_buf_offset; pbuf* tx_copy = pbuf_alloc(PBUF_TRANSPORT, data_size, PBUF_RAM); @@ -435,39 +435,81 @@ class UdpContext data_size -= will_copy; } } - if (_tx_buf_head) - pbuf_free(_tx_buf_head); - _tx_buf_head = 0; - _tx_buf_cur = 0; - _tx_buf_offset = 0; + if (release_source) { + reset_send_buffer(); + } if(!tx_copy){ return false; } - if (!addr) { addr = &_pcb->remote_ip; port = _pcb->remote_port; } -#ifdef LWIP_MAYBE_XCC - uint16_t old_ttl = _pcb->ttl; - if (ip_addr_ismulticast(addr)) { - _pcb->ttl = _mcast_ttl; - } -#endif + err_t err = udp_sendto(_pcb, tx_copy, addr, port); if (err != ERR_OK) { DEBUGV(":ust rc=%d\r\n", (int) err); } -#ifdef LWIP_MAYBE_XCC - _pcb->ttl = old_ttl; -#endif + pbuf_free(tx_copy); return err == ERR_OK; } + bool send_multicast_all (CONST ip_addr_t* addr = 0, uint16_t port = 0) + { + if (!addr) { + addr = &_pcb->remote_ip; + port = _pcb->remote_port; + } + if (!ip_addr_ismulticast(addr)) + { + return false; + } + + // backup PCB multicast settings + + // backup multicast IPv4 address + ip4_addr_t backup_mcast_addr; + ip4_addr_set(&backup_mcast_addr, udp_get_multicast_netif_addr(_pcb)); + // reset it in PCB (may be useless, interface setting is used first (i set))) + ip4_addr_set_any(udp_get_multicast_netif_addr(_pcb)); + // backup multicast interface (will be overwritten) + u8_t backup_mcast_index = udp_get_multicast_netif_index(_pcb); + + // loop on all interfaces and send + + bool ret = false; + for (netif* nif = netif_list; nif; nif = nif->next) + if (netif_is_up(nif)) + { + // change multicast interface + setMulticastInterface(nif); + ret = ret || send(addr, port, false); + } + + // release source + reset_send_buffer(); + // ^^ optimization path: avoid tx_copy multiple times in ::send(,,false) + + // restore PCB multicast settings + udp_set_multicast_netif_index(_pcb, backup_mcast_index); + udp_set_multicast_netif_addr(_pcb, &backup_mcast_addr); + + return ret; + } + private: + void reset_send_buffer () + { + if (_tx_buf_head) + pbuf_free(_tx_buf_head); + _tx_buf_head = 0; + _tx_buf_cur = 0; + _tx_buf_offset = 0; + } + size_t _processSize (const pbuf* pb) { size_t ret = 0; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.cpp b/libraries/ESP8266mDNS/src/LEAmDNS.cpp index 87ff5167ff..92cbc7aecf 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS.cpp @@ -62,11 +62,10 @@ MDNSResponder::MDNSResponder(void) m_pServiceQueries(0), m_fnServiceTxtCallback(0), #ifdef ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE - m_bPassivModeEnabled(true), + m_bPassivModeEnabled(true) #else - m_bPassivModeEnabled(false), + m_bPassivModeEnabled(false) #endif - m_netif(nullptr) { } @@ -95,6 +94,7 @@ MDNSResponder::~MDNSResponder(void) bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress, uint32_t p_u32TTL) { + (void)p_IPAddress; (void)p_u32TTL; // ignored bool bResult = false; @@ -102,82 +102,25 @@ bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress { if (_setHostname(p_pcHostname)) { - - //// select interface - - m_netif = nullptr; - IPAddress ipAddress = p_IPAddress; - - if (!ipAddress.isSet()) - { - - IPAddress sta = WiFi.localIP(); - IPAddress ap = WiFi.softAPIP(); - - if (sta.isSet()) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] STA interface selected\n"))); - ipAddress = sta; - } - else if (ap.isSet()) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] AP interface selected\n"))); - ipAddress = ap; - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] standard interfaces are not up, please specify one in ::begin()\n"))); - return false; - } - - // continue to ensure interface is UP - } - - // check existence of this IP address in the interface list - bool found = false; - m_netif = nullptr; - for (auto a : addrList) - if (ipAddress == a.addr()) - { - if (a.ifUp()) - { - found = true; - m_netif = a.interface(); - break; - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] found interface for IP '%s' but it is not UP\n"), ipAddress.toString().c_str());); - } - if (!found) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] interface defined by IP '%s' not found\n"), ipAddress.toString().c_str());); - return false; - } - - //// done selecting the interface - - if (m_netif->num == STATION_IF) + m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & pEvent) { - - m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & pEvent) + (void) pEvent; + // Ensure that _restart() runs in USER context + schedule_function([this]() { - (void) pEvent; - // Ensure that _restart() runs in USER context - schedule_function([this]() - { - MDNSResponder::_restart(); - }); + MDNSResponder::_restart(); }); + }); - m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & pEvent) + m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & pEvent) + { + (void) pEvent; + // Ensure that _restart() runs in USER context + schedule_function([this]() { - (void) pEvent; - // Ensure that _restart() runs in USER context - schedule_function([this]() - { - MDNSResponder::_restart(); - }); + MDNSResponder::_restart(); }); - } + }); bResult = _restart(); } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.h b/libraries/ESP8266mDNS/src/LEAmDNS.h index fe02560aec..6233d14ac9 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS.h @@ -1203,7 +1203,6 @@ class MDNSResponder MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback; bool m_bPassivModeEnabled; stcProbeInformation m_HostProbeInformation; - CONST netif* m_netif; // network interface to run on /** CONTROL **/ /* MAINTENANCE */ @@ -1260,7 +1259,7 @@ class MDNSResponder const IPAddress _getResponseMulticastInterface() const { - return IPAddress(m_netif->ip_addr); + return IPAddress(IP4_ADDR_ANY); } uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader, diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp index 41e9524aba..40ff53c008 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp @@ -84,9 +84,7 @@ bool MDNSResponder::_process(bool p_bUserContext) } else { - bResult = (m_netif != nullptr) && - (m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running - _updateProbeStatus() && // Probing + bResult = _updateProbeStatus() && // Probing _checkServiceQueryCache(); // Service query cache check } return bResult; @@ -98,9 +96,7 @@ bool MDNSResponder::_process(bool p_bUserContext) bool MDNSResponder::_restart(void) { - return ((m_netif != nullptr) && - (m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running - (_resetProbeStatus(true)) && // Stop and restart probing + return ((_resetProbeStatus(true)) && // Stop and restart probing (_allocUDPContext())); // Restart UDP } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp index d23941ce53..8d1f7e5c81 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp @@ -221,7 +221,7 @@ bool MDNSResponder::_allocUDPContext(void) //TODO: set multicast address (lwip_joingroup() is IPv4 only at the time of writing) multicast_addr.addr = DNS_MQUERY_IPV6_GROUP_INIT; #endif - if (ERR_OK == igmp_joingroup(ip_2_ip4(&m_netif->ip_addr), ip_2_ip4(&multicast_addr))) + if (ERR_OK == igmp_joingroup(IP4_ADDR_ANY4, ip_2_ip4(&multicast_addr))) { m_pUDPContext = new UdpContext; m_pUDPContext->ref(); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp index 7400abec42..3535f0fa71 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp @@ -133,7 +133,7 @@ bool MDNSResponder::_sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParamet #endif DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: Will send to '%s'.\n"), toMulticastAddress.toString().c_str());); bResult = ((_prepareMDNSMessage(p_rSendParameter, fromIPAddress)) && - (m_pUDPContext->send(toMulticastAddress, DNS_MQUERY_PORT))); + (m_pUDPContext->send_multicast_all(toMulticastAddress, DNS_MQUERY_PORT))); DEBUG_EX_ERR(if (!bResult) {