3 * MDNS Server Networking
7 #include "mdns_networking.h"
10 extern mdns_server_t * _mdns_server;
13 * MDNS Server Networking
17 static struct udp_pcb * _pcb_main = NULL;
19 static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport);
22 * @brief Low level UDP PCB Initialize
24 static esp_err_t _udp_pcb_main_init()
29 _pcb_main = udp_new();
31 return ESP_ERR_NO_MEM;
33 if (udp_bind(_pcb_main, IP_ANY_TYPE, MDNS_SERVICE_PORT) != 0) {
34 udp_remove(_pcb_main);
36 return ESP_ERR_INVALID_STATE;
38 _pcb_main->mcast_ttl = 1;
39 _pcb_main->remote_port = MDNS_SERVICE_PORT;
40 ip_addr_copy(_pcb_main->remote_ip, ip_addr_any_type);
41 udp_recv(_pcb_main, &_udp_recv, _mdns_server);
46 * @brief Low level UDP PCB Free
48 static void _udp_pcb_main_deinit()
51 udp_recv(_pcb_main, NULL, NULL);
52 udp_disconnect(_pcb_main);
53 udp_remove(_pcb_main);
59 * @brief Low level UDP Multicast membership control
61 static esp_err_t _udp_join_group(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, bool join)
63 struct netif * netif = NULL;
66 if (!tcpip_adapter_is_netif_up(tcpip_if)) {
67 // Network interface went down before event propagated, skipping IGMP config
68 return ESP_ERR_INVALID_STATE;
71 esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif);
73 return ESP_ERR_INVALID_ARG;
75 netif = (struct netif *)nif;
77 if (ip_protocol == MDNS_IP_PROTOCOL_V4) {
78 ip_addr_t multicast_addr;
79 IP_ADDR4(&multicast_addr, 224, 0, 0, 251);
82 if (igmp_joingroup_netif(netif, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) {
83 return ESP_ERR_INVALID_STATE;
86 if (igmp_leavegroup_netif(netif, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) {
87 return ESP_ERR_INVALID_STATE;
91 ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000);
94 if (mld6_joingroup_netif(netif, &(multicast_addr.u_addr.ip6))) {
95 return ESP_ERR_INVALID_STATE;
98 if (mld6_leavegroup_netif(netif, &(multicast_addr.u_addr.ip6))) {
99 return ESP_ERR_INVALID_STATE;
107 * @brief the receive callback of the raw udp api. Packets are received here
110 static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport)
115 struct pbuf * this_pb = pb;
117 this_pb->next = NULL;
119 mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t));
121 //missed packet - no memory
126 packet->tcpip_if = TCPIP_ADAPTER_IF_MAX;
127 packet->pb = this_pb;
128 packet->src_port = rport;
129 memcpy(&packet->src, raddr, sizeof(ip_addr_t));
130 packet->dest.type = packet->src.type;
132 if (packet->src.type == IPADDR_TYPE_V4) {
133 packet->ip_protocol = MDNS_IP_PROTOCOL_V4;
134 struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN);
135 packet->dest.u_addr.ip4.addr = iphdr->dest.addr;
137 packet->ip_protocol = MDNS_IP_PROTOCOL_V6;
138 struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN);
139 memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
141 packet->multicast = ip_addr_ismulticast(&(packet->dest));
143 //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces)
144 struct netif * netif = NULL;
146 struct udp_pcb * pcb = NULL;
147 for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
148 pcb = _mdns_server->interfaces[i].pcbs[packet->ip_protocol].pcb;
149 tcpip_adapter_get_netif (i, &nif);
150 netif = (struct netif *)nif;
151 if (pcb && netif && netif == ip_current_input_netif ()) {
152 if (packet->src.type == IPADDR_TYPE_V4) {
153 if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) {
154 //packet source is not in the same subnet
159 packet->tcpip_if = i;
165 if (!pcb || !_mdns_server || !_mdns_server->action_queue
166 || _mdns_send_rx_action(packet) != ESP_OK) {
175 * @brief Check if any of the interfaces is up
177 static bool _udp_pcb_is_in_use(){
179 for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
180 for (p=0; p<MDNS_IP_PROTOCOL_MAX; p++) {
181 if(_mdns_server->interfaces[i].pcbs[p].pcb){
190 * @brief Stop PCB Main code
192 static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
197 mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol];
199 free(_pcb->probe_services);
200 _pcb->state = PCB_OFF;
202 _pcb->probe_ip = false;
203 _pcb->probe_services = NULL;
204 _pcb->probe_services_len = 0;
205 _pcb->probe_running = false;
206 _pcb->failed_probes = 0;
207 _udp_join_group(tcpip_if, ip_protocol, false);
208 if(!_udp_pcb_is_in_use()) {
209 _udp_pcb_main_deinit();
215 * @brief Start PCB Main code
217 static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
219 if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) {
220 return ESP_ERR_INVALID_STATE;
223 esp_err_t err = _udp_join_group(tcpip_if, ip_protocol, true);
228 err = _udp_pcb_main_init();
233 _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb = _pcb_main;
234 _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].failed_probes = 0;
239 struct tcpip_api_call_data call;
240 tcpip_adapter_if_t tcpip_if;
241 mdns_ip_protocol_t ip_protocol;
246 * @brief Start PCB from LwIP thread
248 static err_t _mdns_pcb_init_api(struct tcpip_api_call_data *api_call_msg)
250 mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
251 msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol);
256 * @brief Stop PCB from LwIP thread
258 static err_t _mdns_pcb_deinit_api(struct tcpip_api_call_data *api_call_msg)
260 mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
261 _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol);
267 * Non-static functions below are
269 * - commented in mdns_networking.h header
271 esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
273 mdns_api_call_t msg = {
274 .tcpip_if = tcpip_if,
275 .ip_protocol = ip_protocol
277 tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call_data*)&msg);
281 esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
283 mdns_api_call_t msg = {
284 .tcpip_if = tcpip_if,
285 .ip_protocol = ip_protocol
287 tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call_data*)&msg);
291 size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len)
293 struct netif * netif = NULL;
295 esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif);
296 netif = (struct netif *)nif;
301 struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
305 memcpy((uint8_t *)pbt->payload, data, len);
307 err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif);