]> git.sur5r.net Git - freertos/blob - Demo/Common/ethernet/lwIP/api/api_msg.c
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@82 1d2547de-c912-0410-9cb9...
[freertos] / Demo / Common / ethernet / lwIP / 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   conn = arg;\r
80   \r
81   if (conn == NULL) {\r
82     pbuf_free(p);\r
83     return;\r
84   }\r
85   if (conn->recvmbox != SYS_MBOX_NULL) {\r
86     buf = memp_malloc(MEMP_NETBUF);\r
87     if (buf == NULL) {\r
88       pbuf_free(p);\r
89       return;\r
90     } else {\r
91       buf->p = p;\r
92       buf->ptr = p;\r
93       buf->fromaddr = addr;\r
94       buf->fromport = port;\r
95     }\r
96 \r
97   conn->recv_avail += p->tot_len;\r
98     /* Register event with callback */\r
99     if (conn->callback)\r
100         (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);\r
101     sys_mbox_post(conn->recvmbox, buf);\r
102   }\r
103 }\r
104 #endif /* LWIP_UDP */\r
105 #if LWIP_TCP\r
106 \r
107 static err_t\r
108 recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)\r
109 {\r
110   struct netconn *conn;\r
111   u16_t len;\r
112   \r
113   conn = arg;\r
114 \r
115   if (conn == NULL) {\r
116     pbuf_free(p);\r
117     return ERR_VAL;\r
118   }\r
119 \r
120   if (conn->recvmbox != SYS_MBOX_NULL) {\r
121         \r
122     conn->err = err;\r
123     if (p != NULL) {\r
124         len = p->tot_len;\r
125         conn->recv_avail += len;\r
126     }\r
127     else\r
128         len = 0;\r
129     /* Register event with callback */\r
130     if (conn->callback)\r
131         (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, len);\r
132     sys_mbox_post(conn->recvmbox, p);\r
133   }  \r
134   return ERR_OK;\r
135 }\r
136 \r
137 \r
138 static err_t\r
139 poll_tcp(void *arg, struct tcp_pcb *pcb)\r
140 {\r
141   struct netconn *conn;\r
142 \r
143   conn = arg;\r
144   if (conn != NULL &&\r
145      (conn->state == NETCONN_WRITE || conn->state == NETCONN_CLOSE) &&\r
146      conn->sem != SYS_SEM_NULL) {\r
147     sys_sem_signal(conn->sem);\r
148   }\r
149   return ERR_OK;\r
150 }\r
151 \r
152 static err_t\r
153 sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)\r
154 {\r
155   struct netconn *conn;\r
156 \r
157   conn = arg;\r
158   if (conn != NULL && conn->sem != SYS_SEM_NULL) {\r
159     sys_sem_signal(conn->sem);\r
160   }\r
161 \r
162   if (conn && conn->callback)\r
163       if (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)\r
164           (*conn->callback)(conn, NETCONN_EVT_SENDPLUS, len);\r
165   \r
166   return ERR_OK;\r
167 }\r
168 \r
169 static void\r
170 err_tcp(void *arg, err_t err)\r
171 {\r
172   struct netconn *conn;\r
173 \r
174   conn = arg;\r
175 \r
176   conn->pcb.tcp = NULL;\r
177 \r
178   \r
179   conn->err = err;\r
180   if (conn->recvmbox != SYS_MBOX_NULL) {\r
181     /* Register event with callback */\r
182     if (conn->callback)\r
183       (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);\r
184     sys_mbox_post(conn->recvmbox, NULL);\r
185   }\r
186   if (conn->mbox != SYS_MBOX_NULL) {\r
187     sys_mbox_post(conn->mbox, NULL);\r
188   }\r
189   if (conn->acceptmbox != SYS_MBOX_NULL) {\r
190      /* Register event with callback */\r
191     if (conn->callback)\r
192       (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);\r
193     sys_mbox_post(conn->acceptmbox, NULL);\r
194   }\r
195   if (conn->sem != SYS_SEM_NULL) {\r
196     sys_sem_signal(conn->sem);\r
197   }\r
198 }\r
199 \r
200 static void\r
201 setup_tcp(struct netconn *conn)\r
202 {\r
203   struct tcp_pcb *pcb;\r
204   \r
205   pcb = conn->pcb.tcp;\r
206   tcp_arg(pcb, conn);\r
207   tcp_recv(pcb, recv_tcp);\r
208   tcp_sent(pcb, sent_tcp);\r
209   tcp_poll(pcb, poll_tcp, 4);\r
210   tcp_err(pcb, err_tcp);\r
211 }\r
212 \r
213 static err_t\r
214 accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)\r
215 {\r
216   sys_mbox_t mbox;\r
217   struct netconn *newconn;\r
218   struct netconn *conn;\r
219   \r
220 #if API_MSG_DEBUG\r
221 #if TCP_DEBUG\r
222   tcp_debug_print_state(newpcb->state);\r
223 #endif /* TCP_DEBUG */\r
224 #endif /* API_MSG_DEBUG */\r
225   conn = (struct netconn *)arg;\r
226   mbox = conn->acceptmbox;\r
227   newconn = memp_malloc(MEMP_NETCONN);\r
228   if (newconn == NULL) {\r
229     return ERR_MEM;\r
230   }\r
231   newconn->recvmbox = sys_mbox_new();\r
232   if (newconn->recvmbox == SYS_MBOX_NULL) {\r
233     memp_free(MEMP_NETCONN, newconn);\r
234     return ERR_MEM;\r
235   }\r
236   newconn->mbox = sys_mbox_new();\r
237   if (newconn->mbox == SYS_MBOX_NULL) {\r
238     sys_mbox_free(newconn->recvmbox);\r
239     memp_free(MEMP_NETCONN, newconn);\r
240     return ERR_MEM;\r
241   }\r
242   newconn->sem = sys_sem_new(0);\r
243   if (newconn->sem == SYS_SEM_NULL) {\r
244     sys_mbox_free(newconn->recvmbox);\r
245     sys_mbox_free(newconn->mbox);\r
246     memp_free(MEMP_NETCONN, newconn);\r
247     return ERR_MEM;\r
248   }\r
249   /* Allocations were OK, setup the PCB etc */\r
250   newconn->type = NETCONN_TCP;\r
251   newconn->pcb.tcp = newpcb;\r
252   setup_tcp(newconn);\r
253   newconn->acceptmbox = SYS_MBOX_NULL;\r
254   newconn->err = err;\r
255   /* Register event with callback */\r
256   if (conn->callback)\r
257   {\r
258     (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);\r
259   }\r
260   /* We have to set the callback here even though\r
261    * the new socket is unknown. Mark the socket as -1. */\r
262   newconn->callback = conn->callback;\r
263   newconn->socket = -1;\r
264   newconn->recv_avail = 0;\r
265   \r
266   sys_mbox_post(mbox, newconn);\r
267   return ERR_OK;\r
268 }\r
269 #endif /* LWIP_TCP */\r
270 \r
271 static void\r
272 do_newconn(struct api_msg_msg *msg)\r
273 {\r
274    if(msg->conn->pcb.tcp != NULL) {\r
275    /* This "new" connection already has a PCB allocated. */\r
276    /* Is this an error condition? Should it be deleted? \r
277       We currently just are happy and return. */\r
278      sys_mbox_post(msg->conn->mbox, NULL);\r
279      return;\r
280    }\r
281 \r
282    msg->conn->err = ERR_OK;\r
283 \r
284    /* Allocate a PCB for this connection */\r
285    switch(msg->conn->type) {\r
286 #if LWIP_RAW\r
287    case NETCONN_RAW:\r
288       msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */\r
289       raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);\r
290      break;\r
291 #endif\r
292 #if LWIP_UDP\r
293    case NETCONN_UDPLITE:\r
294       msg->conn->pcb.udp = udp_new();\r
295       if(msg->conn->pcb.udp == NULL) {\r
296          msg->conn->err = ERR_MEM;\r
297          break;\r
298       }\r
299       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);\r
300       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
301       break;\r
302    case NETCONN_UDPNOCHKSUM:\r
303       msg->conn->pcb.udp = udp_new();\r
304       if(msg->conn->pcb.udp == NULL) {\r
305          msg->conn->err = ERR_MEM;\r
306          break;\r
307       }\r
308       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);\r
309       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
310       break;\r
311    case NETCONN_UDP:\r
312       msg->conn->pcb.udp = udp_new();\r
313       if(msg->conn->pcb.udp == NULL) {\r
314          msg->conn->err = ERR_MEM;\r
315          break;\r
316       }\r
317       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
318       break;\r
319 #endif /* LWIP_UDP */\r
320 #if LWIP_TCP\r
321    case NETCONN_TCP:\r
322       msg->conn->pcb.tcp = tcp_new();\r
323       if(msg->conn->pcb.tcp == NULL) {\r
324          msg->conn->err = ERR_MEM;\r
325          break;\r
326       }\r
327       setup_tcp(msg->conn);\r
328       break;\r
329 #endif\r
330    }\r
331    \r
332   \r
333   sys_mbox_post(msg->conn->mbox, NULL);\r
334 }\r
335 \r
336 \r
337 static void\r
338 do_delconn(struct api_msg_msg *msg)\r
339 {\r
340   if (msg->conn->pcb.tcp != NULL) {\r
341     switch (msg->conn->type) {\r
342 #if LWIP_RAW\r
343     case NETCONN_RAW:\r
344       raw_remove(msg->conn->pcb.raw);\r
345       break;\r
346 #endif\r
347 #if LWIP_UDP\r
348     case NETCONN_UDPLITE:\r
349       /* FALLTHROUGH */\r
350     case NETCONN_UDPNOCHKSUM:\r
351       /* FALLTHROUGH */\r
352     case NETCONN_UDP:\r
353       msg->conn->pcb.udp->recv_arg = NULL;\r
354       udp_remove(msg->conn->pcb.udp);\r
355       break;\r
356 #endif /* LWIP_UDP */\r
357 #if LWIP_TCP      \r
358     case NETCONN_TCP:\r
359       if (msg->conn->pcb.tcp->state == LISTEN) {\r
360   tcp_arg(msg->conn->pcb.tcp, NULL);\r
361   tcp_accept(msg->conn->pcb.tcp, NULL);  \r
362   tcp_close(msg->conn->pcb.tcp);\r
363       } else {\r
364   tcp_arg(msg->conn->pcb.tcp, NULL);\r
365   tcp_sent(msg->conn->pcb.tcp, NULL);\r
366   tcp_recv(msg->conn->pcb.tcp, NULL);  \r
367   tcp_poll(msg->conn->pcb.tcp, NULL, 0);\r
368   tcp_err(msg->conn->pcb.tcp, NULL);\r
369   if (tcp_close(msg->conn->pcb.tcp) != ERR_OK) {\r
370     tcp_abort(msg->conn->pcb.tcp);\r
371   }\r
372       }\r
373 #endif\r
374     default:  \r
375     break;\r
376     }\r
377   }\r
378   /* Trigger select() in socket layer */\r
379   if (msg->conn->callback)\r
380   {\r
381       (*msg->conn->callback)(msg->conn, NETCONN_EVT_RCVPLUS, 0);\r
382       (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDPLUS, 0);\r
383   }\r
384   \r
385   if (msg->conn->mbox != SYS_MBOX_NULL) {\r
386     sys_mbox_post(msg->conn->mbox, NULL);\r
387   }\r
388 }\r
389 \r
390 static void\r
391 do_bind(struct api_msg_msg *msg)\r
392 {\r
393   if (msg->conn->pcb.tcp == NULL) {\r
394     switch (msg->conn->type) {\r
395 #if LWIP_RAW\r
396     case NETCONN_RAW:\r
397       msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */\r
398       raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);\r
399       break;\r
400 #endif\r
401 #if LWIP_UDP\r
402     case NETCONN_UDPLITE:\r
403       msg->conn->pcb.udp = udp_new();\r
404       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);\r
405       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
406       break;\r
407     case NETCONN_UDPNOCHKSUM:\r
408       msg->conn->pcb.udp = udp_new();\r
409       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);\r
410       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
411       break;\r
412     case NETCONN_UDP:\r
413       msg->conn->pcb.udp = udp_new();\r
414       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
415       break;\r
416 #endif /* LWIP_UDP */\r
417 #if LWIP_TCP      \r
418     case NETCONN_TCP:\r
419       msg->conn->pcb.tcp = tcp_new();\r
420       setup_tcp(msg->conn);\r
421 #endif /* LWIP_TCP */\r
422     default:  \r
423     break;\r
424     }\r
425   }\r
426   switch (msg->conn->type) {\r
427 #if LWIP_RAW\r
428   case NETCONN_RAW:\r
429     msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);\r
430     break;\r
431 #endif\r
432 #if LWIP_UDP\r
433   case NETCONN_UDPLITE:\r
434     /* FALLTHROUGH */\r
435   case NETCONN_UDPNOCHKSUM:\r
436     /* FALLTHROUGH */\r
437   case NETCONN_UDP:\r
438     msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);\r
439     break;\r
440 #endif /* LWIP_UDP */\r
441 #if LWIP_TCP\r
442   case NETCONN_TCP:\r
443     msg->conn->err = tcp_bind(msg->conn->pcb.tcp,\r
444             msg->msg.bc.ipaddr, msg->msg.bc.port);\r
445 #endif /* LWIP_TCP */\r
446   default:\r
447     break;\r
448   }\r
449   sys_mbox_post(msg->conn->mbox, NULL);\r
450 }\r
451 #if LWIP_TCP\r
452 \r
453 static err_t\r
454 do_connected(void *arg, struct tcp_pcb *pcb, err_t err)\r
455 {\r
456   struct netconn *conn;\r
457 \r
458   conn = arg;\r
459 \r
460   if (conn == NULL) {\r
461     return ERR_VAL;\r
462   }\r
463   \r
464   conn->err = err;\r
465   if (conn->type == NETCONN_TCP && err == ERR_OK) {\r
466     setup_tcp(conn);\r
467   }    \r
468   sys_mbox_post(conn->mbox, NULL);\r
469   return ERR_OK;\r
470 }\r
471 #endif  \r
472 \r
473 static void\r
474 do_connect(struct api_msg_msg *msg)\r
475 {\r
476   if (msg->conn->pcb.tcp == NULL) {\r
477     switch (msg->conn->type) {\r
478 #if LWIP_RAW\r
479     case NETCONN_RAW:\r
480       msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */\r
481       raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);\r
482       break;\r
483 #endif\r
484 #if LWIP_UDP\r
485     case NETCONN_UDPLITE:\r
486       msg->conn->pcb.udp = udp_new();\r
487       if (msg->conn->pcb.udp == NULL) {\r
488   msg->conn->err = ERR_MEM;\r
489   sys_mbox_post(msg->conn->mbox, NULL);\r
490   return;\r
491       }\r
492       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);\r
493       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
494       break;\r
495     case NETCONN_UDPNOCHKSUM:\r
496       msg->conn->pcb.udp = udp_new();\r
497       if (msg->conn->pcb.udp == NULL) {\r
498   msg->conn->err = ERR_MEM;\r
499   sys_mbox_post(msg->conn->mbox, NULL);\r
500   return;\r
501       }\r
502       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);\r
503       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
504       break;\r
505     case NETCONN_UDP:\r
506       msg->conn->pcb.udp = udp_new();\r
507       if (msg->conn->pcb.udp == NULL) {\r
508   msg->conn->err = ERR_MEM;\r
509   sys_mbox_post(msg->conn->mbox, NULL);\r
510   return;\r
511       }\r
512       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);\r
513       break;\r
514 #endif /* LWIP_UDP */\r
515 #if LWIP_TCP      \r
516     case NETCONN_TCP:\r
517       msg->conn->pcb.tcp = tcp_new();      \r
518       if (msg->conn->pcb.tcp == NULL) {\r
519   msg->conn->err = ERR_MEM;\r
520   sys_mbox_post(msg->conn->mbox, NULL);\r
521   return;\r
522       }\r
523 #endif\r
524     default:\r
525       break;\r
526     }\r
527   }\r
528   switch (msg->conn->type) {\r
529 #if LWIP_RAW\r
530   case NETCONN_RAW:\r
531     raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);\r
532     sys_mbox_post(msg->conn->mbox, NULL);\r
533     break;\r
534 #endif\r
535 #if LWIP_UDP\r
536   case NETCONN_UDPLITE:\r
537     /* FALLTHROUGH */\r
538   case NETCONN_UDPNOCHKSUM:\r
539     /* FALLTHROUGH */\r
540   case NETCONN_UDP:\r
541     udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);\r
542     sys_mbox_post(msg->conn->mbox, NULL);\r
543     break;\r
544 #endif \r
545 #if LWIP_TCP      \r
546   case NETCONN_TCP:\r
547     /*    tcp_arg(msg->conn->pcb.tcp, msg->conn);*/\r
548     setup_tcp(msg->conn);\r
549     tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,\r
550     do_connected);\r
551     /*tcp_output(msg->conn->pcb.tcp);*/\r
552 #endif\r
553 \r
554   default:\r
555     break;\r
556   }\r
557 }\r
558 \r
559 static void\r
560 do_disconnect(struct api_msg_msg *msg)\r
561 {\r
562 \r
563   switch (msg->conn->type) {\r
564 #if LWIP_RAW\r
565   case NETCONN_RAW:\r
566     /* Do nothing as connecting is only a helper for upper lwip layers */\r
567     break;\r
568 #endif\r
569 #if LWIP_UDP\r
570   case NETCONN_UDPLITE:\r
571     /* FALLTHROUGH */\r
572   case NETCONN_UDPNOCHKSUM:\r
573     /* FALLTHROUGH */\r
574   case NETCONN_UDP:\r
575     udp_disconnect(msg->conn->pcb.udp);\r
576     break;\r
577 #endif \r
578   case NETCONN_TCP:\r
579     break;\r
580   }\r
581   sys_mbox_post(msg->conn->mbox, NULL);\r
582 }\r
583 \r
584 \r
585 static void\r
586 do_listen(struct api_msg_msg *msg)\r
587 {\r
588   if (msg->conn->pcb.tcp != NULL) {\r
589     switch (msg->conn->type) {\r
590 #if LWIP_RAW\r
591     case NETCONN_RAW:\r
592       LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));\r
593       break;\r
594 #endif\r
595 #if LWIP_UDP\r
596     case NETCONN_UDPLITE:\r
597       /* FALLTHROUGH */\r
598     case NETCONN_UDPNOCHKSUM:\r
599       /* FALLTHROUGH */\r
600     case NETCONN_UDP:\r
601       LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));\r
602       break;\r
603 #endif /* LWIP_UDP */\r
604 #if LWIP_TCP      \r
605     case NETCONN_TCP:\r
606       msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);\r
607       if (msg->conn->pcb.tcp == NULL) {\r
608   msg->conn->err = ERR_MEM;\r
609       } else {\r
610   if (msg->conn->acceptmbox == SYS_MBOX_NULL) {\r
611     msg->conn->acceptmbox = sys_mbox_new();\r
612     if (msg->conn->acceptmbox == SYS_MBOX_NULL) {\r
613       msg->conn->err = ERR_MEM;\r
614       break;\r
615     }\r
616   }\r
617   tcp_arg(msg->conn->pcb.tcp, msg->conn);\r
618   tcp_accept(msg->conn->pcb.tcp, accept_function);\r
619       }\r
620 #endif\r
621     default:\r
622       break;\r
623     }\r
624   }\r
625   sys_mbox_post(msg->conn->mbox, NULL);\r
626 }\r
627 \r
628 static void\r
629 do_accept(struct api_msg_msg *msg)\r
630 {\r
631   if (msg->conn->pcb.tcp != NULL) {\r
632     switch (msg->conn->type) {\r
633 #if LWIP_RAW\r
634     case NETCONN_RAW:\r
635       LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));\r
636       break;\r
637 #endif\r
638 #if LWIP_UDP\r
639     case NETCONN_UDPLITE:\r
640       /* FALLTHROUGH */\r
641     case NETCONN_UDPNOCHKSUM:\r
642       /* FALLTHROUGH */\r
643     case NETCONN_UDP:    \r
644       LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));\r
645       break;\r
646 #endif /* LWIP_UDP */\r
647     case NETCONN_TCP:\r
648       break;\r
649     }\r
650   }\r
651 }\r
652 \r
653 static void\r
654 do_send(struct api_msg_msg *msg)\r
655 {\r
656   if (msg->conn->pcb.tcp != NULL) {\r
657     switch (msg->conn->type) {\r
658 #if LWIP_RAW\r
659     case NETCONN_RAW:\r
660       raw_send(msg->conn->pcb.raw, msg->msg.p);\r
661       break;\r
662 #endif\r
663 #if LWIP_UDP\r
664     case NETCONN_UDPLITE:\r
665       /* FALLTHROUGH */\r
666     case NETCONN_UDPNOCHKSUM:\r
667       /* FALLTHROUGH */\r
668     case NETCONN_UDP:\r
669       udp_send(msg->conn->pcb.udp, msg->msg.p);\r
670       break;\r
671 #endif /* LWIP_UDP */\r
672     case NETCONN_TCP:\r
673       break;\r
674     }\r
675   }\r
676   sys_mbox_post(msg->conn->mbox, NULL);\r
677 }\r
678 \r
679 static void\r
680 do_recv(struct api_msg_msg *msg)\r
681 {\r
682 #if LWIP_TCP\r
683   if (msg->conn->pcb.tcp != NULL) {\r
684     if (msg->conn->type == NETCONN_TCP) {\r
685       tcp_recved(msg->conn->pcb.tcp, msg->msg.len);\r
686     }\r
687   }\r
688 #endif  \r
689   sys_mbox_post(msg->conn->mbox, NULL);\r
690 }\r
691 \r
692 static void\r
693 do_write(struct api_msg_msg *msg)\r
694 {\r
695 #if LWIP_TCP  \r
696   err_t err;\r
697 #endif  \r
698   if (msg->conn->pcb.tcp != NULL) {\r
699     switch (msg->conn->type) {\r
700 #if LWIP_RAW\r
701     case NETCONN_RAW:\r
702       msg->conn->err = ERR_VAL;\r
703       break;\r
704 #endif\r
705 #if LWIP_UDP \r
706     case NETCONN_UDPLITE:\r
707       /* FALLTHROUGH */\r
708     case NETCONN_UDPNOCHKSUM:\r
709       /* FALLTHROUGH */\r
710     case NETCONN_UDP:\r
711       msg->conn->err = ERR_VAL;\r
712       break;\r
713 #endif /* LWIP_UDP */\r
714 #if LWIP_TCP \r
715     case NETCONN_TCP:      \r
716       err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,\r
717                       msg->msg.w.len, msg->msg.w.copy);\r
718       /* This is the Nagle algorithm: inhibit the sending of new TCP\r
719    segments when new outgoing data arrives from the user if any\r
720    previously transmitted data on the connection remains\r
721    unacknowledged. */\r
722       if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL ||\r
723         (msg->conn->pcb.tcp->flags & TF_NODELAY) || \r
724         (msg->conn->pcb.tcp->snd_queuelen) > 1)) {\r
725           tcp_output(msg->conn->pcb.tcp);\r
726       }\r
727       msg->conn->err = err;\r
728       if (msg->conn->callback)\r
729           if (err == ERR_OK)\r
730           {\r
731               if (tcp_sndbuf(msg->conn->pcb.tcp) <= TCP_SNDLOWAT)\r
732                   (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDMINUS, msg->msg.w.len);\r
733           }\r
734 #endif\r
735     default:\r
736       break;\r
737     }\r
738   }\r
739   sys_mbox_post(msg->conn->mbox, NULL);\r
740 }\r
741 \r
742 static void\r
743 do_close(struct api_msg_msg *msg)\r
744 {\r
745   err_t err;\r
746 \r
747   err = ERR_OK;\r
748 \r
749   if (msg->conn->pcb.tcp != NULL) {\r
750     switch (msg->conn->type) {\r
751 #if LWIP_RAW\r
752     case NETCONN_RAW:\r
753       break;\r
754 #endif\r
755 #if LWIP_UDP\r
756     case NETCONN_UDPLITE:\r
757       /* FALLTHROUGH */\r
758     case NETCONN_UDPNOCHKSUM:\r
759       /* FALLTHROUGH */\r
760     case NETCONN_UDP:\r
761       break;\r
762 #endif /* LWIP_UDP */\r
763 #if LWIP_TCP\r
764     case NETCONN_TCP:\r
765       if (msg->conn->pcb.tcp->state == LISTEN) {\r
766         err = tcp_close(msg->conn->pcb.tcp);\r
767       }\r
768       else if (msg->conn->pcb.tcp->state == CLOSE_WAIT) {\r
769         err = tcp_output(msg->conn->pcb.tcp);\r
770       }\r
771       msg->conn->err = err;      \r
772 #endif\r
773     default:      \r
774       break;\r
775     }\r
776   }\r
777   sys_mbox_post(msg->conn->mbox, NULL);\r
778 }\r
779 \r
780 typedef void (* api_msg_decode)(struct api_msg_msg *msg);\r
781 static api_msg_decode decode[API_MSG_MAX] = {\r
782   do_newconn,\r
783   do_delconn,\r
784   do_bind,\r
785   do_connect,\r
786   do_disconnect,\r
787   do_listen,\r
788   do_accept,\r
789   do_send,\r
790   do_recv,\r
791   do_write,\r
792   do_close\r
793   };\r
794 void\r
795 api_msg_input(struct api_msg *msg)\r
796 {  \r
797   decode[msg->type](&(msg->msg));\r
798 }\r
799 \r
800 void\r
801 api_msg_post(struct api_msg *msg)\r
802 {\r
803   tcpip_apimsg(msg);\r
804 }\r
805 \r
806 \r
807 \r