2 * Copyright (c) 2001-2004 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"
42 recv_raw(void *arg
, struct raw_pcb
*pcb
, struct pbuf
*p
,
51 if (conn
->recvmbox
!= SYS_MBOX_NULL
) {
52 if (!(buf
= memp_malloc(MEMP_NETBUF
))) {
59 buf
->fromport
= pcb
->protocol
;
61 conn
->recv_avail
+= p
->tot_len
;
62 /* Register event with callback */
64 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, p
->tot_len
);
65 sys_mbox_post(conn
->recvmbox
, buf
);
68 return 0; /* do not eat the packet */
73 recv_udp(void *arg
, struct udp_pcb
*pcb
, struct pbuf
*p
,
74 struct ip_addr
*addr
, u16_t port
)
85 if (conn
->recvmbox
!= SYS_MBOX_NULL
) {
86 buf
= memp_malloc(MEMP_NETBUF
);
97 conn
->recv_avail
+= p
->tot_len
;
98 /* Register event with callback */
100 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, p
->tot_len
);
101 sys_mbox_post(conn
->recvmbox
, buf
);
104 #endif /* LWIP_UDP */
108 recv_tcp(void *arg
, struct tcp_pcb
*pcb
, struct pbuf
*p
, err_t err
)
110 struct netconn
*conn
;
120 if (conn
->recvmbox
!= SYS_MBOX_NULL
) {
125 conn
->recv_avail
+= len
;
129 /* Register event with callback */
131 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, len
);
132 sys_mbox_post(conn
->recvmbox
, p
);
139 poll_tcp(void *arg
, struct tcp_pcb
*pcb
)
141 struct netconn
*conn
;
145 (conn
->state
== NETCONN_WRITE
|| conn
->state
== NETCONN_CLOSE
) &&
146 conn
->sem
!= SYS_SEM_NULL
) {
147 sys_sem_signal(conn
->sem
);
153 sent_tcp(void *arg
, struct tcp_pcb
*pcb
, u16_t len
)
155 struct netconn
*conn
;
158 if (conn
!= NULL
&& conn
->sem
!= SYS_SEM_NULL
) {
159 sys_sem_signal(conn
->sem
);
162 if (conn
&& conn
->callback
)
163 if (tcp_sndbuf(conn
->pcb
.tcp
) > TCP_SNDLOWAT
)
164 (*conn
->callback
)(conn
, NETCONN_EVT_SENDPLUS
, len
);
170 err_tcp(void *arg
, err_t err
)
172 struct netconn
*conn
;
176 conn
->pcb
.tcp
= NULL
;
180 if (conn
->recvmbox
!= SYS_MBOX_NULL
) {
181 /* Register event with callback */
183 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, 0);
184 sys_mbox_post(conn
->recvmbox
, NULL
);
186 if (conn
->mbox
!= SYS_MBOX_NULL
) {
187 sys_mbox_post(conn
->mbox
, NULL
);
189 if (conn
->acceptmbox
!= SYS_MBOX_NULL
) {
190 /* Register event with callback */
192 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, 0);
193 sys_mbox_post(conn
->acceptmbox
, NULL
);
195 if (conn
->sem
!= SYS_SEM_NULL
) {
196 sys_sem_signal(conn
->sem
);
201 setup_tcp(struct netconn
*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
);
214 accept_function(void *arg
, struct tcp_pcb
*newpcb
, err_t err
)
217 struct netconn
*newconn
;
218 struct netconn
*conn
;
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
) {
231 newconn
->recvmbox
= sys_mbox_new();
232 if (newconn
->recvmbox
== SYS_MBOX_NULL
) {
233 memp_free(MEMP_NETCONN
, newconn
);
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
);
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
);
249 /* Allocations were OK, setup the PCB etc */
250 newconn
->type
= NETCONN_TCP
;
251 newconn
->pcb
.tcp
= newpcb
;
253 newconn
->acceptmbox
= SYS_MBOX_NULL
;
255 /* Register event with callback */
258 (*conn
->callback
)(conn
, NETCONN_EVT_RCVPLUS
, 0);
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;
266 sys_mbox_post(mbox
, newconn
);
269 #endif /* LWIP_TCP */
272 do_newconn(struct api_msg_msg
*msg
)
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
);
282 msg
->conn
->err
= ERR_OK
;
284 /* Allocate a PCB for this connection */
285 switch(msg
->conn
->type
) {
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
);
293 case NETCONN_UDPLITE
:
294 msg
->conn
->pcb
.udp
= udp_new();
295 if(msg
->conn
->pcb
.udp
== NULL
) {
296 msg
->conn
->err
= ERR_MEM
;
299 udp_setflags(msg
->conn
->pcb
.udp
, UDP_FLAGS_UDPLITE
);
300 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
302 case NETCONN_UDPNOCHKSUM
:
303 msg
->conn
->pcb
.udp
= udp_new();
304 if(msg
->conn
->pcb
.udp
== NULL
) {
305 msg
->conn
->err
= ERR_MEM
;
308 udp_setflags(msg
->conn
->pcb
.udp
, UDP_FLAGS_NOCHKSUM
);
309 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
312 msg
->conn
->pcb
.udp
= udp_new();
313 if(msg
->conn
->pcb
.udp
== NULL
) {
314 msg
->conn
->err
= ERR_MEM
;
317 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
319 #endif /* LWIP_UDP */
322 msg
->conn
->pcb
.tcp
= tcp_new();
323 if(msg
->conn
->pcb
.tcp
== NULL
) {
324 msg
->conn
->err
= ERR_MEM
;
327 setup_tcp(msg
->conn
);
333 sys_mbox_post(msg
->conn
->mbox
, NULL
);
338 do_delconn(struct api_msg_msg
*msg
)
340 if (msg
->conn
->pcb
.tcp
!= NULL
) {
341 switch (msg
->conn
->type
) {
344 raw_remove(msg
->conn
->pcb
.raw
);
348 case NETCONN_UDPLITE
:
350 case NETCONN_UDPNOCHKSUM
:
353 msg
->conn
->pcb
.udp
->recv_arg
= NULL
;
354 udp_remove(msg
->conn
->pcb
.udp
);
356 #endif /* LWIP_UDP */
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
);
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
);
378 /* Trigger select() in socket layer */
379 if (msg
->conn
->callback
)
381 (*msg
->conn
->callback
)(msg
->conn
, NETCONN_EVT_RCVPLUS
, 0);
382 (*msg
->conn
->callback
)(msg
->conn
, NETCONN_EVT_SENDPLUS
, 0);
385 if (msg
->conn
->mbox
!= SYS_MBOX_NULL
) {
386 sys_mbox_post(msg
->conn
->mbox
, NULL
);
391 do_bind(struct api_msg_msg
*msg
)
393 if (msg
->conn
->pcb
.tcp
== NULL
) {
394 switch (msg
->conn
->type
) {
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
);
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
);
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
);
413 msg
->conn
->pcb
.udp
= udp_new();
414 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
416 #endif /* LWIP_UDP */
419 msg
->conn
->pcb
.tcp
= tcp_new();
420 setup_tcp(msg
->conn
);
421 #endif /* LWIP_TCP */
426 switch (msg
->conn
->type
) {
429 msg
->conn
->err
= raw_bind(msg
->conn
->pcb
.raw
,msg
->msg
.bc
.ipaddr
);
433 case NETCONN_UDPLITE
:
435 case NETCONN_UDPNOCHKSUM
:
438 msg
->conn
->err
= udp_bind(msg
->conn
->pcb
.udp
, msg
->msg
.bc
.ipaddr
, msg
->msg
.bc
.port
);
440 #endif /* LWIP_UDP */
443 msg
->conn
->err
= tcp_bind(msg
->conn
->pcb
.tcp
,
444 msg
->msg
.bc
.ipaddr
, msg
->msg
.bc
.port
);
445 #endif /* LWIP_TCP */
449 sys_mbox_post(msg
->conn
->mbox
, NULL
);
454 do_connected(void *arg
, struct tcp_pcb
*pcb
, err_t err
)
456 struct netconn
*conn
;
465 if (conn
->type
== NETCONN_TCP
&& err
== ERR_OK
) {
468 sys_mbox_post(conn
->mbox
, NULL
);
474 do_connect(struct api_msg_msg
*msg
)
476 if (msg
->conn
->pcb
.tcp
== NULL
) {
477 switch (msg
->conn
->type
) {
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
);
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
);
492 udp_setflags(msg
->conn
->pcb
.udp
, UDP_FLAGS_UDPLITE
);
493 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
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
);
502 udp_setflags(msg
->conn
->pcb
.udp
, UDP_FLAGS_NOCHKSUM
);
503 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
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
);
512 udp_recv(msg
->conn
->pcb
.udp
, recv_udp
, msg
->conn
);
514 #endif /* LWIP_UDP */
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
);
528 switch (msg
->conn
->type
) {
531 raw_connect(msg
->conn
->pcb
.raw
, msg
->msg
.bc
.ipaddr
);
532 sys_mbox_post(msg
->conn
->mbox
, NULL
);
536 case NETCONN_UDPLITE
:
538 case NETCONN_UDPNOCHKSUM
:
541 udp_connect(msg
->conn
->pcb
.udp
, msg
->msg
.bc
.ipaddr
, msg
->msg
.bc
.port
);
542 sys_mbox_post(msg
->conn
->mbox
, NULL
);
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
,
551 /*tcp_output(msg->conn->pcb.tcp);*/
560 do_disconnect(struct api_msg_msg
*msg
)
563 switch (msg
->conn
->type
) {
566 /* Do nothing as connecting is only a helper for upper lwip layers */
570 case NETCONN_UDPLITE
:
572 case NETCONN_UDPNOCHKSUM
:
575 udp_disconnect(msg
->conn
->pcb
.udp
);
581 sys_mbox_post(msg
->conn
->mbox
, NULL
);
586 do_listen(struct api_msg_msg
*msg
)
588 if (msg
->conn
->pcb
.tcp
!= NULL
) {
589 switch (msg
->conn
->type
) {
592 LWIP_DEBUGF(API_MSG_DEBUG
, ("api_msg: listen RAW: cannot listen for RAW.\n"));
596 case NETCONN_UDPLITE
:
598 case NETCONN_UDPNOCHKSUM
:
601 LWIP_DEBUGF(API_MSG_DEBUG
, ("api_msg: listen UDP: cannot listen for UDP.\n"));
603 #endif /* LWIP_UDP */
606 msg
->conn
->pcb
.tcp
= tcp_listen(msg
->conn
->pcb
.tcp
);
607 if (msg
->conn
->pcb
.tcp
== NULL
) {
608 msg
->conn
->err
= ERR_MEM
;
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
;
617 tcp_arg(msg
->conn
->pcb
.tcp
, msg
->conn
);
618 tcp_accept(msg
->conn
->pcb
.tcp
, accept_function
);
625 sys_mbox_post(msg
->conn
->mbox
, NULL
);
629 do_accept(struct api_msg_msg
*msg
)
631 if (msg
->conn
->pcb
.tcp
!= NULL
) {
632 switch (msg
->conn
->type
) {
635 LWIP_DEBUGF(API_MSG_DEBUG
, ("api_msg: accept RAW: cannot accept for RAW.\n"));
639 case NETCONN_UDPLITE
:
641 case NETCONN_UDPNOCHKSUM
:
644 LWIP_DEBUGF(API_MSG_DEBUG
, ("api_msg: accept UDP: cannot accept for UDP.\n"));
646 #endif /* LWIP_UDP */
654 do_send(struct api_msg_msg
*msg
)
656 if (msg
->conn
->pcb
.tcp
!= NULL
) {
657 switch (msg
->conn
->type
) {
660 raw_send(msg
->conn
->pcb
.raw
, msg
->msg
.p
);
664 case NETCONN_UDPLITE
:
666 case NETCONN_UDPNOCHKSUM
:
669 udp_send(msg
->conn
->pcb
.udp
, msg
->msg
.p
);
671 #endif /* LWIP_UDP */
676 sys_mbox_post(msg
->conn
->mbox
, NULL
);
680 do_recv(struct api_msg_msg
*msg
)
683 if (msg
->conn
->pcb
.tcp
!= NULL
) {
684 if (msg
->conn
->type
== NETCONN_TCP
) {
685 tcp_recved(msg
->conn
->pcb
.tcp
, msg
->msg
.len
);
689 sys_mbox_post(msg
->conn
->mbox
, NULL
);
693 do_write(struct api_msg_msg
*msg
)
698 if (msg
->conn
->pcb
.tcp
!= NULL
) {
699 switch (msg
->conn
->type
) {
702 msg
->conn
->err
= ERR_VAL
;
706 case NETCONN_UDPLITE
:
708 case NETCONN_UDPNOCHKSUM
:
711 msg
->conn
->err
= ERR_VAL
;
713 #endif /* LWIP_UDP */
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
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
);
727 msg
->conn
->err
= err
;
728 if (msg
->conn
->callback
)
731 if (tcp_sndbuf(msg
->conn
->pcb
.tcp
) <= TCP_SNDLOWAT
)
732 (*msg
->conn
->callback
)(msg
->conn
, NETCONN_EVT_SENDMINUS
, msg
->msg
.w
.len
);
739 sys_mbox_post(msg
->conn
->mbox
, NULL
);
743 do_close(struct api_msg_msg
*msg
)
749 if (msg
->conn
->pcb
.tcp
!= NULL
) {
750 switch (msg
->conn
->type
) {
756 case NETCONN_UDPLITE
:
758 case NETCONN_UDPNOCHKSUM
:
762 #endif /* LWIP_UDP */
765 if (msg
->conn
->pcb
.tcp
->state
== LISTEN
) {
766 err
= tcp_close(msg
->conn
->pcb
.tcp
);
768 else if (msg
->conn
->pcb
.tcp
->state
== CLOSE_WAIT
) {
769 err
= tcp_output(msg
->conn
->pcb
.tcp
);
771 msg
->conn
->err
= err
;
777 sys_mbox_post(msg
->conn
->mbox
, NULL
);
780 typedef void (* api_msg_decode
)(struct api_msg_msg
*msg
);
781 static api_msg_decode decode
[API_MSG_MAX
] = {
795 api_msg_input(struct api_msg
*msg
)
797 decode
[msg
->type
](&(msg
->msg
));
801 api_msg_post(struct api_msg
*msg
)