2 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
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.
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
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
34 #include "lwip/arch.h"
35 #include "lwip/api_msg.h"
36 #include "lwip/memp.h"
38 #include "lwip/tcpip.h"
44 recv_raw(void *arg
, struct raw_pcb
*pcb
, struct pbuf
*p
,
53 if (conn
->recvmbox
!= SYS_MBOX_NULL
) {
54 if (!(buf
= memp_malloc(MEMP_NETBUF
))) {
61 buf
->fromport
= pcb
->protocol
;
63 conn
->recv_avail
+= p
->tot_len
;
64 /* Register event with callback */
66 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, p
->tot_len
);
67 sys_mbox_post(conn
->recvmbox
, buf
);
70 return 0; /* do not eat the packet */
75 recv_udp(void *arg
, struct udp_pcb
*pcb
, struct pbuf
*p
,
76 struct ip_addr
*addr
, u16_t port
)
87 if (conn
->recvmbox
!= SYS_MBOX_NULL
) {
88 buf
= memp_malloc(MEMP_NETBUF
);
99 conn
->recv_avail
+= p
->tot_len
;
100 /* Register event with callback */
102 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, p
->tot_len
);
103 sys_mbox_post(conn
->recvmbox
, buf
);
106 #endif /* LWIP_UDP */
108 static err_t
recv_tcp ( void* arg
, struct tcp_pcb
* pcb
, struct pbuf
* p
, err_t err
) {
110 struct netconn
* conn
= arg
;
116 if ( ( recvmbox
= conn
-> recvmbox
) != SYS_MBOX_NULL
) {
118 void ( *callback
)( struct netconn
*, enum netconn_evt
, u16_t len
) = conn
-> callback
;
124 conn
-> recv_avail
+= len
;
127 if ( callback
) callback ( conn
, NETCONN_EVT_RCVPLUS
, len
);
129 sys_mbox_post ( recvmbox
, p
);
146 poll_tcp(void *arg
, struct tcp_pcb
*pcb
)
148 struct netconn
*conn
;
152 (conn
->state
== NETCONN_WRITE
|| conn
->state
== NETCONN_CLOSE
) &&
153 conn
->sem
!= SYS_SEM_NULL
) {
154 sys_sem_signal(conn
->sem
);
160 sent_tcp(void *arg
, struct tcp_pcb
*pcb
, u16_t len
)
162 struct netconn
*conn
;
165 if (conn
!= NULL
&& conn
->sem
!= SYS_SEM_NULL
) {
166 sys_sem_signal(conn
->sem
);
169 if (conn
&& conn
->callback
)
170 if (tcp_sndbuf(conn
->pcb
.tcp
) > TCP_SNDLOWAT
)
171 (*conn
->callback
)(conn
, NETCONN_EVT_SENDPLUS
, len
);
177 err_tcp(void *arg
, err_t err
)
179 struct netconn
*conn
;
183 conn
->pcb
.tcp
= NULL
;
187 if (conn
->recvmbox
!= SYS_MBOX_NULL
) {
188 /* Register event with callback */
190 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, 0);
191 sys_mbox_post(conn
->recvmbox
, NULL
);
193 if (conn
->mbox
!= SYS_MBOX_NULL
) {
194 sys_mbox_post(conn
->mbox
, NULL
);
196 if (conn
->acceptmbox
!= SYS_MBOX_NULL
) {
197 /* Register event with callback */
199 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, 0);
200 sys_mbox_post(conn
->acceptmbox
, NULL
);
202 if (conn
->sem
!= SYS_SEM_NULL
) {
203 sys_sem_signal(conn
->sem
);
208 setup_tcp(struct netconn
*conn
)
214 tcp_recv(pcb
, recv_tcp
);
215 tcp_sent(pcb
, sent_tcp
);
216 tcp_poll(pcb
, poll_tcp
, 4);
217 tcp_err(pcb
, err_tcp
);
221 accept_function(void *arg
, struct tcp_pcb
*newpcb
, err_t err
)
224 struct netconn
*newconn
;
225 struct netconn
*conn
;
229 tcp_debug_print_state(newpcb
->state
);
230 #endif /* TCP_DEBUG */
231 #endif /* API_MSG_DEBUG */
232 conn
= (struct netconn
*)arg
;
233 mbox
= conn
->acceptmbox
;
234 newconn
= memp_malloc(MEMP_NETCONN
);
235 if (newconn
== NULL
) {
238 newconn
->type
= NETCONN_TCP
;
239 newconn
->pcb
.tcp
= newpcb
;
241 newconn
->recvmbox
= sys_mbox_new();
242 if (newconn
->recvmbox
== SYS_MBOX_NULL
) {
243 memp_free(MEMP_NETCONN
, newconn
);
246 newconn
->mbox
= sys_mbox_new();
247 if (newconn
->mbox
== SYS_MBOX_NULL
) {
248 sys_mbox_free(newconn
->recvmbox
);
249 memp_free(MEMP_NETCONN
, newconn
);
252 newconn
->sem
= sys_sem_new(0);
253 if (newconn
->sem
== SYS_SEM_NULL
) {
254 sys_mbox_free(newconn
->recvmbox
);
255 sys_mbox_free(newconn
->mbox
);
256 memp_free(MEMP_NETCONN
, newconn
);
259 newconn
->acceptmbox
= SYS_MBOX_NULL
;
261 /* Register event with callback */
264 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, 0);
265 /* We have to set the callback here even though
266 * the new socket is unknown. Mark the socket as -1. */
267 newconn
->callback
= conn
->callback
;
268 newconn
->socket
= -1;
271 sys_mbox_post(mbox
, newconn
);
274 #endif /* LWIP_TCP */
277 do_newconn(struct api_msg_msg
*msg
)
279 if(msg
->conn
->pcb
.tcp
!= NULL
) {
280 /* This "new" connection already has a PCB allocated. */
281 /* Is this an error condition? Should it be deleted?
282 We currently just are happy and return. */
283 sys_mbox_post(msg
->conn
->mbox
, NULL
);
287 msg
->conn
->err
= ERR_OK
;
289 /* Allocate a PCB for this connection */
290 switch(msg
->conn
->type
) {
293 msg
->conn
->pcb
.raw
= raw_new(msg
->msg
.bc
.port
); /* misusing the port field */
294 raw_recv(msg
->conn
->pcb
.raw
, recv_raw
, msg
->conn
);
298 case NETCONN_UDPLITE
:
299 msg
->conn
->pcb
.udp
= udp_new();
300 if(msg
->conn
->pcb
.udp
== NULL
) {
301 msg
->conn
->err
= ERR_MEM
;
304 udp_setflags(msg
->conn
->pcb
.udp
, UDP_FLAGS_UDPLITE
);
305 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
307 case NETCONN_UDPNOCHKSUM
:
308 msg
->conn
->pcb
.udp
= udp_new();
309 if(msg
->conn
->pcb
.udp
== NULL
) {
310 msg
->conn
->err
= ERR_MEM
;
313 udp_setflags(msg
->conn
->pcb
.udp
, UDP_FLAGS_NOCHKSUM
);
314 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
317 msg
->conn
->pcb
.udp
= udp_new();
318 if(msg
->conn
->pcb
.udp
== NULL
) {
319 msg
->conn
->err
= ERR_MEM
;
322 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
324 #endif /* LWIP_UDP */
327 msg
->conn
->pcb
.tcp
= tcp_new();
328 if(msg
->conn
->pcb
.tcp
== NULL
) {
329 msg
->conn
->err
= ERR_MEM
;
332 setup_tcp(msg
->conn
);
340 sys_mbox_post(msg
->conn
->mbox
, NULL
);
345 do_delconn(struct api_msg_msg
*msg
)
347 if (msg
->conn
->pcb
.tcp
!= NULL
) {
348 switch (msg
->conn
->type
) {
351 raw_remove(msg
->conn
->pcb
.raw
);
355 case NETCONN_UDPLITE
:
357 case NETCONN_UDPNOCHKSUM
:
360 msg
->conn
->pcb
.udp
->recv_arg
= NULL
;
361 udp_remove(msg
->conn
->pcb
.udp
);
363 #endif /* LWIP_UDP */
366 if (msg
->conn
->pcb
.tcp
->state
== LISTEN
) {
367 tcp_arg(msg
->conn
->pcb
.tcp
, NULL
);
368 tcp_accept(msg
->conn
->pcb
.tcp
, NULL
);
369 tcp_close(msg
->conn
->pcb
.tcp
);
371 tcp_arg(msg
->conn
->pcb
.tcp
, NULL
);
372 tcp_sent(msg
->conn
->pcb
.tcp
, NULL
);
373 tcp_recv(msg
->conn
->pcb
.tcp
, NULL
);
374 tcp_poll(msg
->conn
->pcb
.tcp
, NULL
, 0);
375 tcp_err(msg
->conn
->pcb
.tcp
, NULL
);
376 if (tcp_close(msg
->conn
->pcb
.tcp
) != ERR_OK
) {
377 tcp_abort(msg
->conn
->pcb
.tcp
);
385 /* Trigger select() in socket layer */
386 if (msg
->conn
->callback
)
388 (*msg
->conn
->callback
)(msg
->conn
, NETCONN_EVT_RCVPLUS
, 0);
389 (*msg
->conn
->callback
)(msg
->conn
, NETCONN_EVT_SENDPLUS
, 0);
392 if (msg
->conn
->mbox
!= SYS_MBOX_NULL
) {
393 sys_mbox_post(msg
->conn
->mbox
, NULL
);
398 do_bind(struct api_msg_msg
*msg
)
400 if (msg
->conn
->pcb
.tcp
== NULL
) {
401 switch (msg
->conn
->type
) {
404 msg
->conn
->pcb
.raw
= raw_new(msg
->msg
.bc
.port
); /* misusing the port field as protocol */
405 raw_recv(msg
->conn
->pcb
.raw
, recv_raw
, msg
->conn
);
409 case NETCONN_UDPLITE
:
410 msg
->conn
->pcb
.udp
= udp_new();
411 udp_setflags(msg
->conn
->pcb
.udp
, UDP_FLAGS_UDPLITE
);
412 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
414 case NETCONN_UDPNOCHKSUM
:
415 msg
->conn
->pcb
.udp
= udp_new();
416 udp_setflags(msg
->conn
->pcb
.udp
, UDP_FLAGS_NOCHKSUM
);
417 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
420 msg
->conn
->pcb
.udp
= udp_new();
421 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
423 #endif /* LWIP_UDP */
426 msg
->conn
->pcb
.tcp
= tcp_new();
427 setup_tcp(msg
->conn
);
428 #endif /* LWIP_TCP */
433 switch (msg
->conn
->type
) {
436 msg
->conn
->err
= raw_bind(msg
->conn
->pcb
.raw
,msg
->msg
.bc
.ipaddr
);
440 case NETCONN_UDPLITE
:
442 case NETCONN_UDPNOCHKSUM
:
445 msg
->conn
->err
= udp_bind(msg
->conn
->pcb
.udp
, msg
->msg
.bc
.ipaddr
, msg
->msg
.bc
.port
);
447 #endif /* LWIP_UDP */
450 msg
->conn
->err
= tcp_bind(msg
->conn
->pcb
.tcp
,
451 msg
->msg
.bc
.ipaddr
, msg
->msg
.bc
.port
);
452 #endif /* LWIP_TCP */
456 sys_mbox_post(msg
->conn
->mbox
, NULL
);
461 do_connected(void *arg
, struct tcp_pcb
*pcb
, err_t err
)
463 struct netconn
*conn
;
472 if (conn
->type
== NETCONN_TCP
&& err
== ERR_OK
) {
475 sys_mbox_post(conn
->mbox
, NULL
);
481 do_connect(struct api_msg_msg
*msg
)
483 if (msg
->conn
->pcb
.tcp
== NULL
) {
484 switch (msg
->conn
->type
) {
487 msg
->conn
->pcb
.raw
= raw_new(msg
->msg
.bc
.port
); /* misusing the port field as protocol */
488 raw_recv(msg
->conn
->pcb
.raw
, recv_raw
, msg
->conn
);
492 case NETCONN_UDPLITE
:
493 msg
->conn
->pcb
.udp
= udp_new();
494 if (msg
->conn
->pcb
.udp
== NULL
) {
495 msg
->conn
->err
= ERR_MEM
;
496 sys_mbox_post(msg
->conn
->mbox
, NULL
);
499 udp_setflags(msg
->conn
->pcb
.udp
, UDP_FLAGS_UDPLITE
);
500 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
502 case NETCONN_UDPNOCHKSUM
:
503 msg
->conn
->pcb
.udp
= udp_new();
504 if (msg
->conn
->pcb
.udp
== NULL
) {
505 msg
->conn
->err
= ERR_MEM
;
506 sys_mbox_post(msg
->conn
->mbox
, NULL
);
509 udp_setflags(msg
->conn
->pcb
.udp
, UDP_FLAGS_NOCHKSUM
);
510 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
513 msg
->conn
->pcb
.udp
= udp_new();
514 if (msg
->conn
->pcb
.udp
== NULL
) {
515 msg
->conn
->err
= ERR_MEM
;
516 sys_mbox_post(msg
->conn
->mbox
, NULL
);
519 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
521 #endif /* LWIP_UDP */
524 msg
->conn
->pcb
.tcp
= tcp_new();
525 if (msg
->conn
->pcb
.tcp
== NULL
) {
526 msg
->conn
->err
= ERR_MEM
;
527 sys_mbox_post(msg
->conn
->mbox
, NULL
);
535 switch (msg
->conn
->type
) {
538 raw_connect(msg
->conn
->pcb
.raw
, msg
->msg
.bc
.ipaddr
);
539 sys_mbox_post(msg
->conn
->mbox
, NULL
);
543 case NETCONN_UDPLITE
:
545 case NETCONN_UDPNOCHKSUM
:
548 udp_connect(msg
->conn
->pcb
.udp
, msg
->msg
.bc
.ipaddr
, msg
->msg
.bc
.port
);
549 sys_mbox_post(msg
->conn
->mbox
, NULL
);
554 /* tcp_arg(msg->conn->pcb.tcp, msg->conn);*/
555 setup_tcp(msg
->conn
);
556 tcp_connect(msg
->conn
->pcb
.tcp
, msg
->msg
.bc
.ipaddr
, msg
->msg
.bc
.port
,
558 /*tcp_output(msg->conn->pcb.tcp);*/
567 do_disconnect(struct api_msg_msg
*msg
)
570 switch (msg
->conn
->type
) {
573 /* Do nothing as connecting is only a helper for upper lwip layers */
577 case NETCONN_UDPLITE
:
579 case NETCONN_UDPNOCHKSUM
:
582 udp_disconnect(msg
->conn
->pcb
.udp
);
590 sys_mbox_post(msg
->conn
->mbox
, NULL
);
595 do_listen(struct api_msg_msg
*msg
)
597 if (msg
->conn
->pcb
.tcp
!= NULL
) {
598 switch (msg
->conn
->type
) {
601 LWIP_DEBUGF(API_MSG_DEBUG
, ("api_msg: listen RAW: cannot listen for RAW.\n"));
605 case NETCONN_UDPLITE
:
607 case NETCONN_UDPNOCHKSUM
:
610 LWIP_DEBUGF(API_MSG_DEBUG
, ("api_msg: listen UDP: cannot listen for UDP.\n"));
612 #endif /* LWIP_UDP */
615 msg
->conn
->pcb
.tcp
= tcp_listen(msg
->conn
->pcb
.tcp
);
616 if (msg
->conn
->pcb
.tcp
== NULL
) {
617 msg
->conn
->err
= ERR_MEM
;
619 if (msg
->conn
->acceptmbox
== SYS_MBOX_NULL
) {
620 msg
->conn
->acceptmbox
= sys_mbox_new();
621 if (msg
->conn
->acceptmbox
== SYS_MBOX_NULL
) {
622 msg
->conn
->err
= ERR_MEM
;
626 tcp_arg(msg
->conn
->pcb
.tcp
, msg
->conn
);
627 tcp_accept(msg
->conn
->pcb
.tcp
, accept_function
);
634 sys_mbox_post(msg
->conn
->mbox
, NULL
);
638 do_accept(struct api_msg_msg
*msg
)
640 if (msg
->conn
->pcb
.tcp
!= NULL
) {
641 switch (msg
->conn
->type
) {
644 LWIP_DEBUGF(API_MSG_DEBUG
, ("api_msg: accept RAW: cannot accept for RAW.\n"));
648 case NETCONN_UDPLITE
:
650 case NETCONN_UDPNOCHKSUM
:
653 LWIP_DEBUGF(API_MSG_DEBUG
, ("api_msg: accept UDP: cannot accept for UDP.\n"));
655 #endif /* LWIP_UDP */
665 do_send(struct api_msg_msg
*msg
)
667 if (msg
->conn
->pcb
.tcp
!= NULL
) {
668 switch (msg
->conn
->type
) {
671 raw_send(msg
->conn
->pcb
.raw
, msg
->msg
.p
);
675 case NETCONN_UDPLITE
:
677 case NETCONN_UDPNOCHKSUM
:
680 udp_send(msg
->conn
->pcb
.udp
, msg
->msg
.p
);
682 #endif /* LWIP_UDP */
689 sys_mbox_post(msg
->conn
->mbox
, NULL
);
692 static void do_recv ( struct api_msg_msg
* msg
) {
694 struct netconn
* conn
= msg
-> conn
;
696 if ( conn
-> pcb
.tcp
&& conn
-> type
== NETCONN_TCP
)
697 tcp_recved ( conn
-> pcb
.tcp
, msg
-> msg
.len
);
699 sys_mbox_post ( conn
-> mbox
, NULL
);
704 do_write(struct api_msg_msg
*msg
)
709 if (msg
->conn
->pcb
.tcp
!= NULL
) {
710 switch (msg
->conn
->type
) {
713 msg
->conn
->err
= ERR_VAL
;
717 case NETCONN_UDPLITE
:
719 case NETCONN_UDPNOCHKSUM
:
722 msg
->conn
->err
= ERR_VAL
;
724 #endif /* LWIP_UDP */
727 err
= tcp_write(msg
->conn
->pcb
.tcp
, msg
->msg
.w
.dataptr
,
728 msg
->msg
.w
.len
, msg
->msg
.w
.copy
);
729 /* This is the Nagle algorithm: inhibit the sending of new TCP
730 segments when new outgoing data arrives from the user if any
731 previously transmitted data on the connection remains
733 if(err
== ERR_OK
&& (msg
->conn
->pcb
.tcp
->unacked
== NULL
|| (msg
->conn
->pcb
.tcp
->flags
& TF_NODELAY
)) ) {
734 tcp_output(msg
->conn
->pcb
.tcp
);
736 msg
->conn
->err
= err
;
737 if (msg
->conn
->callback
)
740 if (tcp_sndbuf(msg
->conn
->pcb
.tcp
) <= TCP_SNDLOWAT
)
741 (*msg
->conn
->callback
)(msg
->conn
, NETCONN_EVT_SENDMINUS
, msg
->msg
.w
.len
);
748 sys_mbox_post(msg
->conn
->mbox
, NULL
);
752 do_close(struct api_msg_msg
*msg
)
758 if (msg
->conn
->pcb
.tcp
!= NULL
) {
759 switch (msg
->conn
->type
) {
765 case NETCONN_UDPLITE
:
767 case NETCONN_UDPNOCHKSUM
:
771 #endif /* LWIP_UDP */
774 if (msg
->conn
->pcb
.tcp
->state
== LISTEN
) {
775 err
= tcp_close(msg
->conn
->pcb
.tcp
);
777 msg
->conn
->err
= err
;
783 sys_mbox_post(msg
->conn
->mbox
, NULL
);
786 api_msg_decode __decode__
[ API_MSG_MAX
] = {