espconn_udp.c 14 KB

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