blob: 0cbe626fb5237ccad90891676848aa8523487851 [file] [log] [blame]
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07001/*
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
41static u8_t
42recv_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
72static void
73recv_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
107static err_t
108recv_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
138static err_t
139poll_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
152static err_t
153sent_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
169static void
170err_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
200static void
201setup_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
213static err_t
214accept_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
269static void
270do_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
335static void
336do_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
388static void
389do_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
451static err_t
452do_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
471static void
472do_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
557static void
558do_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
583static void
584do_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
626static void
627do_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
651static void
652do_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
677static void
678do_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
690static void
691do_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
738static void
739do_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
773typedef void (* api_msg_decode)(struct api_msg_msg *msg);
774static 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 };
787void
788api_msg_input(struct api_msg *msg)
789{
790 decode[msg->type](&(msg->msg));
791}
792
793void
794api_msg_post(struct api_msg *msg)
795{
796 tcpip_apimsg(msg);
797}
798
799
800