Mistake on this page?
Report an issue in GitHub or email us
api.h
Go to the documentation of this file.
1 /**
2  * @file
3  * netconn API (to be used from non-TCPIP threads)
4  */
5 
6 /*
7  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without modification,
11  * are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  * this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote products
19  * derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30  * OF SUCH DAMAGE.
31  *
32  * This file is part of the lwIP TCP/IP stack.
33  *
34  * Author: Adam Dunkels <adam@sics.se>
35  *
36  */
37 #ifndef LWIP_HDR_API_H
38 #define LWIP_HDR_API_H
39 
40 #include "lwip/opt.h"
41 
42 #if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
43 /* Note: Netconn API is always available when sockets are enabled -
44  * sockets are implemented on top of them */
45 
46 #include "lwip/arch.h"
47 #include "lwip/netbuf.h"
48 #include "lwip/sys.h"
49 #include "lwip/ip_addr.h"
50 #include "lwip/err.h"
51 
52 #ifdef __cplusplus
53 extern "C" {
54 #endif
55 
56 /* Throughout this file, IP addresses and port numbers are expected to be in
57  * the same byte order as in the corresponding pcb.
58  */
59 
60 /* Flags for netconn_write (u8_t) */
61 #define NETCONN_NOFLAG 0x00
62 #define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */
63 #define NETCONN_COPY 0x01
64 #define NETCONN_MORE 0x02
65 #define NETCONN_DONTBLOCK 0x04
66 #define NETCONN_NOAUTORCVD 0x08 /* prevent netconn_recv_data_tcp() from updating the tcp window - must be done manually via netconn_tcp_recvd() */
67 #define NETCONN_NOFIN 0x10 /* upper layer already received data, leave FIN in queue until called again */
68 
69 /* Flags for struct netconn.flags (u8_t) */
70 /** This netconn had an error, don't block on recvmbox/acceptmbox any more */
71 #define NETCONN_FLAG_MBOXCLOSED 0x01
72 /** Should this netconn avoid blocking? */
73 #define NETCONN_FLAG_NON_BLOCKING 0x02
74 /** Was the last connect action a non-blocking one? */
75 #define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04
76 #if LWIP_NETCONN_FULLDUPLEX
77  /** The mbox of this netconn is being deallocated, don't use it anymore */
78 #define NETCONN_FLAG_MBOXINVALID 0x08
79 #endif /* LWIP_NETCONN_FULLDUPLEX */
80 /** If a nonblocking write has been rejected before, poll_tcp needs to
81  check if the netconn is writable again */
82 #define NETCONN_FLAG_CHECK_WRITESPACE 0x10
83 #if LWIP_IPV6
84 /** If this flag is set then only IPv6 communication is allowed on the
85  netconn. As per RFC#3493 this features defaults to OFF allowing
86  dual-stack usage by default. */
87 #define NETCONN_FLAG_IPV6_V6ONLY 0x20
88 #endif /* LWIP_IPV6 */
89 #if LWIP_NETBUF_RECVINFO
90 /** Received packet info will be recorded for this netconn */
91 #define NETCONN_FLAG_PKTINFO 0x40
92 #endif /* LWIP_NETBUF_RECVINFO */
93 /** A FIN has been received but not passed to the application yet */
94 #define NETCONN_FIN_RX_PENDING 0x80
95 
96 /* Helpers to process several netconn_types by the same code */
97 #define NETCONNTYPE_GROUP(t) ((t)&0xF0)
98 #define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0)
99 #if LWIP_IPV6
100 #define NETCONN_TYPE_IPV6 0x08
101 #define NETCONNTYPE_ISIPV6(t) (((t)&NETCONN_TYPE_IPV6) != 0)
102 #define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE)
103 #define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM)
104 #else /* LWIP_IPV6 */
105 #define NETCONNTYPE_ISIPV6(t) (0)
106 #define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE)
107 #define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM)
108 #endif /* LWIP_IPV6 */
109 
110 /** @ingroup netconn_common
111  * Protocol family and type of the netconn
112  */
113 enum netconn_type {
114  NETCONN_INVALID = 0,
115  /** TCP IPv4 */
116  NETCONN_TCP = 0x10,
117 #if LWIP_IPV6
118  /** TCP IPv6 */
119  NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */,
120 #endif /* LWIP_IPV6 */
121  /** UDP IPv4 */
122  NETCONN_UDP = 0x20,
123  /** UDP IPv4 lite */
124  NETCONN_UDPLITE = 0x21,
125  /** UDP IPv4 no checksum */
126  NETCONN_UDPNOCHKSUM = 0x22,
127 
128 #if LWIP_IPV6
129  /** UDP IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */
130  NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */,
131  /** UDP IPv6 lite (dual-stack by default, unless you call @ref netconn_set_ipv6only) */
132  NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */,
133  /** UDP IPv6 no checksum (dual-stack by default, unless you call @ref netconn_set_ipv6only) */
134  NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */,
135 #endif /* LWIP_IPV6 */
136 
137  /** Raw connection IPv4 */
138  NETCONN_RAW = 0x40
139 #if LWIP_IPV6
140  /** Raw connection IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */
141  , NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */
142 #endif /* LWIP_IPV6 */
143 };
144 
145 /** Current state of the netconn. Non-TCP netconns are always
146  * in state NETCONN_NONE! */
147 enum netconn_state {
148  NETCONN_NONE,
149  NETCONN_WRITE,
150  NETCONN_LISTEN,
151  NETCONN_CONNECT,
152  NETCONN_CLOSE
153 };
154 
155 /** Used to inform the callback function about changes
156  *
157  * Event explanation:
158  *
159  * In the netconn implementation, there are three ways to block a client:
160  *
161  * - accept mbox (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); in netconn_accept())
162  * - receive mbox (sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); in netconn_recv_data())
163  * - send queue is full (sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); in lwip_netconn_do_write())
164  *
165  * The events have to be seen as events signaling the state of these mboxes/semaphores. For non-blocking
166  * connections, you need to know in advance whether a call to a netconn function call would block or not,
167  * and these events tell you about that.
168  *
169  * RCVPLUS events say: Safe to perform a potentially blocking call call once more.
170  * They are counted in sockets - three RCVPLUS events for accept mbox means you are safe
171  * to call netconn_accept 3 times without being blocked.
172  * Same thing for receive mbox.
173  *
174  * RCVMINUS events say: Your call to to a possibly blocking function is "acknowledged".
175  * Socket implementation decrements the counter.
176  *
177  * For TX, there is no need to count, its merely a flag. SENDPLUS means you may send something.
178  * SENDPLUS occurs when enough data was delivered to peer so netconn_send() can be called again.
179  * A SENDMINUS event occurs when the next call to a netconn_send() would be blocking.
180  */
181 enum netconn_evt {
182  NETCONN_EVT_RCVPLUS,
183  NETCONN_EVT_RCVMINUS,
184  NETCONN_EVT_SENDPLUS,
185  NETCONN_EVT_SENDMINUS,
186  NETCONN_EVT_ERROR
187 };
188 
189 #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
190 /** Used for netconn_join_leave_group() */
191 enum netconn_igmp {
192  NETCONN_JOIN,
193  NETCONN_LEAVE
194 };
195 #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
196 
197 #if LWIP_DNS
198 /* Used for netconn_gethostbyname_addrtype(), these should match the DNS_ADDRTYPE defines in dns.h */
199 #define NETCONN_DNS_DEFAULT NETCONN_DNS_IPV4_IPV6
200 #define NETCONN_DNS_IPV4 0
201 #define NETCONN_DNS_IPV6 1
202 #define NETCONN_DNS_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */
203 #define NETCONN_DNS_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */
204 #endif /* LWIP_DNS */
205 
206 /* forward-declare some structs to avoid to include their headers */
207 struct ip_pcb;
208 struct tcp_pcb;
209 struct udp_pcb;
210 struct raw_pcb;
211 struct netconn;
212 struct api_msg;
213 
214 /** A callback prototype to inform about events for a netconn */
215 typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len);
216 
217 /** A netconn descriptor */
218 struct netconn {
219  /** type of the netconn (TCP, UDP or RAW) */
220  enum netconn_type type;
221  /** current state of the netconn */
222  enum netconn_state state;
223  /** the lwIP internal protocol control block */
224  union {
225  struct ip_pcb *ip;
226  struct tcp_pcb *tcp;
227  struct udp_pcb *udp;
228  struct raw_pcb *raw;
229  } pcb;
230  /** the last asynchronous unreported error this netconn had */
231  err_t pending_err;
232 #if !LWIP_NETCONN_SEM_PER_THREAD
233  /** sem that is used to synchronously execute functions in the core context */
234  sys_sem_t op_completed;
235 #endif
236  /** mbox where received packets are stored until they are fetched
237  by the netconn application thread (can grow quite big) */
238  sys_mbox_t recvmbox;
239 #if LWIP_TCP
240  /** mbox where new connections are stored until processed
241  by the application thread */
242  sys_mbox_t acceptmbox;
243 #endif /* LWIP_TCP */
244 #if LWIP_NETCONN_FULLDUPLEX
245  /** number of threads waiting on an mbox. This is required to unblock
246  all threads when closing while threads are waiting. */
247  int mbox_threads_waiting;
248 #endif
249  /** only used for socket layer */
250 #if LWIP_SOCKET
251  int socket;
252 #endif /* LWIP_SOCKET */
253 #if LWIP_SO_SNDTIMEO
254  /** timeout to wait for sending data (which means enqueueing data for sending
255  in internal buffers) in milliseconds */
256  s32_t send_timeout;
257 #endif /* LWIP_SO_RCVTIMEO */
258 #if LWIP_SO_RCVTIMEO
259  /** timeout in milliseconds to wait for new data to be received
260  (or connections to arrive for listening netconns) */
261  u32_t recv_timeout;
262 #endif /* LWIP_SO_RCVTIMEO */
263 #if LWIP_SO_RCVBUF
264  /** maximum amount of bytes queued in recvmbox
265  not used for TCP: adjust TCP_WND instead! */
266  int recv_bufsize;
267  /** number of bytes currently in recvmbox to be received,
268  tested against recv_bufsize to limit bytes on recvmbox
269  for UDP and RAW, used for FIONREAD */
270  int recv_avail;
271 #endif /* LWIP_SO_RCVBUF */
272 #if LWIP_SO_LINGER
273  /** values <0 mean linger is disabled, values > 0 are seconds to linger */
274  s16_t linger;
275 #endif /* LWIP_SO_LINGER */
276  /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
277  u8_t flags;
278 #if LWIP_TCP
279  /** TCP: when data passed to netconn_write doesn't fit into the send buffer,
280  this temporarily stores the message.
281  Also used during connect and close. */
282  struct api_msg *current_msg;
283 #endif /* LWIP_TCP */
284  /** A callback function that is informed about events for this netconn */
285  netconn_callback callback;
286 };
287 
288 /** This vector type is passed to @ref netconn_write_vectors_partly to send
289  * multiple buffers at once.
290  * ATTENTION: This type has to directly map struct iovec since one is casted
291  * into the other!
292  */
293 struct netvector {
294  /** pointer to the application buffer that contains the data to send */
295  const void *ptr;
296  /** size of the application data to send */
297  size_t len;
298 };
299 
300 /** Register an Network connection event */
301 #define API_EVENT(c,e,l) if (c->callback) { \
302  (*c->callback)(c, e, l); \
303  }
304 
305 /* Network connection functions: */
306 
307 /** @ingroup netconn_common
308  * Create new netconn connection
309  * @param t @ref netconn_type */
310 #define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL)
311 #define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c)
312 struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto,
313  netconn_callback callback);
314 err_t netconn_prepare_delete(struct netconn *conn);
315 err_t netconn_delete(struct netconn *conn);
316 /** Get the type of a netconn (as enum netconn_type). */
317 #define netconn_type(conn) (conn->type)
318 
319 err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr,
320  u16_t *port, u8_t local);
321 /** @ingroup netconn_common */
322 #define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0)
323 /** @ingroup netconn_common */
324 #define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1)
325 
326 err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port);
327 err_t netconn_bind_if(struct netconn *conn, u8_t if_idx);
328 err_t netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port);
329 err_t netconn_disconnect (struct netconn *conn);
330 err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog);
331 /** @ingroup netconn_tcp */
332 #define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG)
333 err_t netconn_accept(struct netconn *conn, struct netconn **new_conn);
334 err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf);
335 err_t netconn_recv_udp_raw_netbuf(struct netconn *conn, struct netbuf **new_buf);
336 err_t netconn_recv_udp_raw_netbuf_flags(struct netconn *conn, struct netbuf **new_buf, u8_t apiflags);
337 err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf);
338 err_t netconn_recv_tcp_pbuf_flags(struct netconn *conn, struct pbuf **new_buf, u8_t apiflags);
339 err_t netconn_tcp_recvd(struct netconn *conn, size_t len);
340 err_t netconn_sendto(struct netconn *conn, struct netbuf *buf,
341  const ip_addr_t *addr, u16_t port);
342 err_t netconn_send(struct netconn *conn, struct netbuf *buf);
343 err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
344  u8_t apiflags, size_t *bytes_written);
345 err_t netconn_write_vectors_partly(struct netconn *conn, struct netvector *vectors, u16_t vectorcnt,
346  u8_t apiflags, size_t *bytes_written);
347 /** @ingroup netconn_tcp */
348 #define netconn_write(conn, dataptr, size, apiflags) \
349  netconn_write_partly(conn, dataptr, size, apiflags, NULL)
350 err_t netconn_close(struct netconn *conn);
351 err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx);
352 
353 #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
354 err_t netconn_join_leave_group(struct netconn *conn, const ip_addr_t *multiaddr,
355  const ip_addr_t *netif_addr, enum netconn_igmp join_or_leave);
356 err_t netconn_join_leave_group_netif(struct netconn *conn, const ip_addr_t *multiaddr,
357  u8_t if_idx, enum netconn_igmp join_or_leave);
358 #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
359 #if LWIP_DNS
360 #if LWIP_IPV4 && LWIP_IPV6
361 err_t netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype);
362 #define netconn_gethostbyname(name, addr) netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_DEFAULT)
363 #else /* LWIP_IPV4 && LWIP_IPV6 */
364 err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
365 #define netconn_gethostbyname_addrtype(name, addr, dns_addrtype) netconn_gethostbyname(name, addr)
366 #endif /* LWIP_IPV4 && LWIP_IPV6 */
367 #endif /* LWIP_DNS */
368 
369 err_t netconn_err(struct netconn *conn);
370 #define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
371 
372 #define netconn_set_flags(conn, set_flags) do { (conn)->flags = (u8_t)((conn)->flags | (set_flags)); } while(0)
373 #define netconn_clear_flags(conn, clr_flags) do { (conn)->flags = (u8_t)((conn)->flags & (u8_t)(~(clr_flags) & 0xff)); } while(0)
374 #define netconn_is_flag_set(conn, flag) (((conn)->flags & (flag)) != 0)
375 
376 /** Set the blocking status of netconn calls (@todo: write/send is missing) */
377 #define netconn_set_nonblocking(conn, val) do { if(val) { \
378  netconn_set_flags(conn, NETCONN_FLAG_NON_BLOCKING); \
379 } else { \
380  netconn_clear_flags(conn, NETCONN_FLAG_NON_BLOCKING); }} while(0)
381 /** Get the blocking status of netconn calls (@todo: write/send is missing) */
382 #define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0)
383 
384 #if LWIP_IPV6
385 /** @ingroup netconn_common
386  * TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY)
387  */
388 #define netconn_set_ipv6only(conn, val) do { if(val) { \
389  netconn_set_flags(conn, NETCONN_FLAG_IPV6_V6ONLY); \
390 } else { \
391  netconn_clear_flags(conn, NETCONN_FLAG_IPV6_V6ONLY); }} while(0)
392 /** @ingroup netconn_common
393  * TCP: Get the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY)
394  */
395 #define netconn_get_ipv6only(conn) (((conn)->flags & NETCONN_FLAG_IPV6_V6ONLY) != 0)
396 #endif /* LWIP_IPV6 */
397 
398 #if LWIP_SO_SNDTIMEO
399 /** Set the send timeout in milliseconds */
400 #define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout))
401 /** Get the send timeout in milliseconds */
402 #define netconn_get_sendtimeout(conn) ((conn)->send_timeout)
403 #endif /* LWIP_SO_SNDTIMEO */
404 #if LWIP_SO_RCVTIMEO
405 /** Set the receive timeout in milliseconds */
406 #define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout))
407 /** Get the receive timeout in milliseconds */
408 #define netconn_get_recvtimeout(conn) ((conn)->recv_timeout)
409 #endif /* LWIP_SO_RCVTIMEO */
410 #if LWIP_SO_RCVBUF
411 /** Set the receive buffer in bytes */
412 #define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize))
413 /** Get the receive buffer in bytes */
414 #define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize)
415 #endif /* LWIP_SO_RCVBUF*/
416 
417 #if LWIP_NETCONN_SEM_PER_THREAD
418 void netconn_thread_init(void);
419 void netconn_thread_cleanup(void);
420 #else /* LWIP_NETCONN_SEM_PER_THREAD */
421 #define netconn_thread_init()
422 #define netconn_thread_cleanup()
423 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
424 
425 #ifdef __cplusplus
426 }
427 #endif
428 
429 #endif /* LWIP_NETCONN || LWIP_SOCKET */
430 
431 #endif /* LWIP_HDR_API_H */
OS abstraction layer.
lwIP Options Configuration
Callback< R(ArgTs...)> callback(R(*func)(ArgTs...)=nullptr) noexcept
Create a callback class with type inferred from the arguments.
Definition: Callback.h:678
Main packet buffer struct.
lwIP Error codes
IP address structure for passing IP addresses by value.
Definition: nsapi_types.h:237
netbuf API (for netconn API)
Support for different processor and compiler architectures.
IP address API (common IPv4 and IPv6)
Definition: ip.h:91
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.