Merge branch 'bugfix/mdns_tcpip_threadsafe' into 'master'

mdns: Use LwIP IPC for low-level API calls

See merge request !925
This commit is contained in:
Angus Gratton 2017-08-30 13:28:51 +08:00
commit ef60d73fe4

View file

@ -23,6 +23,8 @@
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "lwip/igmp.h" #include "lwip/igmp.h"
#include "lwip/udp.h" #include "lwip/udp.h"
#include "lwip/tcpip.h"
#include "lwip/priv/tcpip_priv.h"
#include "esp_wifi.h" #include "esp_wifi.h"
#endif #endif
@ -154,6 +156,14 @@ struct mdns_server_s {
} search; } search;
}; };
typedef struct {
struct tcpip_api_call call;
mdns_server_t *server;
uint8_t *data;
size_t len;
esp_err_t err;
} mdns_api_call_t;
#define MDNS_MUTEX_LOCK() xSemaphoreTake(server->lock, portMAX_DELAY) #define MDNS_MUTEX_LOCK() xSemaphoreTake(server->lock, portMAX_DELAY)
#define MDNS_MUTEX_UNLOCK() xSemaphoreGive(server->lock) #define MDNS_MUTEX_UNLOCK() xSemaphoreGive(server->lock)
@ -195,6 +205,56 @@ static void _mdns_server_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb,
} }
} }
/**
* @brief init the network of MDNS server (called in tcpip thread context)
*/
static err_t _mdns_server_init_api(struct tcpip_api_call *api_call_msg)
{
mdns_api_call_t *msg = (mdns_api_call_t*)api_call_msg;
mdns_server_t *server = msg->server;
esp_err_t err = ESP_OK;
tcpip_adapter_ip_info_t if_ip_info;
err = tcpip_adapter_get_ip_info(server->tcpip_if, &if_ip_info);
if (err) {
msg->err = err;
return ERR_OK;
}
ip_addr_t laddr;
IP_ADDR4(&laddr, 224, 0, 0, 251);
ip_addr_t multicast_if_addr = IPADDR4_INIT(if_ip_info.ip.addr);
if (igmp_joingroup((const struct ip4_addr *)&multicast_if_addr.u_addr.ip4, (const struct ip4_addr *)&laddr.u_addr.ip4)) {
msg->err = ESP_ERR_INVALID_STATE;
return ERR_OK;
}
struct udp_pcb * pcb = udp_new();
if (!pcb) {
msg->err = ESP_ERR_NO_MEM;
return ERR_OK;
}
pcb->remote_port = MDNS_SERVICE_PORT;
if (udp_bind(pcb, &multicast_if_addr, pcb->remote_port) != 0) {
udp_remove(pcb);
msg->err = ESP_ERR_INVALID_STATE;
return ERR_OK;
}
pcb->mcast_ttl = 1;
ip_addr_copy(pcb->multicast_ip, multicast_if_addr);
ip_addr_copy(pcb->remote_ip, laddr);
server->pcb = pcb;
udp_recv(pcb, &_mdns_server_recv, server);
msg->err = err;
return ERR_OK;
}
/** /**
* @brief init the network of MDNS server * @brief init the network of MDNS server
* *
@ -207,42 +267,29 @@ static void _mdns_server_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb,
*/ */
esp_err_t _mdns_server_init(mdns_server_t * server) esp_err_t _mdns_server_init(mdns_server_t * server)
{ {
esp_err_t err = ESP_OK; mdns_api_call_t msg = {
.server = server,
tcpip_adapter_ip_info_t if_ip_info; };
err = tcpip_adapter_get_ip_info(server->tcpip_if, &if_ip_info); tcpip_api_call(_mdns_server_init_api, (struct tcpip_api_call*)&msg);
if (err) { return msg.err;
return err;
} }
ip_addr_t laddr; /**
IP_ADDR4(&laddr, 224, 0, 0, 251); * @brief stop the network of MDNS server (called in tcpip thread context)
*/
static err_t _mdns_server_deinit_api(struct tcpip_api_call *api_call_msg)
{
mdns_api_call_t *msg = (mdns_api_call_t*)api_call_msg;
mdns_server_t *server = msg->server;
ip_addr_t multicast_if_addr = IPADDR4_INIT(if_ip_info.ip.addr); if (server->pcb) {
udp_recv(server->pcb, NULL, NULL);
if (igmp_joingroup((const struct ip4_addr *)&multicast_if_addr.u_addr.ip4, (const struct ip4_addr *)&laddr.u_addr.ip4)) { udp_disconnect(server->pcb);
return ESP_ERR_INVALID_STATE; udp_remove(server->pcb);
server->pcb = NULL;
} }
msg->err = ESP_OK;
struct udp_pcb * pcb = udp_new(); return ERR_OK;
if (!pcb) {
return ESP_ERR_NO_MEM;
}
pcb->remote_port = MDNS_SERVICE_PORT;
if (udp_bind(pcb, &multicast_if_addr, pcb->remote_port) != 0) {
udp_remove(pcb);
return ESP_ERR_INVALID_STATE;
}
pcb->mcast_ttl = 1;
ip_addr_copy(pcb->multicast_ip, multicast_if_addr);
ip_addr_copy(pcb->remote_ip, laddr);
server->pcb = pcb;
udp_recv(pcb, &_mdns_server_recv, server);
return err;
} }
/** /**
@ -254,16 +301,39 @@ esp_err_t _mdns_server_init(mdns_server_t * server)
*/ */
esp_err_t _mdns_server_deinit(mdns_server_t * server) esp_err_t _mdns_server_deinit(mdns_server_t * server)
{ {
if (server->pcb) { mdns_api_call_t msg = {
udp_recv(server->pcb, NULL, NULL); .server = server,
udp_disconnect(server->pcb); };
udp_remove(server->pcb); tcpip_api_call(_mdns_server_deinit_api, (struct tcpip_api_call*)&msg);
server->pcb = NULL; return msg.err;
}
return ESP_OK;
} }
#endif #endif
/**
* @brief send packet over UDP (called in tcpip thread context)
*/
static err_t _mdns_server_write_api(struct tcpip_api_call *api_call_msg)
{
mdns_api_call_t *msg = (mdns_api_call_t*)api_call_msg;
mdns_server_t *server = msg->server;
struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, msg->len, PBUF_RAM);
if (pbt == NULL) {
msg->len = 0;
return ERR_OK;
}
uint8_t* dst = (uint8_t *)pbt->payload;
memcpy(dst, msg->data, msg->len);
err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port);
pbuf_free(pbt);
if (err) {
msg->len = 0;
return ERR_OK;
}
return ERR_OK;
}
/** /**
* @brief send packet over UDP * @brief send packet over UDP
* *
@ -273,22 +343,18 @@ esp_err_t _mdns_server_deinit(mdns_server_t * server)
* *
* @return length of sent packet or 0 on error * @return length of sent packet or 0 on error
*/ */
static size_t _mdns_server_write(mdns_server_t * server, uint8_t * data, size_t len) static size_t _mdns_server_write(mdns_server_t * server, uint8_t * data, size_t len) {
{
#ifndef MDNS_TEST_MODE #ifndef MDNS_TEST_MODE
struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); mdns_api_call_t msg = {
if (pbt == NULL) { .server = server,
return 0; .data = data,
} .len = len,
uint8_t* dst = (uint8_t *)pbt->payload; };
memcpy(dst, data, len); tcpip_api_call(_mdns_server_write_api, (struct tcpip_api_call*)&msg);
err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port); return msg.len;
pbuf_free(pbt); #else
if (err) {
return 0;
}
#endif
return len; return len;
#endif
} }
/* /*