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>
33 /* This is the part of the API that is linked with
38 #include "lwip/api_msg.h"
39 #include "lwip/memp.h"
46 extern void tcpip_apimsg(struct api_msg
*apimsg
);
49 struct netbuf
* netbuf_new ( void ) {
50 struct netbuf
*buf
= memp_malloc ( MEMP_NETBUF
);
59 } /* end netbuf_new */
61 void netbuf_delete ( struct netbuf
* buf
) {
64 if ( buf
-> p
!= NULL
) {
65 pbuf_free ( buf
-> p
);
66 buf
-> p
= buf
-> ptr
= NULL
;
68 memp_free ( MEMP_NETBUF
, buf
);
71 } /* end netbuf_delete */
73 void netbuf_ref ( struct netbuf
* buf
, void* dataptr
, u16_t size
) {
75 if ( buf
-> p
) pbuf_free ( buf
-> p
);
77 buf
-> p
= pbuf_alloc ( PBUF_TRANSPORT
, 0, PBUF_REF
);
78 buf
-> p
-> payload
= dataptr
;
79 buf
-> p
-> len
= buf
-> p
-> tot_len
= size
;
80 buf
-> ptr
= buf
-> p
;
82 } /* end netbuf_ref */
84 void netbuf_copy_partial (
85 struct netbuf
* buf
, void* dataptr
, u16_t len
, u16_t offset
91 if ( !buf
|| !dataptr
) return;
93 for ( p
= buf
-> p
; left
< len
&& p
; p
= p
-> next
) {
95 if ( offset
&& offset
>= p
-> len
)
101 int buf_copy_len
= p
-> len
- offset
;
102 int lDiff
= len
- left
;
104 lDiff
= buf_copy_len
> lDiff
? lDiff
: buf_copy_len
;
107 &( ( char* )dataptr
)[ left
],
108 &( ( char* )p
-> payload
)[ offset
],
113 if ( left
>= len
) return;
121 } /* end netbuf_copy_partial */
124 netconn
*netconn_new_with_proto_and_callback(enum netconn_type t
, u16_t proto
,
125 void (*callback
)(struct netconn
*, enum netconn_evt
, u16_t len
))
127 struct netconn
*conn
;
130 conn
= memp_malloc(MEMP_NETCONN
);
137 conn
->pcb
.tcp
= NULL
;
139 if ((conn
->mbox
= sys_mbox_new()) == SYS_MBOX_NULL
) {
140 memp_free(MEMP_NETCONN
, conn
);
143 conn
->recvmbox
= SYS_MBOX_NULL
;
144 conn
->acceptmbox
= SYS_MBOX_NULL
;
145 conn
->sem
= SYS_SEM_NULL
;
146 conn
->state
= NETCONN_NONE
;
148 conn
->callback
= callback
;
149 conn
->recv_avail
= 0;
151 if((msg
= memp_malloc(MEMP_API_MSG
)) == NULL
) {
152 memp_free(MEMP_NETCONN
, conn
);
156 msg
->type
= API_MSG_NEWCONN
;
157 msg
->msg
.msg
.bc
.port
= proto
; /* misusing the port field */
158 msg
->msg
.conn
= conn
;
160 sys_mbox_fetch(conn
->mbox
, NULL
);
161 memp_free(MEMP_API_MSG
, msg
);
163 if ( conn
->err
!= ERR_OK
) {
164 memp_free(MEMP_NETCONN
, conn
);
172 netconn_delete(struct netconn
*conn
)
181 if ((msg
= memp_malloc(MEMP_API_MSG
)) == NULL
) {
185 msg
->type
= API_MSG_DELCONN
;
186 msg
->msg
.conn
= conn
;
188 sys_mbox_fetch(conn
->mbox
, NULL
);
189 memp_free(MEMP_API_MSG
, msg
);
191 /* Drain the recvmbox. */
192 if (conn
->recvmbox
!= SYS_MBOX_NULL
) {
193 while (sys_arch_mbox_fetch(conn
->recvmbox
, &mem
, 1) != SYS_ARCH_TIMEOUT
) {
194 if (conn
->type
== NETCONN_TCP
) {
195 pbuf_free((struct pbuf
*)mem
);
197 netbuf_delete((struct netbuf
*)mem
);
200 sys_mbox_free(conn
->recvmbox
);
201 conn
->recvmbox
= SYS_MBOX_NULL
;
204 /* Drain the acceptmbox. */
205 if (conn
->acceptmbox
!= SYS_MBOX_NULL
) {
206 while (sys_arch_mbox_fetch(conn
->acceptmbox
, &mem
, 1) != SYS_ARCH_TIMEOUT
) {
207 netconn_delete((struct netconn
*)mem
);
210 sys_mbox_free(conn
->acceptmbox
);
211 conn
->acceptmbox
= SYS_MBOX_NULL
;
214 sys_mbox_free(conn
->mbox
);
215 conn
->mbox
= SYS_MBOX_NULL
;
216 if (conn
->sem
!= SYS_SEM_NULL
) {
217 sys_sem_free(conn
->sem
);
219 /* conn->sem = SYS_SEM_NULL;*/
220 memp_free(MEMP_NETCONN
, conn
);
225 netconn_peer(struct netconn
*conn
, struct ip_addr
*addr
,
228 switch (conn
->type
) {
230 /* return an error as connecting is only a helper for upper layers */
232 case NETCONN_UDPLITE
:
233 case NETCONN_UDPNOCHKSUM
:
235 if (conn
->pcb
.udp
== NULL
||
236 ((conn
->pcb
.udp
->flags
& UDP_FLAGS_CONNECTED
) == 0))
238 *addr
= (conn
->pcb
.udp
->remote_ip
);
239 *port
= conn
->pcb
.udp
->remote_port
;
242 if (conn
->pcb
.tcp
== NULL
)
244 *addr
= (conn
->pcb
.tcp
->remote_ip
);
245 *port
= conn
->pcb
.tcp
->remote_port
;
248 return (conn
->err
= ERR_OK
);
252 netconn_addr(struct netconn
*conn
, struct ip_addr
**addr
,
255 switch (conn
->type
) {
257 *addr
= &(conn
->pcb
.raw
->local_ip
);
258 *port
= conn
->pcb
.raw
->protocol
;
260 case NETCONN_UDPLITE
:
261 case NETCONN_UDPNOCHKSUM
:
263 *addr
= &(conn
->pcb
.udp
->local_ip
);
264 *port
= conn
->pcb
.udp
->local_port
;
267 *addr
= &(conn
->pcb
.tcp
->local_ip
);
268 *port
= conn
->pcb
.tcp
->local_port
;
271 return (conn
->err
= ERR_OK
);
275 netconn_bind(struct netconn
*conn
, struct ip_addr
*addr
,
284 if (conn
->type
!= NETCONN_TCP
&&
285 conn
->recvmbox
== SYS_MBOX_NULL
) {
286 if ((conn
->recvmbox
= sys_mbox_new()) == SYS_MBOX_NULL
) {
291 if ((msg
= memp_malloc(MEMP_API_MSG
)) == NULL
) {
292 return (conn
->err
= ERR_MEM
);
294 msg
->type
= API_MSG_BIND
;
295 msg
->msg
.conn
= conn
;
296 msg
->msg
.msg
.bc
.ipaddr
= addr
;
297 msg
->msg
.msg
.bc
.port
= port
;
299 sys_mbox_fetch(conn
->mbox
, NULL
);
300 memp_free(MEMP_API_MSG
, msg
);
306 netconn_connect(struct netconn
*conn
, struct ip_addr
*addr
,
316 if (conn
->recvmbox
== SYS_MBOX_NULL
) {
317 if ((conn
->recvmbox
= sys_mbox_new()) == SYS_MBOX_NULL
) {
322 if ((msg
= memp_malloc(MEMP_API_MSG
)) == NULL
) {
325 msg
->type
= API_MSG_CONNECT
;
326 msg
->msg
.conn
= conn
;
327 msg
->msg
.msg
.bc
.ipaddr
= addr
;
328 msg
->msg
.msg
.bc
.port
= port
;
330 sys_mbox_fetch(conn
->mbox
, NULL
);
331 memp_free(MEMP_API_MSG
, msg
);
336 netconn_disconnect(struct netconn
*conn
)
344 if ((msg
= memp_malloc(MEMP_API_MSG
)) == NULL
) {
347 msg
->type
= API_MSG_DISCONNECT
;
348 msg
->msg
.conn
= conn
;
350 sys_mbox_fetch(conn
->mbox
, NULL
);
351 memp_free(MEMP_API_MSG
, msg
);
357 netconn_listen(struct netconn
*conn
)
365 if (conn
->acceptmbox
== SYS_MBOX_NULL
) {
366 conn
->acceptmbox
= sys_mbox_new();
367 if (conn
->acceptmbox
== SYS_MBOX_NULL
) {
372 if ((msg
= memp_malloc(MEMP_API_MSG
)) == NULL
) {
373 return (conn
->err
= ERR_MEM
);
375 msg
->type
= API_MSG_LISTEN
;
376 msg
->msg
.conn
= conn
;
378 sys_mbox_fetch(conn
->mbox
, NULL
);
379 memp_free(MEMP_API_MSG
, msg
);
384 netconn_accept(struct netconn
*conn
)
386 struct netconn
*newconn
;
392 sys_mbox_fetch(conn
->acceptmbox
, (void **)&newconn
);
393 /* Register event with callback */
395 (*conn
->callback
)(conn
, NETCONN_EVT_RCVMINUS
, 0);
401 netconn_recv(struct netconn
*conn
)
412 if (conn
->recvmbox
== SYS_MBOX_NULL
) {
413 conn
->err
= ERR_CONN
;
417 if (conn
->err
!= ERR_OK
) {
421 if (conn
->type
== NETCONN_TCP
) {
422 if (conn
->pcb
.tcp
->state
== LISTEN
) {
423 conn
->err
= ERR_CONN
;
428 buf
= memp_malloc(MEMP_NETBUF
);
435 sys_mbox_fetch(conn
->recvmbox
, (void **)&p
);
440 conn
->recv_avail
-= len
;
445 /* Register event with callback */
447 (*conn
->callback
)(conn
, NETCONN_EVT_RCVMINUS
, len
);
449 /* If we are closed, we indicate that we no longer wish to receive
450 data by setting conn->recvmbox to SYS_MBOX_NULL. */
452 memp_free(MEMP_NETBUF
, buf
);
453 sys_mbox_free(conn
->recvmbox
);
454 conn
->recvmbox
= SYS_MBOX_NULL
;
461 buf
->fromaddr
= NULL
;
463 /* Let the stack know that we have taken the data. */
464 if ((msg
= memp_malloc(MEMP_API_MSG
)) == NULL
) {
468 msg
->type
= API_MSG_RECV
;
469 msg
->msg
.conn
= conn
;
471 msg
->msg
.msg
.len
= buf
->p
->tot_len
;
473 msg
->msg
.msg
.len
= 1;
477 sys_mbox_fetch(conn
->mbox
, NULL
);
478 memp_free(MEMP_API_MSG
, msg
);
480 sys_mbox_fetch(conn
->recvmbox
, (void **)&buf
);
481 conn
->recv_avail
-= buf
->p
->tot_len
;
482 /* Register event with callback */
484 (*conn
->callback
)(conn
, NETCONN_EVT_RCVMINUS
, buf
->p
->tot_len
);
491 netconn_send(struct netconn
*conn
, struct netbuf
*buf
)
499 if (conn
->err
!= ERR_OK
) {
503 if ((msg
= memp_malloc(MEMP_API_MSG
)) == NULL
) {
504 return (conn
->err
= ERR_MEM
);
506 msg
->type
= API_MSG_SEND
;
507 msg
->msg
.conn
= conn
;
508 msg
->msg
.msg
.p
= buf
->p
;
511 sys_mbox_fetch(conn
->mbox
, NULL
);
512 memp_free(MEMP_API_MSG
, msg
);
518 netconn_write(struct netconn
*conn
, void *dataptr
, u16_t size
, u8_t copy
)
527 if (conn
->err
!= ERR_OK
) {
531 if ((msg
= memp_malloc(MEMP_API_MSG
)) == NULL
) {
532 return (conn
->err
= ERR_MEM
);
534 msg
->type
= API_MSG_WRITE
;
535 msg
->msg
.conn
= conn
;
538 conn
->state
= NETCONN_WRITE
;
539 while (conn
->err
== ERR_OK
&& size
> 0) {
540 msg
->msg
.msg
.w
.dataptr
= dataptr
;
541 msg
->msg
.msg
.w
.copy
= copy
;
543 if (conn
->type
== NETCONN_TCP
) {
544 if (tcp_sndbuf(conn
->pcb
.tcp
) == 0) {
545 sys_sem_wait(conn
->sem
);
546 if (conn
->err
!= ERR_OK
) {
550 if (size
> tcp_sndbuf(conn
->pcb
.tcp
)) {
551 /* We cannot send more than one send buffer's worth of data at a
553 len
= tcp_sndbuf(conn
->pcb
.tcp
);
561 LWIP_DEBUGF(API_LIB_DEBUG
, ("netconn_write: writing %d bytes (%d)\n", len
, copy
));
562 msg
->msg
.msg
.w
.len
= len
;
564 sys_mbox_fetch(conn
->mbox
, NULL
);
565 if (conn
->err
== ERR_OK
) {
566 dataptr
= (void *)((u8_t
*)dataptr
+ len
);
568 } else if (conn
->err
== ERR_MEM
) {
570 sys_sem_wait(conn
->sem
);
576 memp_free(MEMP_API_MSG
, msg
);
577 conn
->state
= NETCONN_NONE
;
583 netconn_close(struct netconn
*conn
)
590 if ((msg
= memp_malloc(MEMP_API_MSG
)) == NULL
) {
591 return (conn
->err
= ERR_MEM
);
594 conn
->state
= NETCONN_CLOSE
;
596 msg
->type
= API_MSG_CLOSE
;
597 msg
->msg
.conn
= conn
;
599 sys_mbox_fetch(conn
->mbox
, NULL
);
600 if (conn
->err
== ERR_MEM
&&
601 conn
->sem
!= SYS_SEM_NULL
) {
602 sys_sem_wait(conn
->sem
);
605 conn
->state
= NETCONN_NONE
;
606 memp_free(MEMP_API_MSG
, msg
);