MeterLogger
espconn_udp.c
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2013-2014 Espressif Systems (Wuxi)
3  *
4  * FileName: espconn_udp.c
5  *
6  * Description: udp proto interface
7  *
8  * Modification history:
9  * 2014/3/31, v1.0 create this file.
10 *******************************************************************************/
11 
12 #include "ets_sys.h"
13 #include "os_type.h"
14 //#include "os.h"
15 
16 #include "lwip/inet.h"
17 #include "lwip/err.h"
18 #include "lwip/pbuf.h"
19 #include "lwip/mem.h"
20 #include "lwip/tcp_impl.h"
21 #include "lwip/udp.h"
22 
23 #include "lwip/app/espconn_udp.h"
24 
25 #ifdef MEMLEAK_DEBUG
26 static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
27 #endif
28 
31 
32 enum send_opt{
35 };
36 static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn)
37 {
38  if (pespconn == NULL) {
39  return;
40  }
41 
42  if (pespconn->sent_callback != NULL) {
43  pespconn->sent_callback(pespconn);
44  }
45 }
46 
47 static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg, enum send_opt opt)
48 {
49  espconn_msg *psent = arg;
50 
51  if (psent == NULL) {
52  return;
53  }
54 
55  if (psent->pcommon.cntr == 0) {
56  psent->pespconn->state = ESPCONN_CONNECT;
57 // sys_timeout(10, espconn_data_sentcb, psent->pespconn);
59  } else {
60  if (opt == ESPCONN_SEND){
61  espconn_udp_sent(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr);
62  } else {
63  espconn_udp_sendto(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr);
64  }
65  }
66 }
67 
68 /******************************************************************************
69  * FunctionName : espconn_udp_sent
70  * Description : sent data for client or server
71  * Parameters : void *arg -- client or server to send
72  * uint8* psent -- Data to send
73  * uint16 length -- Length of data to send
74  * Returns : return espconn error code.
75  * - ESPCONN_OK. Successful. No error occured.
76  * - ESPCONN_MEM. Out of memory.
77  * - ESPCONN_RTE. Could not find route to destination address.
78  * - More errors could be returned by lower protocol layers.
79 *******************************************************************************/
81 espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
82 {
83  espconn_msg *pudp_sent = arg;
84  struct udp_pcb *upcb = pudp_sent->pcommon.pcb;
85  struct pbuf *p, *q ,*p_temp;
86  u8_t *data = NULL;
87  u16_t cnt = 0;
88  u16_t datalen = 0;
89  u16_t i = 0;
90  err_t err;
91  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d %p\n", __LINE__, length, upcb));
92 
93  if (pudp_sent == NULL || upcb == NULL || psent == NULL || length == 0) {
94  return ESPCONN_ARG;
95  }
96 
97  if (1470 < length) {
98  datalen = 1470;
99  } else {
100  datalen = length;
101  }
102 
103  p = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
104  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
105 
106  if (p != NULL) {
107  q = p;
108 
109  while (q != NULL) {
110  data = (u8_t *)q->payload;
111  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, data));
112 
113  for (i = 0; i < q->len; i++) {
114  data[i] = ((u8_t *) psent)[cnt++];
115  }
116 
117  q = q->next;
118  }
119  } else {
120  return ESPCONN_MEM;
121  }
122 
123  upcb->remote_port = pudp_sent->pespconn->proto.udp->remote_port;
124  IP4_ADDR(&upcb->remote_ip, pudp_sent->pespconn->proto.udp->remote_ip[0],
125  pudp_sent->pespconn->proto.udp->remote_ip[1],
126  pudp_sent->pespconn->proto.udp->remote_ip[2],
127  pudp_sent->pespconn->proto.udp->remote_ip[3]);
128 
129  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %x %d\n", __LINE__, upcb->remote_ip, upcb->remote_port));
130 
131  struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
132  struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
133 
134  if(wifi_get_opmode() == ESPCONN_AP_STA && default_interface == ESPCONN_AP_STA && sta_netif != NULL && ap_netif != NULL)
135  {
136  if(netif_is_up(sta_netif) && netif_is_up(ap_netif) && \
137  ip_addr_isbroadcast(&upcb->remote_ip, sta_netif) && \
138  ip_addr_isbroadcast(&upcb->remote_ip, ap_netif)) {
139 
140  p_temp = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
141  if (pbuf_copy (p_temp,p) != ERR_OK) {
142  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent: copying to new pbuf failed\n"));
143  return ESPCONN_ARG;
144  }
145  netif_set_default(sta_netif);
146  err = udp_send(upcb, p_temp);
147  pbuf_free(p_temp);
148  netif_set_default(ap_netif);
149  }
150  }
151  err = udp_send(upcb, p);
152 
153  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d\n", __LINE__, err));
154 
155  if (p->ref != 0) {
156  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
157  pbuf_free(p);
158  pudp_sent->pcommon.ptrbuf = psent + datalen;
159  pudp_sent->pcommon.cntr = length - datalen;
160  espconn_data_sent(pudp_sent, ESPCONN_SEND);
161  if (err > 0)
162  return ESPCONN_IF;
163  return err;
164  } else {
165  pbuf_free(p);
166  return ESPCONN_RTE;
167  }
168 }
169 
170 /******************************************************************************
171  * FunctionName : espconn_udp_sendto
172  * Description : sent data for UDP
173  * Parameters : void *arg -- UDP to send
174  * uint8* psent -- Data to send
175  * uint16 length -- Length of data to send
176  * Returns : return espconn error code.
177  * - ESPCONN_OK. Successful. No error occured.
178  * - ESPCONN_MEM. Out of memory.
179  * - ESPCONN_RTE. Could not find route to destination address.
180  * - More errors could be returned by lower protocol layers.
181 *******************************************************************************/
183 espconn_udp_sendto(void *arg, uint8 *psent, uint16 length)
184 {
185  espconn_msg *pudp_sent = arg;
186  struct udp_pcb *upcb = pudp_sent->pcommon.pcb;
187  struct espconn *pespconn = pudp_sent->pespconn;
188  struct pbuf *p, *q ,*p_temp;
189  struct ip_addr dst_ip;
190  u16_t dst_port;
191  u8_t *data = NULL;
192  u16_t cnt = 0;
193  u16_t datalen = 0;
194  u16_t i = 0;
195  err_t err;
196  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d %p\n", __LINE__, length, upcb));
197 
198  if (pudp_sent == NULL || upcb == NULL || psent == NULL || length == 0) {
199  return ESPCONN_ARG;
200  }
201 
202  if (1470 < length) {
203  datalen = 1470;
204  } else {
205  datalen = length;
206  }
207 
208  p = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
209  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
210 
211  if (p != NULL) {
212  q = p;
213 
214  while (q != NULL) {
215  data = (u8_t *)q->payload;
216  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, data));
217 
218  for (i = 0; i < q->len; i++) {
219  data[i] = ((u8_t *) psent)[cnt++];
220  }
221 
222  q = q->next;
223  }
224  } else {
225  return ESPCONN_MEM;
226  }
227 
228  dst_port = pespconn->proto.udp->remote_port;
229  IP4_ADDR(&dst_ip, pespconn->proto.udp->remote_ip[0],
230  pespconn->proto.udp->remote_ip[1], pespconn->proto.udp->remote_ip[2],
231  pespconn->proto.udp->remote_ip[3]);
232  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %x %d\n", __LINE__, upcb->remote_ip, upcb->remote_port));
233 
234  struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
235  struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
236 
237  if(wifi_get_opmode() == ESPCONN_AP_STA && default_interface == ESPCONN_AP_STA && sta_netif != NULL && ap_netif != NULL)
238  {
239  if(netif_is_up(sta_netif) && netif_is_up(ap_netif) && \
240  ip_addr_isbroadcast(&upcb->remote_ip, sta_netif) && \
241  ip_addr_isbroadcast(&upcb->remote_ip, ap_netif)) {
242 
243  p_temp = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
244  if (pbuf_copy (p_temp,p) != ERR_OK) {
245  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sendto: copying to new pbuf failed\n"));
246  return ESPCONN_ARG;
247  }
248  netif_set_default(sta_netif);
249  err = udp_sendto(upcb, p_temp, &dst_ip, dst_port);
250  pbuf_free(p_temp);
251  netif_set_default(ap_netif);
252  }
253  }
254  err = udp_sendto(upcb, p, &dst_ip, dst_port);
255 
256  if (p->ref != 0) {
257  pbuf_free(p);
258  pudp_sent->pcommon.ptrbuf = psent + datalen;
259  pudp_sent->pcommon.cntr = length - datalen;
260  if (err == ERR_OK)
261  espconn_data_sent(pudp_sent, ESPCONN_SENDTO);
262 
263  if (err > 0)
264  return ESPCONN_IF;
265  return err;
266  } else {
267  pbuf_free(p);
268  return ESPCONN_RTE;
269  }
270 }
271 
272 /******************************************************************************
273  * FunctionName : espconn_udp_server_recv
274  * Description : This callback will be called when receiving a datagram.
275  * Parameters : arg -- user supplied argument
276  * upcb -- the udp_pcb which received data
277  * p -- the packet buffer that was received
278  * addr -- the remote IP address from which the packet was received
279  * port -- the remote port from which the packet was received
280  * Returns : none
281 *******************************************************************************/
282 static void ICACHE_FLASH_ATTR
283 espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p,
284  struct ip_addr *addr, u16_t port)
285 {
286  espconn_msg *precv = arg;
287  struct pbuf *q = NULL;
288  u8_t *pdata = NULL;
289  u16_t length = 0;
290  struct ip_info ipconfig;
291 
292  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %p\n", __LINE__, upcb));
293 
294  precv->pcommon.remote_ip[0] = ip4_addr1_16(addr);
295  precv->pcommon.remote_ip[1] = ip4_addr2_16(addr);
296  precv->pcommon.remote_ip[2] = ip4_addr3_16(addr);
297  precv->pcommon.remote_ip[3] = ip4_addr4_16(addr);
298  precv->pcommon.remote_port = port;
299  precv->pcommon.pcb = upcb;
300 
301  if (wifi_get_opmode() != 1) {
302  wifi_get_ip_info(1, &ipconfig);
303 
304  if (!ip_addr_netcmp(addr, &ipconfig.ip, &ipconfig.netmask)) {
305  wifi_get_ip_info(0, &ipconfig);
306  }
307  } else {
308  wifi_get_ip_info(0, &ipconfig);
309  }
310 
311  precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&ipconfig.ip);
312  precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&ipconfig.ip);
313  precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&ipconfig.ip);
314  precv->pespconn->proto.udp->local_ip[3] = ip4_addr4_16(&ipconfig.ip);
315 
316  if (p != NULL) {
317  pdata = (u8_t *)os_zalloc(p ->tot_len + 1);
318  length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
319  precv->pcommon.pcb = upcb;
320  pbuf_free(p);
321  if (length != 0) {
322  if (precv->pespconn->recv_callback != NULL) {
323  precv->pespconn->recv_callback(precv->pespconn, pdata, length);
324  }
325  }
326  os_free(pdata);
327  } else {
328  return;
329  }
330 }
331 
332 /******************************************************************************
333  * FunctionName : espconn_udp_disconnect
334  * Description : A new incoming connection has been disconnected.
335  * Parameters : espconn -- the espconn used to disconnect with host
336  * Returns : none
337 *******************************************************************************/
339 {
340  if (pdiscon == NULL) {
341  return;
342  }
343 
344  struct udp_pcb *upcb = pdiscon->pcommon.pcb;
345 
346  udp_disconnect(upcb);
347 
348  udp_remove(upcb);
349 
350  espconn_list_delete(&plink_active, pdiscon);
351 
352  os_free(pdiscon);
353  pdiscon = NULL;
354 }
355 
356 /******************************************************************************
357  * FunctionName : espconn_udp_server
358  * Description : Initialize the server: set up a PCB and bind it to the port
359  * Parameters : pespconn -- the espconn used to build server
360  * Returns : none
361 *******************************************************************************/
363 espconn_udp_server(struct espconn *pespconn)
364 {
365  struct udp_pcb *upcb = NULL;
366  espconn_msg *pserver = NULL;
367  upcb = udp_new();
368 
369  if (upcb == NULL) {
370  return ESPCONN_MEM;
371  } else {
372  pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
373 
374  if (pserver == NULL) {
375  udp_remove(upcb);
376  return ESPCONN_MEM;
377  }
378 
379  pserver->pcommon.pcb = upcb;
380  pserver->pespconn = pespconn;
381  espconn_list_creat(&plink_active, pserver);
382  udp_bind(upcb, IP_ADDR_ANY, pserver->pespconn->proto.udp->local_port);
383  udp_recv(upcb, espconn_udp_recv, (void *)pserver);
384  return ESPCONN_OK;
385  }
386 }
387 
388 /******************************************************************************
389  * FunctionName : espconn_igmp_leave
390  * Description : leave a multicast group
391  * Parameters : host_ip -- the ip address of udp server
392  * multicast_ip -- multicast ip given by user
393  * Returns : none
394 *******************************************************************************/
396 espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip)
397 {
398  if (igmp_leavegroup(host_ip, multicast_ip) != ERR_OK) {
399  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_leave_multigrup failed!\n"));
400  return -1;
401  };
402 
403  return ESPCONN_OK;
404 }
405 
406 /******************************************************************************
407  * FunctionName : espconn_igmp_join
408  * Description : join a multicast group
409  * Parameters : host_ip -- the ip address of udp server
410  * multicast_ip -- multicast ip given by user
411  * Returns : none
412 *******************************************************************************/
414 espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip)
415 {
416  if (igmp_joingroup(host_ip, multicast_ip) != ERR_OK) {
417  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_join_multigrup failed!\n"));
418  return -1;
419  };
420 
421  /* join to any IP address at the port */
422  return ESPCONN_OK;
423 }
send_opt
Definition: espconn_udp.c:32
struct ip_addr ip
Definition: ip_addr.h:248
#define ip4_addr3_16(ipaddr)
Definition: ip_addr.h:228
esp_udp * udp
Definition: espconn.h:106
uint8 default_interface
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
int local_port
Definition: espconn.h:83
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) ICACHE_FLASH_ATTR
Definition: pbuf.c:930
#define ESPCONN_UDP_DEBUG
Definition: espconn_udp.h:5
static void ICACHE_FLASH_ATTR espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
Definition: espconn_udp.c:283
#define ip_addr_netcmp(addr1, addr2, mask)
Definition: ip_addr.h:194
int remote_port
Definition: espconn.h:151
#define ESPCONN_AP_STA
Definition: espconn.h:45
void espconn_list_delete(espconn_msg **phead, espconn_msg *pdelete)
Definition: espconn.c:104
#define NULL
Definition: def.h:47
static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn)
Definition: espconn_udp.c:36
void * pcb
Definition: espconn.h:150
#define ESPCONN_OK
Definition: espconn.h:20
const ip_addr_t ip_addr_any ICACHE_RODATA_ATTR
Definition: ip_addr.c:44
unsigned short uint16
Definition: c_types.h:50
#define ICACHE_FLASH_ATTR
Definition: c_types.h:99
bool wifi_get_ip_info(uint8 if_index, struct ip_info *info)
err_t ICACHE_FLASH_ATTR espconn_udp_sendto(void *arg, uint8 *psent, uint16 length)
Definition: espconn_udp.c:183
Definition: pbuf.h:58
struct netif * eagle_lwip_getif(uint8 index)
uint8 wifi_get_opmode(void)
void ICACHE_FLASH_ATTR espconn_udp_disconnect(espconn_msg *pdiscon)
Definition: espconn_udp.c:338
#define os_zalloc(s)
Definition: mem.h:44
sint8 ICACHE_FLASH_ATTR espconn_udp_server(struct espconn *pespconn)
Definition: espconn_udp.c:363
void espconn_list_creat(espconn_msg **phead, espconn_msg *pinsert)
Definition: espconn.c:76
#define ESPCONN_RTE
Definition: espconn.h:23
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:94
void netif_set_default(struct netif *netif) ICACHE_FLASH_ATTR
Definition: netif.c:431
#define ERR_OK
Definition: err.h:52
comon_pkt pcommon
Definition: espconn.h:170
Definition: pbuf.h:76
#define ESPCONN_ARG
Definition: espconn.h:32
sint8 ICACHE_FLASH_ATTR espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip)
Definition: espconn_udp.c:414
unsigned char uint8
Definition: c_types.h:45
s8_t err_t
Definition: err.h:47
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
Definition: netif.h:139
#define ip4_addr4_16(ipaddr)
Definition: ip_addr.h:229
uint8 remote_ip[4]
Definition: espconn.h:152
int remote_port
Definition: espconn.h:82
#define IP_ADDR_ANY
Definition: ip_addr.h:92
sint8 ICACHE_FLASH_ATTR espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip)
Definition: espconn_udp.c:396
#define os_free(s)
Definition: mem.h:40
uint16 cntr
Definition: espconn.h:158
struct ip_addr netmask
Definition: ip_addr.h:249
u8_t pbuf_free(struct pbuf *p) ICACHE_FLASH_ATTR
Definition: pbuf.c:685
union espconn::@1 proto
uint8 local_ip[4]
Definition: espconn.h:84
#define ESPCONN_IF
Definition: espconn.h:33
#define ip4_addr1_16(ipaddr)
Definition: ip_addr.h:226
enum espconn_state state
Definition: espconn.h:103
unsigned char u8_t
Definition: cc.h:52
uint8 remote_ip[4]
Definition: espconn.h:85
void * payload
Definition: pbuf.h:81
u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset) ICACHE_FLASH_ATTR
Definition: pbuf.c:996
espconn_recv_callback recv_callback
Definition: espconn.h:109
#define ip4_addr2_16(ipaddr)
Definition: ip_addr.h:227
signed char sint8
Definition: c_types.h:47
#define netif_is_up(netif)
Definition: netif.h:286
static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg, enum send_opt opt)
Definition: espconn_udp.c:47
u16_t ref
Definition: pbuf.h:106
err_t ICACHE_FLASH_ATTR espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
Definition: espconn_udp.c:81
struct espconn * pespconn
Definition: espconn.h:169
espconn_sent_callback sent_callback
Definition: espconn.h:110
uint8 * ptrbuf
Definition: espconn.h:157
struct pbuf * pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type) ICACHE_FLASH_ATTR
Definition: pbuf.c:234
unsigned short u16_t
Definition: cc.h:54
espconn_msg * plink_active
Definition: espconn.c:32
#define IP4_ADDR(ipaddr, a, b, c, d)
Definition: ip_addr.h:139
#define ESPCONN_MEM
Definition: espconn.h:21