]> git.sur5r.net Git - freertos/blob - Demo/lwIP_Demo_Rowley_ARM7/lwip-1.1.0/src/api/api_msg.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / lwIP_Demo_Rowley_ARM7 / lwip-1.1.0 / src / api / api_msg.c
1 /*\r
2  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.\r
3  * All rights reserved. \r
4  * \r
5  * Redistribution and use in source and binary forms, with or without modification, \r
6  * are permitted provided that the following conditions are met:\r
7  *\r
8  * 1. Redistributions of source code must retain the above copyright notice,\r
9  *    this list of conditions and the following disclaimer.\r
10  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
11  *    this list of conditions and the following disclaimer in the documentation\r
12  *    and/or other materials provided with the distribution.\r
13  * 3. The name of the author may not be used to endorse or promote products\r
14  *    derived from this software without specific prior written permission. \r
15  *\r
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED \r
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \r
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT \r
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \r
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \r
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING \r
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY \r
25  * OF SUCH DAMAGE.\r
26  *\r
27  * This file is part of the lwIP TCP/IP stack.\r
28  * \r
29  * Author: Adam Dunkels <adam@sics.se>\r
30  *\r
31  */\r
32 \r
33 #include "lwip/opt.h"\r
34 #include "lwip/arch.h"\r
35 #include "lwip/api_msg.h"\r
36 #include "lwip/memp.h"\r
37 #include "lwip/sys.h"\r
38 #include "lwip/tcpip.h"\r
39 \r
40 #if LWIP_RAW\r
41 static u8_t\r
42 recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,\r
43     struct ip_addr *addr)\r
44 {\r
45   struct netbuf *buf;\r
46   struct netconn *conn;\r
47 \r
48   conn = arg;\r
49   if (!conn) return 0;\r
50 \r
51   if (conn->recvmbox != SYS_MBOX_NULL) {\r
52     if (!(buf = memp_malloc(MEMP_NETBUF))) {\r
53       return 0;\r
54     }\r
55     pbuf_ref(p);\r
56     buf->p = p;\r
57     buf->ptr = p;\r
58     buf->fromaddr = addr;\r
59     buf->fromport = pcb->protocol;\r
60 \r
61     conn->recv_avail += p->tot_len;\r
62     /* Register event with callback */\r
63     if (conn->callback)\r
64         (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);\r
65     sys_mbox_post(conn->recvmbox, buf);\r
66   }\r
67 \r
68   return 0; /* do not eat the packet */\r
69 }\r
70 #endif\r
71 #if LWIP_UDP\r
72 static void\r
73 recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,\r
74    struct ip_addr *addr, u16_t port)\r
75 {\r
76   struct netbuf *buf;\r
77   struct netconn *conn;\r
78 \r
79   (void)pcb;\r
80 \r
81   conn = arg;\r
82   \r
83   if (conn == NULL) {\r
84     pbuf_free(p);\r
85     return;\r
86   }\r
87   if (conn->recvmbox != SYS_MBOX_NULL) {\r
88     buf = memp_malloc(MEMP_NETBUF);\r
89     if (buf == NULL) {\r
90       pbuf_free(p);\r
91       return;\r
92     } else {\r
93       buf->p = p;\r
94       buf->ptr = p;\r
95       buf->fromaddr = addr;\r
96       buf->fromport = port;\r
97     }\r
98 \r
99   conn->recv_avail += p->tot_len;\r
100     /* Register event with callback */\r
101     if (conn->callback)\r
102         (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);\r
103     sys_mbox_post(conn->recvmbox, buf);\r
104   }\r
105 }\r
106 #endif /* LWIP_UDP */\r
107 #if LWIP_TCP\r
108 \r
109 static err_t\r
110 recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)\r
111 {\r
112   struct netconn *conn;\r
113   u16_t len;\r
114 \r
115   (void)pcb;\r
116 \r
117   conn = arg;\r
118 \r
119   if (conn == NULL) {\r
120     pbuf_free(p);\r
121     return ERR_VAL;\r
122   }\r
123 \r
124   if (conn->recvmbox != SYS_MBOX_NULL) {\r
125         \r
126     conn->err = err;\r
127     if (p != NULL) {\r
128         len = p->tot_len;\r
129         conn->recv_avail += len;\r
130     }\r
131     else\r
132         len = 0;\r
133     /* Register event with callback */\r
134     if (conn->callback)\r
135         (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, len);\r
136     sys_mbox_post(conn->recvmbox, p);\r
137   }  \r
138   return ERR_OK;\r
139 }\r
140 \r
141 \r
142 static err_t\r
143 poll_tcp(void *arg, struct tcp_pcb *pcb)\r
144 {\r
145   struct netconn *conn;\r
146 \r
147   (void)pcb;\r
148 \r
149   conn = arg;\r
150   if (conn != NULL &&\r
151      (conn->state == NETCONN_WRITE || conn->state == NETCONN_CLOSE) &&\r
152      conn->sem != SYS_SEM_NULL) {\r
153     sys_sem_signal(conn->sem);\r
154   }\r
155   return ERR_OK;\r
156 }\r
157 \r
158 static err_t\r
159 sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)\r
160 {\r
161   struct netconn *conn;\r
162 \r
163   (void)pcb;\r
164 \r
165   conn = arg;\r
166   if (conn != NULL && conn->sem != SYS_SEM_NULL) {\r
167     sys_sem_signal(conn->sem);\r
168   }\r
169 \r
170   if (conn && conn->callback)\r
171       if (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)\r
172           (*conn->callback)(conn, NETCONN_EVT_SENDPLUS, len);\r
173   \r
174   return ERR_OK;\r
175 }\r
176 \r
177 static void\r
178 err_tcp(void *arg, err_t err)\r
179 {\r
180   struct netconn *conn;\r
181 \r
182   conn = arg;\r
183 \r
184   conn->pcb.tcp = NULL;\r
185 \r
186   \r
187   conn->err = err;\r
188   if (conn->recvmbox != SYS_MBOX_NULL) {\r
189     /* Register event with callback */\r
190     if (conn->callback)\r
191       (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);\r
192     sys_mbox_post(conn->recvmbox, NULL);\r
193   }\r
194   if (conn->mbox != SYS_MBOX_NULL) {\r
195     sys_mbox_post(conn->mbox, NULL);\r
196   }\r
197   if (conn->acceptmbox != SYS_MBOX_NULL) {\r
198      /* Register event with callback */\r
199     if (conn->callback)\r
200       (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);\r
201     sys_mbox_post(conn->acceptmbox, NULL);\r
202   }\r
203   if (conn->sem != SYS_SEM_NULL) {\r
204     sys_sem_signal(conn->sem);\r
205   }\r
206 }\r
207 \r
208 static void\r
209 setup_tcp(struct netconn *conn)\r
210 {\r
211   struct tcp_pcb *pcb;\r
212   \r
213   pcb = conn->pcb.tcp;\r
214   tcp_arg(pcb, conn);\r
215   tcp_recv(pcb, recv_tcp);\r
216   tcp_sent(pcb, sent_tcp);\r
217   tcp_poll(pcb, poll_tcp, 4);\r
218   tcp_err(pcb, err_tcp);\r
219 }\r
220 \r
221 static err_t\r
222 accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)\r
223 {\r
224   sys_mbox_t mbox;\r
225   struct netconn *newconn;\r
226   struct netconn *conn;\r
227   \r
228 #if API_MSG_DEBUG\r
229 #if TCP_DEBUG\r
230   tcp_debug_print_state(newpcb->state);\r
231 #endif /* TCP_DEBUG */\r
232 #endif /* API_MSG_DEBUG */\r
233   conn = (struct netconn *)arg;\r
234   mbox = conn->acceptmbox;\r
235   newconn = memp_malloc(MEMP_NETCONN);\r
236   if (newconn == NULL) {\r
237     return ERR_MEM;\r
238   }\r
239   newconn->type = NETCONN_TCP;\r
240   newconn->pcb.tcp = newpcb;\r
241   setup_tcp(newconn);\r
242   newconn->recvmbox = sys_mbox_new();\r
243   if (newconn->recvmbox == SYS_MBOX_NULL) {\r
244     memp_free(MEMP_NETCONN, newconn);\r
245     return ERR_MEM;\r
246   }\r
247   newconn->mbox = sys_mbox_new();\r
248   if (newconn->mbox == SYS_MBOX_NULL) {\r
249     sys_mbox_free(newconn->recvmbox);\r
250     memp_free(MEMP_NETCONN, newconn);\r
251     return ERR_MEM;\r
252   }\r
253   newconn->sem = sys_sem_new(0);\r
254   if (newconn->sem == SYS_SEM_NULL) {\r
255     sys_mbox_free(newconn->recvmbox);\r
256     sys_mbox_free(newconn->mbox);\r
257     memp_free(MEMP_NETCONN, newconn);\r
258     return ERR_MEM;\r
259   }\r
260   newconn->acceptmbox = SYS_MBOX_NULL;\r
261   newconn->err = err;\r
262   /* Register event with callback */\r
263   if (conn->callback)\r
264   {\r
265     (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);\r
266     /* We have to set the callback here even though\r
267      * the new socket is unknown. Mark the socket as -1. */\r
268     newconn->callback = conn->callback;\r
269     newconn->socket = -1;\r
270   }\r
271   \r
272   sys_mbox_post(mbox, newconn);\r
273   return ERR_OK;\r
274 }\r
275 #endif /* LWIP_TCP */\r
276 \r
277 static void\r
278 do_newconn(struct api_msg_msg *msg)\r
279 {\r
280    if(msg->conn->pcb.tcp != NULL) {\r
281    /* This "new" connection already has a PCB allocated. */\r
282    /* Is this an error condition? Should it be deleted? \r
283       We currently just are happy and return. */\r
284      sys_mbox_post(msg->conn->mbox, NULL);\r
285      return;\r
286    }\r
287 \r
288    msg->conn->err = ERR_OK;\r
289 \r
290    /* Allocate a PCB for this connection */\r
291    switch(msg->conn->type) {\r
292 #if LWIP_RAW\r
293    case NETCONN_RAW:\r
294       msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */\r
295       raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);\r
296      break;\r
297 #endif\r
298 #if LWIP_UDP\r
299    case NETCONN_UDPLITE:\r
300       msg->conn->pcb.udp = udp_new();\r
301       if(msg->conn->pcb.udp == NULL) {\r
302          msg->conn->err = ERR_MEM;\r
303          break;\r
304       }\r
305       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);\r
306       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
307       break;\r
308    case NETCONN_UDPNOCHKSUM:\r
309       msg->conn->pcb.udp = udp_new();\r
310       if(msg->conn->pcb.udp == NULL) {\r
311          msg->conn->err = ERR_MEM;\r
312          break;\r
313       }\r
314       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);\r
315       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
316       break;\r
317    case NETCONN_UDP:\r
318       msg->conn->pcb.udp = udp_new();\r
319       if(msg->conn->pcb.udp == NULL) {\r
320          msg->conn->err = ERR_MEM;\r
321          break;\r
322       }\r
323       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
324       break;\r
325 #endif /* LWIP_UDP */\r
326 #if LWIP_TCP\r
327    case NETCONN_TCP:\r
328       msg->conn->pcb.tcp = tcp_new();\r
329       if(msg->conn->pcb.tcp == NULL) {\r
330          msg->conn->err = ERR_MEM;\r
331          break;\r
332       }\r
333       setup_tcp(msg->conn);\r
334       break;\r
335 #endif\r
336    }\r
337    \r
338   \r
339   sys_mbox_post(msg->conn->mbox, NULL);\r
340 }\r
341 \r
342 \r
343 static void\r
344 do_delconn(struct api_msg_msg *msg)\r
345 {\r
346   if (msg->conn->pcb.tcp != NULL) {\r
347     switch (msg->conn->type) {\r
348 #if LWIP_RAW\r
349     case NETCONN_RAW:\r
350       raw_remove(msg->conn->pcb.raw);\r
351       break;\r
352 #endif\r
353 #if LWIP_UDP\r
354     case NETCONN_UDPLITE:\r
355       /* FALLTHROUGH */\r
356     case NETCONN_UDPNOCHKSUM:\r
357       /* FALLTHROUGH */\r
358     case NETCONN_UDP:\r
359       msg->conn->pcb.udp->recv_arg = NULL;\r
360       udp_remove(msg->conn->pcb.udp);\r
361       break;\r
362 #endif /* LWIP_UDP */\r
363 #if LWIP_TCP      \r
364     case NETCONN_TCP:\r
365       if (msg->conn->pcb.tcp->state == LISTEN) {\r
366   tcp_arg(msg->conn->pcb.tcp, NULL);\r
367   tcp_accept(msg->conn->pcb.tcp, NULL);  \r
368   tcp_close(msg->conn->pcb.tcp);\r
369       } else {\r
370   tcp_arg(msg->conn->pcb.tcp, NULL);\r
371   tcp_sent(msg->conn->pcb.tcp, NULL);\r
372   tcp_recv(msg->conn->pcb.tcp, NULL);  \r
373   tcp_poll(msg->conn->pcb.tcp, NULL, 0);\r
374   tcp_err(msg->conn->pcb.tcp, NULL);\r
375   if (tcp_close(msg->conn->pcb.tcp) != ERR_OK) {\r
376     tcp_abort(msg->conn->pcb.tcp);\r
377   }\r
378       }\r
379 #endif\r
380     default:  \r
381     break;\r
382     }\r
383   }\r
384   /* Trigger select() in socket layer */\r
385   if (msg->conn->callback)\r
386   {\r
387       (*msg->conn->callback)(msg->conn, NETCONN_EVT_RCVPLUS, 0);\r
388       (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDPLUS, 0);\r
389   }\r
390   \r
391   if (msg->conn->mbox != SYS_MBOX_NULL) {\r
392     sys_mbox_post(msg->conn->mbox, NULL);\r
393   }\r
394 }\r
395 \r
396 static void\r
397 do_bind(struct api_msg_msg *msg)\r
398 {\r
399   if (msg->conn->pcb.tcp == NULL) {\r
400     switch (msg->conn->type) {\r
401 #if LWIP_RAW\r
402     case NETCONN_RAW:\r
403       msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */\r
404       raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);\r
405       break;\r
406 #endif\r
407 #if LWIP_UDP\r
408     case NETCONN_UDPLITE:\r
409       msg->conn->pcb.udp = udp_new();\r
410       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);\r
411       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
412       break;\r
413     case NETCONN_UDPNOCHKSUM:\r
414       msg->conn->pcb.udp = udp_new();\r
415       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);\r
416       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
417       break;\r
418     case NETCONN_UDP:\r
419       msg->conn->pcb.udp = udp_new();\r
420       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
421       break;\r
422 #endif /* LWIP_UDP */\r
423 #if LWIP_TCP      \r
424     case NETCONN_TCP:\r
425       msg->conn->pcb.tcp = tcp_new();\r
426       setup_tcp(msg->conn);\r
427 #endif /* LWIP_TCP */\r
428     default:  \r
429     break;\r
430     }\r
431   }\r
432   switch (msg->conn->type) {\r
433 #if LWIP_RAW\r
434   case NETCONN_RAW:\r
435     msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);\r
436     break;\r
437 #endif\r
438 #if LWIP_UDP\r
439   case NETCONN_UDPLITE:\r
440     /* FALLTHROUGH */\r
441   case NETCONN_UDPNOCHKSUM:\r
442     /* FALLTHROUGH */\r
443   case NETCONN_UDP:\r
444     msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);\r
445     break;\r
446 #endif /* LWIP_UDP */\r
447 #if LWIP_TCP\r
448   case NETCONN_TCP:\r
449     msg->conn->err = tcp_bind(msg->conn->pcb.tcp,\r
450             msg->msg.bc.ipaddr, msg->msg.bc.port);\r
451 #endif /* LWIP_TCP */\r
452   default:\r
453     break;\r
454   }\r
455   sys_mbox_post(msg->conn->mbox, NULL);\r
456 }\r
457 #if LWIP_TCP\r
458 \r
459 static err_t\r
460 do_connected(void *arg, struct tcp_pcb *pcb, err_t err)\r
461 {\r
462   struct netconn *conn;\r
463 \r
464   (void)pcb;\r
465 \r
466   conn = arg;\r
467 \r
468   if (conn == NULL) {\r
469     return ERR_VAL;\r
470   }\r
471   \r
472   conn->err = err;\r
473   if (conn->type == NETCONN_TCP && err == ERR_OK) {\r
474     setup_tcp(conn);\r
475   }    \r
476   sys_mbox_post(conn->mbox, NULL);\r
477   return ERR_OK;\r
478 }\r
479 #endif  \r
480 \r
481 static void\r
482 do_connect(struct api_msg_msg *msg)\r
483 {\r
484   if (msg->conn->pcb.tcp == NULL) {\r
485     switch (msg->conn->type) {\r
486 #if LWIP_RAW\r
487     case NETCONN_RAW:\r
488       msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */\r
489       raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);\r
490       break;\r
491 #endif\r
492 #if LWIP_UDP\r
493     case NETCONN_UDPLITE:\r
494       msg->conn->pcb.udp = udp_new();\r
495       if (msg->conn->pcb.udp == NULL) {\r
496   msg->conn->err = ERR_MEM;\r
497   sys_mbox_post(msg->conn->mbox, NULL);\r
498   return;\r
499       }\r
500       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);\r
501       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
502       break;\r
503     case NETCONN_UDPNOCHKSUM:\r
504       msg->conn->pcb.udp = udp_new();\r
505       if (msg->conn->pcb.udp == NULL) {\r
506   msg->conn->err = ERR_MEM;\r
507   sys_mbox_post(msg->conn->mbox, NULL);\r
508   return;\r
509       }\r
510       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);\r
511       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
512       break;\r
513     case NETCONN_UDP:\r
514       msg->conn->pcb.udp = udp_new();\r
515       if (msg->conn->pcb.udp == NULL) {\r
516   msg->conn->err = ERR_MEM;\r
517   sys_mbox_post(msg->conn->mbox, NULL);\r
518   return;\r
519       }\r
520       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
521       break;\r
522 #endif /* LWIP_UDP */\r
523 #if LWIP_TCP      \r
524     case NETCONN_TCP:\r
525       msg->conn->pcb.tcp = tcp_new();      \r
526       if (msg->conn->pcb.tcp == NULL) {\r
527   msg->conn->err = ERR_MEM;\r
528   sys_mbox_post(msg->conn->mbox, NULL);\r
529   return;\r
530       }\r
531 #endif\r
532     default:\r
533       break;\r
534     }\r
535   }\r
536   switch (msg->conn->type) {\r
537 #if LWIP_RAW\r
538   case NETCONN_RAW:\r
539     raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);\r
540     sys_mbox_post(msg->conn->mbox, NULL);\r
541     break;\r
542 #endif\r
543 #if LWIP_UDP\r
544   case NETCONN_UDPLITE:\r
545     /* FALLTHROUGH */\r
546   case NETCONN_UDPNOCHKSUM:\r
547     /* FALLTHROUGH */\r
548   case NETCONN_UDP:\r
549     udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);\r
550     sys_mbox_post(msg->conn->mbox, NULL);\r
551     break;\r
552 #endif \r
553 #if LWIP_TCP      \r
554   case NETCONN_TCP:\r
555     /*    tcp_arg(msg->conn->pcb.tcp, msg->conn);*/\r
556     setup_tcp(msg->conn);\r
557     tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,\r
558     do_connected);\r
559     /*tcp_output(msg->conn->pcb.tcp);*/\r
560 #endif\r
561 \r
562   default:\r
563     break;\r
564   }\r
565 }\r
566 \r
567 static void\r
568 do_disconnect(struct api_msg_msg *msg)\r
569 {\r
570 \r
571   switch (msg->conn->type) {\r
572 #if LWIP_RAW\r
573   case NETCONN_RAW:\r
574     /* Do nothing as connecting is only a helper for upper lwip layers */\r
575     break;\r
576 #endif\r
577 #if LWIP_UDP\r
578   case NETCONN_UDPLITE:\r
579     /* FALLTHROUGH */\r
580   case NETCONN_UDPNOCHKSUM:\r
581     /* FALLTHROUGH */\r
582   case NETCONN_UDP:\r
583     udp_disconnect(msg->conn->pcb.udp);\r
584     break;\r
585 #endif \r
586   case NETCONN_TCP:\r
587     break;\r
588   }\r
589   sys_mbox_post(msg->conn->mbox, NULL);\r
590 }\r
591 \r
592 \r
593 static void\r
594 do_listen(struct api_msg_msg *msg)\r
595 {\r
596   if (msg->conn->pcb.tcp != NULL) {\r
597     switch (msg->conn->type) {\r
598 #if LWIP_RAW\r
599     case NETCONN_RAW:\r
600       LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));\r
601       break;\r
602 #endif\r
603 #if LWIP_UDP\r
604     case NETCONN_UDPLITE:\r
605       /* FALLTHROUGH */\r
606     case NETCONN_UDPNOCHKSUM:\r
607       /* FALLTHROUGH */\r
608     case NETCONN_UDP:\r
609       LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));\r
610       break;\r
611 #endif /* LWIP_UDP */\r
612 #if LWIP_TCP      \r
613     case NETCONN_TCP:\r
614       msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);\r
615       if (msg->conn->pcb.tcp == NULL) {\r
616   msg->conn->err = ERR_MEM;\r
617       } else {\r
618   if (msg->conn->acceptmbox == SYS_MBOX_NULL) {\r
619     msg->conn->acceptmbox = sys_mbox_new();\r
620     if (msg->conn->acceptmbox == SYS_MBOX_NULL) {\r
621       msg->conn->err = ERR_MEM;\r
622       break;\r
623     }\r
624   }\r
625   tcp_arg(msg->conn->pcb.tcp, msg->conn);\r
626   tcp_accept(msg->conn->pcb.tcp, accept_function);\r
627       }\r
628 #endif\r
629     default:\r
630       break;\r
631     }\r
632   }\r
633   sys_mbox_post(msg->conn->mbox, NULL);\r
634 }\r
635 \r
636 static void\r
637 do_accept(struct api_msg_msg *msg)\r
638 {\r
639   if (msg->conn->pcb.tcp != NULL) {\r
640     switch (msg->conn->type) {\r
641 #if LWIP_RAW\r
642     case NETCONN_RAW:\r
643       LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));\r
644       break;\r
645 #endif\r
646 #if LWIP_UDP\r
647     case NETCONN_UDPLITE:\r
648       /* FALLTHROUGH */\r
649     case NETCONN_UDPNOCHKSUM:\r
650       /* FALLTHROUGH */\r
651     case NETCONN_UDP:    \r
652       LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));\r
653       break;\r
654 #endif /* LWIP_UDP */\r
655     case NETCONN_TCP:\r
656       break;\r
657     }\r
658   }\r
659 }\r
660 \r
661 static void\r
662 do_send(struct api_msg_msg *msg)\r
663 {\r
664   if (msg->conn->pcb.tcp != NULL) {\r
665     switch (msg->conn->type) {\r
666 #if LWIP_RAW\r
667     case NETCONN_RAW:\r
668       raw_send(msg->conn->pcb.raw, msg->msg.p);\r
669       break;\r
670 #endif\r
671 #if LWIP_UDP\r
672     case NETCONN_UDPLITE:\r
673       /* FALLTHROUGH */\r
674     case NETCONN_UDPNOCHKSUM:\r
675       /* FALLTHROUGH */\r
676     case NETCONN_UDP:\r
677       udp_send(msg->conn->pcb.udp, msg->msg.p);\r
678       break;\r
679 #endif /* LWIP_UDP */\r
680     case NETCONN_TCP:\r
681       break;\r
682     }\r
683   }\r
684   sys_mbox_post(msg->conn->mbox, NULL);\r
685 }\r
686 \r
687 static void\r
688 do_recv(struct api_msg_msg *msg)\r
689 {\r
690 #if LWIP_TCP\r
691   if (msg->conn->pcb.tcp != NULL) {\r
692     if (msg->conn->type == NETCONN_TCP) {\r
693       tcp_recved(msg->conn->pcb.tcp, msg->msg.len);\r
694     }\r
695   }\r
696 #endif  \r
697   sys_mbox_post(msg->conn->mbox, NULL);\r
698 }\r
699 \r
700 static void\r
701 do_write(struct api_msg_msg *msg)\r
702 {\r
703 #if LWIP_TCP  \r
704   err_t err;\r
705 #endif  \r
706   if (msg->conn->pcb.tcp != NULL) {\r
707     switch (msg->conn->type) {\r
708 #if LWIP_RAW\r
709     case NETCONN_RAW:\r
710       msg->conn->err = ERR_VAL;\r
711       break;\r
712 #endif\r
713 #if LWIP_UDP \r
714     case NETCONN_UDPLITE:\r
715       /* FALLTHROUGH */\r
716     case NETCONN_UDPNOCHKSUM:\r
717       /* FALLTHROUGH */\r
718     case NETCONN_UDP:\r
719       msg->conn->err = ERR_VAL;\r
720       break;\r
721 #endif /* LWIP_UDP */\r
722 #if LWIP_TCP \r
723     case NETCONN_TCP:      \r
724       err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,\r
725                       msg->msg.w.len, msg->msg.w.copy);\r
726       /* This is the Nagle algorithm: inhibit the sending of new TCP\r
727    segments when new outgoing data arrives from the user if any\r
728    previously transmitted data on the connection remains\r
729    unacknowledged. */\r
730       if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL || (msg->conn->pcb.tcp->flags & TF_NODELAY)) ) {\r
731   tcp_output(msg->conn->pcb.tcp);\r
732       }\r
733       msg->conn->err = err;\r
734       if (msg->conn->callback)\r
735           if (err == ERR_OK)\r
736           {\r
737               if (tcp_sndbuf(msg->conn->pcb.tcp) <= TCP_SNDLOWAT)\r
738                   (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDMINUS, msg->msg.w.len);\r
739           }\r
740 #endif\r
741     default:\r
742       break;\r
743     }\r
744   }\r
745   sys_mbox_post(msg->conn->mbox, NULL);\r
746 }\r
747 \r
748 static void\r
749 do_close(struct api_msg_msg *msg)\r
750 {\r
751   err_t err;\r
752 \r
753   err = ERR_OK;\r
754 \r
755   if (msg->conn->pcb.tcp != NULL) {\r
756     switch (msg->conn->type) {\r
757 #if LWIP_RAW\r
758     case NETCONN_RAW:\r
759       break;\r
760 #endif\r
761 #if LWIP_UDP\r
762     case NETCONN_UDPLITE:\r
763       /* FALLTHROUGH */\r
764     case NETCONN_UDPNOCHKSUM:\r
765       /* FALLTHROUGH */\r
766     case NETCONN_UDP:\r
767       break;\r
768 #endif /* LWIP_UDP */\r
769 #if LWIP_TCP\r
770     case NETCONN_TCP:\r
771       if (msg->conn->pcb.tcp->state == LISTEN) {\r
772   err = tcp_close(msg->conn->pcb.tcp);\r
773       }\r
774       msg->conn->err = err;      \r
775 #endif\r
776     default:      \r
777       break;\r
778     }\r
779   }\r
780   sys_mbox_post(msg->conn->mbox, NULL);\r
781 }\r
782 \r
783 typedef void (* api_msg_decode)(struct api_msg_msg *msg);\r
784 static api_msg_decode decode[API_MSG_MAX] = {\r
785   do_newconn,\r
786   do_delconn,\r
787   do_bind,\r
788   do_connect,\r
789   do_disconnect,\r
790   do_listen,\r
791   do_accept,\r
792   do_send,\r
793   do_recv,\r
794   do_write,\r
795   do_close\r
796   };\r
797 void\r
798 api_msg_input(struct api_msg *msg)\r
799 {  \r
800   decode[msg->type](&(msg->msg));\r
801 }\r
802 \r
803 void\r
804 api_msg_post(struct api_msg *msg)\r
805 {\r
806   tcpip_apimsg(msg);\r
807 }\r
808 \r
809 \r
810 \r