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.
Dependencies: nRF51_Vdd TextLCD BME280
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 mbed_rtos_storage_semaphore_t linked_sem; 00145 osSemaphoreId_t linked; 00146 mbed_rtos_storage_semaphore_t unlinked_sem; 00147 osSemaphoreId_t unlinked; 00148 mbed_rtos_storage_semaphore_t has_any_addr_sem; 00149 osSemaphoreId_t has_any_addr; 00150 #define HAS_ANY_ADDR 1 00151 #if PREF_ADDR_TIMEOUT 00152 mbed_rtos_storage_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 mbed_rtos_storage_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 15:15:51 by
