tcp_server.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /**
  2. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification,
  6. * are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  17. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  19. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  20. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  21. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  24. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  25. * OF SUCH DAMAGE.
  26. *
  27. * This file is part of and a contribution to the lwIP TCP/IP stack.
  28. *
  29. * Credits go to Adam Dunkels (and the current maintainers) of this software.
  30. *
  31. * Christiaan Simons rewrote this file to get a more stable application.
  32. *
  33. **/
  34. /* This file was modified by ST */
  35. #include "lwip/debug.h"
  36. #include "lwip/stats.h"
  37. #include "lwip/tcp.h"
  38. #if LWIP_TCP
  39. static struct tcp_pcb *tcp_server_pcb;
  40. /* ECHO protocol states */
  41. enum tcp_server_states
  42. {
  43. ES_NONE = 0,
  44. ES_ACCEPTED,
  45. ES_RECEIVED,
  46. ES_CLOSING
  47. };
  48. /* structure for maintaing connection infos to be passed as argument
  49. to LwIP callbacks*/
  50. struct tcp_server_struct
  51. {
  52. u8_t state; /* current connection state */
  53. u8_t retries;
  54. struct tcp_pcb *pcb; /* pointer on the current tcp_pcb */
  55. struct pbuf *p; /* pointer on the received/to be transmitted pbuf */
  56. };
  57. static err_t tcp_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
  58. static err_t tcp_server_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
  59. static void tcp_server_error(void *arg, err_t err);
  60. static err_t tcp_server_poll(void *arg, struct tcp_pcb *tpcb);
  61. static err_t tcp_server_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
  62. static void tcp_server_send(struct tcp_pcb *tpcb, struct tcp_server_struct *es);
  63. static void tcp_server_connection_close(struct tcp_pcb *tpcb, struct tcp_server_struct *es);
  64. /**
  65. * @brief Initializes the tcp server
  66. * @param None
  67. * @retval None
  68. */
  69. void tcp_server_init(void)
  70. {
  71. /* create new tcp pcb */
  72. tcp_server_pcb = tcp_new();
  73. if (tcp_server_pcb != NULL)
  74. {
  75. err_t err;
  76. /* bind _pcb to port 7 (ECHO protocol) */
  77. err = tcp_bind(tcp_server_pcb, IP_ADDR_ANY, 7);
  78. if (err == ERR_OK)
  79. {
  80. /* start tcp listening for _pcb */
  81. tcp_server_pcb = tcp_listen(tcp_server_pcb);
  82. /* initialize LwIP tcp_accept callback function */
  83. tcp_accept(tcp_server_pcb, tcp_server_accept);
  84. }
  85. else
  86. {
  87. /* deallocate the pcb */
  88. memp_free(MEMP_TCP_PCB, tcp_server_pcb);
  89. }
  90. }
  91. }
  92. /**
  93. * @brief This function is the implementation of tcp_accept LwIP callback
  94. * @param arg: not used
  95. * @param newpcb: pointer on tcp_pcb struct for the newly created tcp connection
  96. * @param err: not used
  97. * @retval err_t: error status
  98. */
  99. static err_t tcp_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
  100. {
  101. err_t ret_err;
  102. struct tcp_server_struct *es;
  103. LWIP_UNUSED_ARG(arg);
  104. LWIP_UNUSED_ARG(err);
  105. /* set priority for the newly accepted tcp connection newpcb */
  106. tcp_setprio(newpcb, TCP_PRIO_MIN);
  107. /* allocate structure es to maintain tcp connection informations */
  108. es = (struct tcp_server_struct *)mem_malloc(sizeof(struct tcp_server_struct));
  109. if (es != NULL)
  110. {
  111. es->state = ES_ACCEPTED;
  112. es->pcb = newpcb;
  113. es->retries = 0;
  114. es->p = NULL;
  115. /* pass newly allocated es structure as argument to newpcb */
  116. tcp_arg(newpcb, es);
  117. /* initialize lwip tcp_recv callback function for newpcb */
  118. tcp_recv(newpcb, tcp_server_recv);
  119. /* initialize lwip tcp_err callback function for newpcb */
  120. tcp_err(newpcb, tcp_server_error);
  121. /* initialize lwip tcp_poll callback function for newpcb */
  122. tcp_poll(newpcb, tcp_server_poll, 0);
  123. ret_err = ERR_OK;
  124. }
  125. else
  126. {
  127. /* close tcp connection */
  128. tcp_server_connection_close(newpcb, es);
  129. /* return memory error */
  130. ret_err = ERR_MEM;
  131. }
  132. return ret_err;
  133. }
  134. /**
  135. * @brief This function is the implementation for tcp_recv LwIP callback
  136. * @param arg: pointer on a argument for the tcp_pcb connection
  137. * @param tpcb: pointer on the tcp_pcb connection
  138. * @param pbuf: pointer on the received pbuf
  139. * @param err: error information regarding the reveived pbuf
  140. * @retval err_t: error code
  141. */
  142. static err_t tcp_server_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
  143. {
  144. struct tcp_server_struct *es;
  145. err_t ret_err;
  146. LWIP_ASSERT("arg != NULL",arg != NULL);
  147. es = (struct tcp_server_struct *)arg;
  148. /* if we receive an empty tcp frame from client => close connection */
  149. if (p == NULL)
  150. {
  151. /* remote host closed connection */
  152. es->state = ES_CLOSING;
  153. if(es->p == NULL)
  154. {
  155. /* we're done sending, close connection */
  156. tcp_server_connection_close(tpcb, es);
  157. }
  158. else
  159. {
  160. /* we're not done yet */
  161. /* acknowledge received packet */
  162. tcp_sent(tpcb, tcp_server_sent);
  163. /* send remaining data*/
  164. tcp_server_send(tpcb, es);
  165. }
  166. ret_err = ERR_OK;
  167. }
  168. /* else : a non empty frame was received from client but for some reason err != ERR_OK */
  169. else if(err != ERR_OK)
  170. {
  171. /* free received pbuf*/
  172. if (p != NULL)
  173. {
  174. es->p = NULL;
  175. pbuf_free(p);
  176. }
  177. ret_err = err;
  178. }
  179. else if(es->state == ES_ACCEPTED)
  180. {
  181. /* first data chunk in p->payload */
  182. es->state = ES_RECEIVED;
  183. /* store reference to incoming pbuf (chain) */
  184. es->p = p;
  185. /* initialize LwIP tcp_sent callback function */
  186. tcp_sent(tpcb, tcp_server_sent);
  187. /* send back the received data () */
  188. tcp_server_send(tpcb, es);
  189. ret_err = ERR_OK;
  190. }
  191. else if (es->state == ES_RECEIVED)
  192. {
  193. /* more data received from client and previous data has been already sent*/
  194. if(es->p == NULL)
  195. {
  196. es->p = p;
  197. /*
  198. TODO: Process income data here
  199. */
  200. char aa[128];
  201. memcpy(aa, p->payload, p->len);
  202. aa[p->len] = 0x00;
  203. DEBUG_INFO("Payload: %s\r\n", aa);
  204. /* send back received data */
  205. tcp_server_send(tpcb, es);
  206. }
  207. else
  208. {
  209. struct pbuf *ptr;
  210. /* chain pbufs to the end of what we recv'ed previously */
  211. ptr = es->p;
  212. pbuf_chain(ptr,p);
  213. }
  214. ret_err = ERR_OK;
  215. }
  216. else if(es->state == ES_CLOSING)
  217. {
  218. /* odd case, remote side closing twice, trash data */
  219. tcp_recved(tpcb, p->tot_len);
  220. es->p = NULL;
  221. pbuf_free(p);
  222. ret_err = ERR_OK;
  223. }
  224. else
  225. {
  226. /* unkown es->state, trash data */
  227. tcp_recved(tpcb, p->tot_len);
  228. es->p = NULL;
  229. pbuf_free(p);
  230. ret_err = ERR_OK;
  231. }
  232. return ret_err;
  233. }
  234. /**
  235. * @brief This function implements the tcp_err callback function (called
  236. * when a fatal tcp_connection error occurs.
  237. * @param arg: pointer on argument parameter
  238. * @param err: not used
  239. * @retval None
  240. */
  241. static void tcp_server_error(void *arg, err_t err)
  242. {
  243. struct tcp_server_struct *es;
  244. LWIP_UNUSED_ARG(err);
  245. es = (struct tcp_server_struct *)arg;
  246. if (es != NULL)
  247. {
  248. /* free es structure */
  249. mem_free(es);
  250. }
  251. }
  252. /**
  253. * @brief This function implements the tcp_poll LwIP callback function
  254. * @param arg: pointer on argument passed to callback
  255. * @param tpcb: pointer on the tcp_pcb for the current tcp connection
  256. * @retval err_t: error code
  257. */
  258. static err_t tcp_server_poll(void *arg, struct tcp_pcb *tpcb)
  259. {
  260. err_t ret_err;
  261. struct tcp_server_struct *es;
  262. es = (struct tcp_server_struct *)arg;
  263. if (es != NULL)
  264. {
  265. if (es->p != NULL)
  266. {
  267. tcp_sent(tpcb, tcp_server_sent);
  268. /* there is a remaining pbuf (chain) , try to send data */
  269. DEBUG_INFO("Poll...\r\n");
  270. tcp_server_send(tpcb, es);
  271. }
  272. else
  273. {
  274. /* no remaining pbuf (chain) */
  275. if(es->state == ES_CLOSING)
  276. {
  277. /* close tcp connection */
  278. tcp_server_connection_close(tpcb, es);
  279. }
  280. }
  281. ret_err = ERR_OK;
  282. }
  283. else
  284. {
  285. /* nothing to be done */
  286. tcp_abort(tpcb);
  287. ret_err = ERR_ABRT;
  288. }
  289. return ret_err;
  290. }
  291. /**
  292. * @brief This function implements the tcp_sent LwIP callback (called when ACK
  293. * is received from remote host for sent data)
  294. * @param None
  295. * @retval None
  296. */
  297. static err_t tcp_server_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
  298. {
  299. struct tcp_server_struct *es;
  300. LWIP_UNUSED_ARG(len);
  301. es = (struct tcp_server_struct *)arg;
  302. es->retries = 0;
  303. if(es->p != NULL)
  304. {
  305. /* still got pbufs to send */
  306. tcp_sent(tpcb, tcp_server_sent);
  307. tcp_server_send(tpcb, es);
  308. }
  309. else
  310. {
  311. /* if no more data to send and client closed connection*/
  312. if(es->state == ES_CLOSING)
  313. tcp_server_connection_close(tpcb, es);
  314. }
  315. return ERR_OK;
  316. }
  317. /**
  318. * @brief This function is used to send data for tcp connection
  319. * @param tpcb: pointer on the tcp_pcb connection
  320. * @param es: pointer on _state structure
  321. * @retval None
  322. */
  323. static void tcp_server_send(struct tcp_pcb *tpcb, struct tcp_server_struct *es)
  324. {
  325. struct pbuf *ptr;
  326. err_t wr_err = ERR_OK;
  327. while ((wr_err == ERR_OK) &&
  328. (es->p != NULL) &&
  329. (es->p->len <= tcp_sndbuf(tpcb)))
  330. {
  331. /* get pointer on pbuf from es structure */
  332. ptr = es->p;
  333. /* enqueue data for transmission */
  334. wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
  335. if (wr_err == ERR_OK)
  336. {
  337. u16_t plen;
  338. u8_t freed;
  339. plen = ptr->len;
  340. /* continue with next pbuf in chain (if any) */
  341. es->p = ptr->next;
  342. if(es->p != NULL)
  343. {
  344. /* increment reference count for es->p */
  345. pbuf_ref(es->p);
  346. }
  347. /* chop first pbuf from chain */
  348. do
  349. {
  350. /* try hard to free pbuf */
  351. freed = pbuf_free(ptr);
  352. }
  353. while(freed == 0);
  354. /* we can read more data now */
  355. tcp_recved(tpcb, plen);
  356. }
  357. else if(wr_err == ERR_MEM)
  358. {
  359. /* we are low on memory, try later / harder, defer to poll */
  360. es->p = ptr;
  361. }
  362. else
  363. {
  364. /* other problem ?? */
  365. }
  366. }
  367. }
  368. /**
  369. * @brief This functions closes the tcp connection
  370. * @param tcp_pcb: pointer on the tcp connection
  371. * @param es: pointer on _state structure
  372. * @retval None
  373. */
  374. static void tcp_server_connection_close(struct tcp_pcb *tpcb, struct tcp_server_struct *es)
  375. {
  376. /* remove all callbacks */
  377. tcp_arg(tpcb, NULL);
  378. tcp_sent(tpcb, NULL);
  379. tcp_recv(tpcb, NULL);
  380. tcp_err(tpcb, NULL);
  381. tcp_poll(tpcb, NULL, 0);
  382. /* delete es structure */
  383. if (es != NULL)
  384. {
  385. mem_free(es);
  386. }
  387. /* close tcp connection */
  388. tcp_close(tpcb);
  389. }
  390. #endif /* LWIP_TCP */