espconn_udp.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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. // sys_timeout(10, espconn_data_sentcb, psent->pespconn);
  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 (1470 < length) {
  85. datalen = 1470;
  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. espconn_data_sent(pudp_sent, ESPCONN_SEND);
  136. if (err > 0)
  137. return ESPCONN_IF;
  138. return err;
  139. } else {
  140. pbuf_free(p);
  141. return ESPCONN_RTE;
  142. }
  143. }
  144. /******************************************************************************
  145. * FunctionName : espconn_udp_sendto
  146. * Description : sent data for UDP
  147. * Parameters : void *arg -- UDP to send
  148. * uint8* psent -- Data to send
  149. * uint16 length -- Length of data to send
  150. * Returns : return espconn error code.
  151. * - ESPCONN_OK. Successful. No error occured.
  152. * - ESPCONN_MEM. Out of memory.
  153. * - ESPCONN_RTE. Could not find route to destination address.
  154. * - More errors could be returned by lower protocol layers.
  155. *******************************************************************************/
  156. err_t ICACHE_FLASH_ATTR
  157. espconn_udp_sendto(void *arg, uint8 *psent, uint16 length)
  158. {
  159. espconn_msg *pudp_sent = arg;
  160. struct udp_pcb *upcb = pudp_sent->pcommon.pcb;
  161. struct espconn *pespconn = pudp_sent->pespconn;
  162. struct pbuf *p, *q ,*p_temp;
  163. struct ip_addr dst_ip;
  164. u16_t dst_port;
  165. u8_t *data = NULL;
  166. u16_t cnt = 0;
  167. u16_t datalen = 0;
  168. u16_t i = 0;
  169. err_t err;
  170. LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d %p\n", __LINE__, length, upcb));
  171. if (pudp_sent == NULL || upcb == NULL || psent == NULL || length == 0) {
  172. return ESPCONN_ARG;
  173. }
  174. if (1470 < length) {
  175. datalen = 1470;
  176. } else {
  177. datalen = length;
  178. }
  179. p = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
  180. LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
  181. if (p != NULL) {
  182. q = p;
  183. while (q != NULL) {
  184. data = (u8_t *)q->payload;
  185. LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, data));
  186. for (i = 0; i < q->len; i++) {
  187. data[i] = ((u8_t *) psent)[cnt++];
  188. }
  189. q = q->next;
  190. }
  191. } else {
  192. return ESPCONN_MEM;
  193. }
  194. dst_port = pespconn->proto.udp->remote_port;
  195. IP4_ADDR(&dst_ip, pespconn->proto.udp->remote_ip[0],
  196. pespconn->proto.udp->remote_ip[1], pespconn->proto.udp->remote_ip[2],
  197. pespconn->proto.udp->remote_ip[3]);
  198. LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %x %d\n", __LINE__, upcb->remote_ip, upcb->remote_port));
  199. struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
  200. struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
  201. if(wifi_get_opmode() == ESPCONN_AP_STA && default_interface == ESPCONN_AP_STA && sta_netif != NULL && ap_netif != NULL)
  202. {
  203. if(netif_is_up(sta_netif) && netif_is_up(ap_netif) && \
  204. ip_addr_isbroadcast(&upcb->remote_ip, sta_netif) && \
  205. ip_addr_isbroadcast(&upcb->remote_ip, ap_netif)) {
  206. p_temp = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
  207. if (pbuf_copy (p_temp,p) != ERR_OK) {
  208. LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sendto: copying to new pbuf failed\n"));
  209. return ESPCONN_ARG;
  210. }
  211. netif_set_default(sta_netif);
  212. err = udp_sendto(upcb, p_temp, &dst_ip, dst_port);
  213. pbuf_free(p_temp);
  214. netif_set_default(ap_netif);
  215. }
  216. }
  217. err = udp_sendto(upcb, p, &dst_ip, dst_port);
  218. if (p->ref != 0) {
  219. pbuf_free(p);
  220. pudp_sent->pcommon.ptrbuf = psent + datalen;
  221. pudp_sent->pcommon.cntr = length - datalen;
  222. if (err == ERR_OK)
  223. espconn_data_sent(pudp_sent, ESPCONN_SENDTO);
  224. if (err > 0)
  225. return ESPCONN_IF;
  226. return err;
  227. } else {
  228. pbuf_free(p);
  229. return ESPCONN_RTE;
  230. }
  231. }
  232. /******************************************************************************
  233. * FunctionName : espconn_udp_server_recv
  234. * Description : This callback will be called when receiving a datagram.
  235. * Parameters : arg -- user supplied argument
  236. * upcb -- the udp_pcb which received data
  237. * p -- the packet buffer that was received
  238. * addr -- the remote IP address from which the packet was received
  239. * port -- the remote port from which the packet was received
  240. * Returns : none
  241. *******************************************************************************/
  242. static void ICACHE_FLASH_ATTR
  243. espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p,
  244. struct ip_addr *addr, u16_t port)
  245. {
  246. espconn_msg *precv = arg;
  247. struct pbuf *q = NULL;
  248. u8_t *pdata = NULL;
  249. u16_t length = 0;
  250. struct ip_info ipconfig;
  251. LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %p\n", __LINE__, upcb));
  252. precv->pcommon.remote_ip[0] = ip4_addr1_16(addr);
  253. precv->pcommon.remote_ip[1] = ip4_addr2_16(addr);
  254. precv->pcommon.remote_ip[2] = ip4_addr3_16(addr);
  255. precv->pcommon.remote_ip[3] = ip4_addr4_16(addr);
  256. precv->pcommon.remote_port = port;
  257. precv->pcommon.pcb = upcb;
  258. if (wifi_get_opmode() != 1) {
  259. wifi_get_ip_info(1, &ipconfig);
  260. if (!ip_addr_netcmp(addr, &ipconfig.ip, &ipconfig.netmask)) {
  261. wifi_get_ip_info(0, &ipconfig);
  262. }
  263. } else {
  264. wifi_get_ip_info(0, &ipconfig);
  265. }
  266. precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&ipconfig.ip);
  267. precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&ipconfig.ip);
  268. precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&ipconfig.ip);
  269. precv->pespconn->proto.udp->local_ip[3] = ip4_addr4_16(&ipconfig.ip);
  270. if (p != NULL) {
  271. pdata = (u8_t *)os_zalloc(p ->tot_len + 1);
  272. length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
  273. precv->pcommon.pcb = upcb;
  274. pbuf_free(p);
  275. if (length != 0) {
  276. if (precv->pespconn->recv_callback != NULL) {
  277. precv->pespconn->recv_callback(precv->pespconn, pdata, length);
  278. }
  279. }
  280. os_free(pdata);
  281. } else {
  282. return;
  283. }
  284. }
  285. /******************************************************************************
  286. * FunctionName : espconn_udp_disconnect
  287. * Description : A new incoming connection has been disconnected.
  288. * Parameters : espconn -- the espconn used to disconnect with host
  289. * Returns : none
  290. *******************************************************************************/
  291. void ICACHE_FLASH_ATTR espconn_udp_disconnect(espconn_msg *pdiscon)
  292. {
  293. if (pdiscon == NULL) {
  294. return;
  295. }
  296. struct udp_pcb *upcb = pdiscon->pcommon.pcb;
  297. udp_disconnect(upcb);
  298. udp_remove(upcb);
  299. espconn_list_delete(&plink_active, pdiscon);
  300. os_free(pdiscon);
  301. pdiscon = NULL;
  302. }
  303. /******************************************************************************
  304. * FunctionName : espconn_udp_server
  305. * Description : Initialize the server: set up a PCB and bind it to the port
  306. * Parameters : pespconn -- the espconn used to build server
  307. * Returns : none
  308. *******************************************************************************/
  309. sint8 ICACHE_FLASH_ATTR
  310. espconn_udp_server(struct espconn *pespconn)
  311. {
  312. struct udp_pcb *upcb = NULL;
  313. espconn_msg *pserver = NULL;
  314. upcb = udp_new();
  315. if (upcb == NULL) {
  316. return ESPCONN_MEM;
  317. } else {
  318. pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
  319. if (pserver == NULL) {
  320. udp_remove(upcb);
  321. return ESPCONN_MEM;
  322. }
  323. pserver->pcommon.pcb = upcb;
  324. pserver->pespconn = pespconn;
  325. espconn_list_creat(&plink_active, pserver);
  326. udp_bind(upcb, IP_ADDR_ANY, pserver->pespconn->proto.udp->local_port);
  327. udp_recv(upcb, espconn_udp_recv, (void *)pserver);
  328. return ESPCONN_OK;
  329. }
  330. }
  331. /******************************************************************************
  332. * FunctionName : espconn_igmp_leave
  333. * Description : leave a multicast group
  334. * Parameters : host_ip -- the ip address of udp server
  335. * multicast_ip -- multicast ip given by user
  336. * Returns : none
  337. *******************************************************************************/
  338. sint8 ICACHE_FLASH_ATTR
  339. espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip)
  340. {
  341. if (igmp_leavegroup(host_ip, multicast_ip) != ERR_OK) {
  342. LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_leave_multigrup failed!\n"));
  343. return -1;
  344. };
  345. return ESPCONN_OK;
  346. }
  347. /******************************************************************************
  348. * FunctionName : espconn_igmp_join
  349. * Description : join a multicast group
  350. * Parameters : host_ip -- the ip address of udp server
  351. * multicast_ip -- multicast ip given by user
  352. * Returns : none
  353. *******************************************************************************/
  354. sint8 ICACHE_FLASH_ATTR
  355. espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip)
  356. {
  357. if (igmp_joingroup(host_ip, multicast_ip) != ERR_OK) {
  358. LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_join_multigrup failed!\n"));
  359. return -1;
  360. };
  361. /* join to any IP address at the port */
  362. return ESPCONN_OK;
  363. }