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