Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
LWIPStack.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #ifndef LWIPSTACK_H_ 00018 #define LWIPSTACK_H_ 00019 00020 #include "lwip/tcpip.h" 00021 #include "lwip/tcp.h" 00022 #include "lwip/ip.h" 00023 #include "lwip/api.h" 00024 #include "netif/etharp.h" 00025 #include "lwip/ethip6.h" 00026 #include "netsocket/nsapi_types.h" 00027 #include "netsocket/EMAC.h" 00028 #include "netsocket/OnboardNetworkStack.h" 00029 #include "LWIPMemoryManager.h" 00030 00031 00032 class LWIP : public OnboardNetworkStack, private mbed::NonCopyable<LWIP> { 00033 public: 00034 00035 static LWIP &get_instance(); 00036 00037 class Interface : public OnboardNetworkStack::Interface { 00038 public: 00039 /** Connect the interface to the network 00040 * 00041 * Sets up a connection on specified network interface, using DHCP or provided network details. If the @a dhcp is set to 00042 * true all the remaining parameters are ignored. 00043 * 00044 * @param dhcp true if the network details should be acquired using DHCP 00045 * @param ip IP address to be used for the interface as "W:X:Y:Z" or NULL 00046 * @param netmask Net mask to be used for the interface as "W:X:Y:Z" or NULL 00047 * @param gw Gateway address to be used for the interface as "W:X:Y:Z" or NULL 00048 * @param stack Allow manual selection of IPv4 and/or IPv6. 00049 * @param blocking Specify whether bringup blocks for connection completion. 00050 * @return NSAPI_ERROR_OK on success, or error code 00051 */ 00052 virtual nsapi_error_t bringup(bool dhcp, const char *ip, 00053 const char *netmask, const char *gw, 00054 nsapi_ip_stack_t stack = DEFAULT_STACK, 00055 bool blocking = true 00056 ); 00057 00058 /** Disconnect interface from the network 00059 * 00060 * After this call the network interface is inactive, to use it again user needs to call @a mbed_ipstack_bringup again. 00061 * 00062 * @return NSAPI_ERROR_OK on success, or error code 00063 */ 00064 virtual nsapi_error_t bringdown(); 00065 00066 /** Register callback for status reporting 00067 * 00068 * The specified status callback function will be called on status changes 00069 * on the network. The parameters on the callback are the event type and 00070 * event-type dependent reason parameter. 00071 * 00072 * @param status_cb The callback for status changes 00073 */ 00074 virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb); 00075 00076 /** Get the connection status 00077 * 00078 * @return The connection status according to ConnectionStatusType 00079 */ 00080 virtual nsapi_connection_status_t get_connection_status() const; 00081 00082 /** Return MAC address of the network interface 00083 * 00084 * @return MAC address as "V:W:X:Y:Z" 00085 */ 00086 virtual char *get_mac_address(char *buf, nsapi_size_t buflen); 00087 00088 /** Copies IP address of the network interface to user supplied buffer 00089 * 00090 * @param emac EMAC HAL implementation for this network interface 00091 * @param buf buffer to which IP address will be copied as "W:X:Y:Z" 00092 * @param buflen size of supplied buffer 00093 * @return Pointer to a buffer, or NULL if the buffer is too small 00094 */ 00095 virtual char *get_ip_address(char *buf, nsapi_size_t buflen); 00096 00097 /** Copies netmask of the network interface to user supplied buffer 00098 * 00099 * @param buf buffer to which netmask will be copied as "W:X:Y:Z" 00100 * @param buflen size of supplied buffer 00101 * @return Pointer to a buffer, or NULL if the buffer is too small 00102 */ 00103 virtual char *get_netmask(char *buf, nsapi_size_t buflen); 00104 00105 /** Copies gateway address of the network interface to user supplied buffer 00106 * 00107 * @param buf buffer to which gateway address will be copied as "W:X:Y:Z" 00108 * @param buflen size of supplied buffer 00109 * @return Pointer to a buffer, or NULL if the buffer is too small 00110 */ 00111 virtual char *get_gateway(char *buf, nsapi_size_t buflen); 00112 00113 private: 00114 friend LWIP; 00115 00116 Interface(); 00117 00118 nsapi_error_t set_dhcp(); 00119 static void netif_link_irq(struct netif *netif); 00120 static void netif_status_irq(struct netif *netif); 00121 static Interface *our_if_from_netif(struct netif *netif); 00122 00123 #if LWIP_ETHERNET 00124 static err_t emac_low_level_output(struct netif *netif, struct pbuf *p); 00125 void emac_input(emac_mem_buf_t *buf); 00126 void emac_state_change(bool up); 00127 #if LWIP_IGMP 00128 static err_t emac_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, enum netif_mac_filter_action action); 00129 #endif 00130 #if LWIP_IPV6_MLD 00131 static err_t emac_mld_mac_filter(struct netif *netif, const ip6_addr_t *group, enum netif_mac_filter_action action); 00132 #endif 00133 00134 static err_t emac_if_init(struct netif *netif); 00135 #endif 00136 00137 union { 00138 #if LWIP_ETHERNET 00139 EMAC *emac; /**< HW specific emac implementation */ 00140 #endif 00141 void *hw; /**< alternative implementation pointer - used for PPP */ 00142 }; 00143 00144 os_semaphore_t linked_sem; 00145 osSemaphoreId_t linked; 00146 os_semaphore_t unlinked_sem; 00147 osSemaphoreId_t unlinked; 00148 os_semaphore_t has_any_addr_sem; 00149 osSemaphoreId_t has_any_addr; 00150 #define HAS_ANY_ADDR 1 00151 #if PREF_ADDR_TIMEOUT 00152 os_semaphore_t has_pref_addr_sem; 00153 osSemaphoreId_t has_pref_addr; 00154 #define HAS_PREF_ADDR 2 00155 #endif 00156 #if BOTH_ADDR_TIMEOUT 00157 os_semaphore_t has_both_addr_sem; 00158 osSemaphoreId_t has_both_addr; 00159 #define HAS_BOTH_ADDR 4 00160 #endif 00161 char has_addr_state; 00162 nsapi_connection_status_t connected; 00163 bool dhcp_started; 00164 bool dhcp_has_to_be_set; 00165 bool blocking; 00166 bool ppp; 00167 mbed::Callback<void(nsapi_event_t, intptr_t)> client_callback; 00168 struct netif netif; 00169 static Interface *list; 00170 Interface *next; 00171 LWIPMemoryManager *memory_manager; 00172 }; 00173 00174 /** Register a network interface with the IP stack 00175 * 00176 * Connects EMAC layer with the IP stack and initializes all the required infrastructure. 00177 * This function should be called only once for each available interface. 00178 * 00179 * @param emac EMAC HAL implementation for this network interface 00180 * @param default_if true if the interface should be treated as the default one 00181 * @param[out] interface_out pointer to stack interface object controlling the EMAC 00182 * @return NSAPI_ERROR_OK on success, or error code 00183 */ 00184 virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out); 00185 00186 /** Register a PPP interface with the IP stack 00187 * 00188 * Connects PPP layer with the IP stack and initializes all the required infrastructure. 00189 * This function should be called only once for each available interface. 00190 * 00191 * This is an internal function that links ppp_lwip.cpp to mbed_ipstack_lwip.cpp, 00192 * once a driver starts it via the nsapi_ppp.h API. 00193 * 00194 * Ultimately the nsapi_ppp.h API will be deprecated, and there will be a 00195 * mbed_ipstack_add_ppp_interface() replacing nsapi_ppp_connect(). 00196 * 00197 * @param pcb PPP implementation specific user data; will be passed to PPP callbacks 00198 * @param default_if true if the interface should be treated as the default one 00199 * @param stack Allow manual selection of IPv4 and/or IPv6 00200 * @param[out] interface_out set to interface handle that must be passed to subsequent mbed_stack calls 00201 * @return NSAPI_ERROR_OK on success, or error code 00202 */ 00203 nsapi_error_t _add_ppp_interface(void *pcb, bool default_if, nsapi_ip_stack_t stack, LWIP::Interface **interface_out); 00204 00205 /** Get a domain name server from a list of servers to query 00206 * 00207 * Returns a DNS server address for a index. If returns error no more 00208 * DNS servers to read. 00209 * 00210 * @param index Index of the DNS server, starts from zero 00211 * @param address Destination for the host address 00212 * @return 0 on success, negative error code on failure 00213 */ 00214 virtual nsapi_error_t get_dns_server(int index, SocketAddress *address); 00215 00216 /** Get the local IP address 00217 * 00218 * @return Null-terminated representation of the local IP address 00219 * or null if not yet connected 00220 */ 00221 virtual const char *get_ip_address(); 00222 00223 protected: 00224 LWIP(); 00225 virtual ~LWIP() {} 00226 00227 /** Opens a socket 00228 * 00229 * Creates a network socket and stores it in the specified handle. 00230 * The handle must be passed to following calls on the socket. 00231 * 00232 * A stack may have a finite number of sockets, in this case 00233 * NSAPI_ERROR_NO_SOCKET is returned if no socket is available. 00234 * 00235 * @param handle Destination for the handle to a newly created socket 00236 * @param proto Protocol of socket to open, NSAPI_TCP or NSAPI_UDP 00237 * @return 0 on success, negative error code on failure 00238 */ 00239 virtual nsapi_error_t socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto); 00240 00241 /** Close the socket 00242 * 00243 * Closes any open connection and deallocates any memory associated 00244 * with the socket. 00245 * 00246 * @param handle Socket handle 00247 * @return 0 on success, negative error code on failure 00248 */ 00249 virtual nsapi_error_t socket_close(nsapi_socket_t handle); 00250 00251 /** Bind a specific address to a socket 00252 * 00253 * Binding a socket specifies the address and port on which to recieve 00254 * data. If the IP address is zeroed, only the port is bound. 00255 * 00256 * @param handle Socket handle 00257 * @param address Local address to bind 00258 * @return 0 on success, negative error code on failure. 00259 */ 00260 virtual nsapi_error_t socket_bind(nsapi_socket_t handle, const SocketAddress &address); 00261 00262 /** Listen for connections on a TCP socket 00263 * 00264 * Marks the socket as a passive socket that can be used to accept 00265 * incoming connections. 00266 * 00267 * @param handle Socket handle 00268 * @param backlog Number of pending connections that can be queued 00269 * simultaneously 00270 * @return 0 on success, negative error code on failure 00271 */ 00272 virtual nsapi_error_t socket_listen(nsapi_socket_t handle, int backlog); 00273 00274 /** Connects TCP socket to a remote host 00275 * 00276 * Initiates a connection to a remote server specified by the 00277 * indicated address. 00278 * 00279 * @param handle Socket handle 00280 * @param address The SocketAddress of the remote host 00281 * @return 0 on success, negative error code on failure 00282 */ 00283 virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address); 00284 00285 /** Accepts a connection on a TCP socket 00286 * 00287 * The server socket must be bound and set to listen for connections. 00288 * On a new connection, creates a network socket and stores it in the 00289 * specified handle. The handle must be passed to following calls on 00290 * the socket. 00291 * 00292 * A stack may have a finite number of sockets, in this case 00293 * NSAPI_ERROR_NO_SOCKET is returned if no socket is available. 00294 * 00295 * This call is non-blocking. If accept would block, 00296 * NSAPI_ERROR_WOULD_BLOCK is returned immediately. 00297 * 00298 * @param server Socket handle to server to accept from 00299 * @param handle Destination for a handle to the newly created socket 00300 * @param address Destination for the remote address or NULL 00301 * @return 0 on success, negative error code on failure 00302 */ 00303 virtual nsapi_error_t socket_accept(nsapi_socket_t server, 00304 nsapi_socket_t *handle, SocketAddress *address=0); 00305 00306 /** Send data over a TCP socket 00307 * 00308 * The socket must be connected to a remote host. Returns the number of 00309 * bytes sent from the buffer. 00310 * 00311 * This call is non-blocking. If send would block, 00312 * NSAPI_ERROR_WOULD_BLOCK is returned immediately. 00313 * 00314 * @param handle Socket handle 00315 * @param data Buffer of data to send to the host 00316 * @param size Size of the buffer in bytes 00317 * @return Number of sent bytes on success, negative error 00318 * code on failure 00319 */ 00320 virtual nsapi_size_or_error_t socket_send(nsapi_socket_t handle, 00321 const void *data, nsapi_size_t size); 00322 00323 /** Receive data over a TCP socket 00324 * 00325 * The socket must be connected to a remote host. Returns the number of 00326 * bytes received into the buffer. 00327 * 00328 * This call is non-blocking. If recv would block, 00329 * NSAPI_ERROR_WOULD_BLOCK is returned immediately. 00330 * 00331 * @param handle Socket handle 00332 * @param data Destination buffer for data received from the host 00333 * @param size Size of the buffer in bytes 00334 * @return Number of received bytes on success, negative error 00335 * code on failure 00336 */ 00337 virtual nsapi_size_or_error_t socket_recv(nsapi_socket_t handle, 00338 void *data, nsapi_size_t size); 00339 00340 /** Send a packet over a UDP socket 00341 * 00342 * Sends data to the specified address. Returns the number of bytes 00343 * sent from the buffer. 00344 * 00345 * This call is non-blocking. If sendto would block, 00346 * NSAPI_ERROR_WOULD_BLOCK is returned immediately. 00347 * 00348 * @param handle Socket handle 00349 * @param address The SocketAddress of the remote host 00350 * @param data Buffer of data to send to the host 00351 * @param size Size of the buffer in bytes 00352 * @return Number of sent bytes on success, negative error 00353 * code on failure 00354 */ 00355 virtual nsapi_size_or_error_t socket_sendto(nsapi_socket_t handle, const SocketAddress &address, 00356 const void *data, nsapi_size_t size); 00357 00358 /** Receive a packet over a UDP socket 00359 * 00360 * Receives data and stores the source address in address if address 00361 * is not NULL. Returns the number of bytes received into the buffer. 00362 * 00363 * This call is non-blocking. If recvfrom would block, 00364 * NSAPI_ERROR_WOULD_BLOCK is returned immediately. 00365 * 00366 * @param handle Socket handle 00367 * @param address Destination for the source address or NULL 00368 * @param buffer Destination buffer for data received from the host 00369 * @param size Size of the buffer in bytes 00370 * @return Number of received bytes on success, negative error 00371 * code on failure 00372 */ 00373 virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, 00374 void *buffer, nsapi_size_t size); 00375 00376 /** Register a callback on state change of the socket 00377 * 00378 * The specified callback will be called on state changes such as when 00379 * the socket can recv/send/accept successfully and on when an error 00380 * occurs. The callback may also be called spuriously without reason. 00381 * 00382 * The callback may be called in an interrupt context and should not 00383 * perform expensive operations such as recv/send calls. 00384 * 00385 * @param handle Socket handle 00386 * @param callback Function to call on state change 00387 * @param data Argument to pass to callback 00388 */ 00389 virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data); 00390 00391 /* Set stack-specific socket options 00392 * 00393 * The setsockopt allow an application to pass stack-specific hints 00394 * to the underlying stack. For unsupported options, 00395 * NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified. 00396 * 00397 * @param handle Socket handle 00398 * @param level Stack-specific protocol level 00399 * @param optname Stack-specific option identifier 00400 * @param optval Option value 00401 * @param optlen Length of the option value 00402 * @return 0 on success, negative error code on failure 00403 */ 00404 virtual nsapi_error_t setsockopt(nsapi_socket_t handle, int level, 00405 int optname, const void *optval, unsigned optlen); 00406 00407 /* Get stack-specific socket options 00408 * 00409 * The getstackopt allow an application to retrieve stack-specific hints 00410 * from the underlying stack. For unsupported options, 00411 * NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified. 00412 * 00413 * @param handle Socket handle 00414 * @param level Stack-specific protocol level 00415 * @param optname Stack-specific option identifier 00416 * @param optval Destination for option value 00417 * @param optlen Length of the option value 00418 * @return 0 on success, negative error code on failure 00419 */ 00420 virtual nsapi_error_t getsockopt(nsapi_socket_t handle, int level, 00421 int optname, void *optval, unsigned *optlen); 00422 private: 00423 00424 /** Call in callback 00425 * 00426 * Callback is used to call the call in method of the network stack. 00427 */ 00428 typedef mbed::Callback<nsapi_error_t (int delay_ms, mbed::Callback<void()> user_cb)> call_in_callback_cb_t; 00429 00430 /** Get a call in callback 00431 * 00432 * Get a call in callback from the network stack context. 00433 * 00434 * Callback should not take more than 10ms to execute, otherwise it might 00435 * prevent underlying thread processing. A portable user of the callback 00436 * should not make calls to network operations due to stack size limitations. 00437 * The callback should not perform expensive operations such as socket recv/send 00438 * calls or blocking operations. 00439 * 00440 * @return Call in callback 00441 */ 00442 virtual call_in_callback_cb_t get_call_in_callback(); 00443 00444 /** Call a callback after a delay 00445 * 00446 * Call a callback from the network stack context after a delay. If function 00447 * returns error callback will not be called. 00448 * 00449 * @param delay Delay in milliseconds 00450 * @param func Callback to be called 00451 * @return 0 on success, negative error code on failure 00452 */ 00453 nsapi_error_t call_in(int delay, mbed::Callback<void()> func); 00454 00455 struct mbed_lwip_socket { 00456 bool in_use; 00457 00458 struct netconn *conn; 00459 struct netbuf *buf; 00460 u16_t offset; 00461 00462 void (*cb)(void *); 00463 void *data; 00464 00465 // Track multicast addresses subscribed to by this socket 00466 nsapi_ip_mreq_t *multicast_memberships; 00467 uint32_t multicast_memberships_count; 00468 uint32_t multicast_memberships_registry; 00469 }; 00470 00471 struct lwip_callback { 00472 unsigned int delay; 00473 mbed::Callback<void()> callback; 00474 }; 00475 00476 static nsapi_error_t err_remap(err_t err); 00477 static bool is_local_addr(const ip_addr_t *ip_addr); 00478 static const ip_addr_t *get_ip_addr(bool any_addr, const struct netif *netif); 00479 static const ip_addr_t *get_ipv4_addr(const struct netif *netif); 00480 static const ip_addr_t *get_ipv6_addr(const struct netif *netif); 00481 00482 static void add_dns_addr(struct netif *lwip_netif); 00483 00484 /* Static arena of sockets */ 00485 struct mbed_lwip_socket arena[MEMP_NUM_NETCONN]; 00486 void arena_init(void); 00487 struct mbed_lwip_socket *arena_alloc(); 00488 void arena_dealloc(struct mbed_lwip_socket *s); 00489 00490 static uint32_t next_registered_multicast_member(const struct mbed_lwip_socket *s, uint32_t index) { 00491 while (!(s->multicast_memberships_registry & (0x0001 << index))) { index++; } 00492 return index; 00493 } 00494 00495 static uint32_t next_free_multicast_member(const struct mbed_lwip_socket *s, uint32_t index) { 00496 while ((s->multicast_memberships_registry & (0x0001 << index))) { index++; } 00497 return index; 00498 } 00499 00500 static void set_multicast_member_registry_bit(struct mbed_lwip_socket *s, uint32_t index) { 00501 s->multicast_memberships_registry |= (0x0001 << index); 00502 } 00503 00504 static void clear_multicast_member_registry_bit(struct mbed_lwip_socket *s, uint32_t index) { 00505 s->multicast_memberships_registry &= ~(0x0001 << index); 00506 } 00507 static int32_t find_multicast_member(const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr); 00508 00509 static void socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len); 00510 00511 static void tcpip_init_irq(void *handle); 00512 static void tcpip_thread_callback(void *ptr); 00513 00514 char ip_address[40]; 00515 rtos::Semaphore tcpip_inited; 00516 Interface *default_interface; 00517 LWIPMemoryManager memory_manager; 00518 osThreadId tcpip_thread_id; 00519 rtos::Mutex adaptation; 00520 }; 00521 00522 #endif /* LWIPSTACK_H_ */
Generated on Tue Jul 12 2022 12:44:54 by
