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