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