diff options
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket')
25 files changed, 4537 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/README.md b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/README.md new file mode 100644 index 0000000..9ec0b8d --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/README.md @@ -0,0 +1,28 @@ +# Socket module + +The socket module contains the BSD socket implementation for the IoT SDK. The purpose of the socket +API is to + +* Provide a common API for all platforms +* Simplify porting of pc network applications + +The socket API hides details of the underlying transport, but supports proprietary extensions for +controlling configuration settings and using underlying transport layers. + +<pre> +socket/ + api/ - Public socket API headers + common/ - Common implementation of API and implementation code shared by all platforms (main socket API implementation, with hooks for different transports) + libraries/ - Generic libraries that are not tied to a specific platform + portdb/ - Port database to track and allocate socket ports + addr_util/ - Common address utilities + mbuf/ - Memory buffer utilities + transport/ - Transport/network stack hooks + ipv6/ - Nordic IPv6 stack transport hook + lwip/ - LwIP transport hook + test/ - Integration tests shared between transport stacks + platform/ - Platform specific code + ble/ - BLE specific code (only wrappers around sd_ble_app_evt_()) + config/ - Configuration socket implementations + medium/ - Medium configuration socket implementation +</pre> diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/arpa/inet.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/arpa/inet.h new file mode 100644 index 0000000..c1749d3 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/arpa/inet.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef SOCKET_ARPA_INET_H__ +#define SOCKET_ARPA_INET_H__ + +#include "socket_api.h" + +#endif diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/netinet/in.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/netinet/in.h new file mode 100644 index 0000000..bfcf881 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/netinet/in.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef SOCKET_NETINET_IN_H__ +#define SOCKET_NETINET_IN_H__ + +#include "socket_api.h" + +#endif diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/socket_api.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/socket_api.h new file mode 100644 index 0000000..37e50d4 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/socket_api.h @@ -0,0 +1,593 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file socket_api.h + * + * @defgroup iot_socket BSD Socket interface + * @ingroup iot_sdk_socket + * @{ + * @brief Nordic socket interface for IoT. + * + * @details This module provides the socket interface for writing IoT applications. The API is + * designed to be compatible with the POSIX/BSD socket interface for the purpose of + * making porting easy. The socket options API has been extended to support configuring + * Nordic BLE stack, tuning of RF parameters as well as security options. + */ +#ifndef SOCKET_API_H__ +#define SOCKET_API_H__ + +#include <stdint.h> + +#include "sdk_common.h" +#include "iot_defines.h" +#include "errno.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(__GNUC__) || (__GNUC__ == 0) +typedef int32_t ssize_t; +#else +#include <sys/types.h> +#ifdef __SES_ARM +typedef int32_t ssize_t; +#endif +#endif + +#ifndef htons +#define htons(x) HTONS(x) /**< Convert byte order from host to network (short). */ +#endif + +#ifndef htonl +#define htonl(x) HTONL(x) /**< Convert byte order from host to network (long). */ +#endif + +#ifndef ntohs +#define ntohs(x) NTOHS(x) /**< Convert byte order from network to host (short). */ +#endif + +#ifndef ntohl +#define ntohl(x) NTOHL(x) /**< Convert byte order from network to host (long). */ +#endif + +/**@defgroup socket_families Values for socket_family_t + * @ingroup iot_socket + * @{ + */ +#define AF_INET 2 /**< IPv4 socket family. */ +#define AF_INET6 10 /**< IPv6 socket family. */ +#if defined(NRF52) || defined(NRF52_SERIES) +#define AF_NRF_CFG 39 /**< nRF configuration socket.*/ +#endif +/**@} */ + +/**@defgroup socket_types Values for socket_type_t + * @ingroup iot_socket + * @{ + */ +#define SOCK_STREAM 1 /**< TCP socket type. */ +#define SOCK_DGRAM 2 /**< UDP socket type. */ +/**@} */ + +/**@defgroup socket_protocols Values for socket_protocol_t + * @ingroup iot_socket + * @{ + */ +#define IPPROTO_TCP 1 /**< Use TCP as transport protocol. */ +#define IPPROTO_UDP 2 /**< Use UDP as transport protocol. */ +/**@} */ + +/**@defgroup socket_send_recv_flags Socket send/recv flags + * @ingroup iot_socket + * @{ + */ +#define MSG_DONTROUTE 0x01 /**< Send only to hosts on directly connected networks. */ +#define MSG_DONTWAIT 0x02 /**< Enables non-blocking operation. */ +#define MSG_OOB 0x04 /**< Sends out-of-band data on sockets that support this. */ +#define MSG_PEEK 0x08 /**< Return data from the beginning of receive queue without removing data from the queue. */ +#define MSG_WAITALL 0x10 /**< Request a blocking operation until the request is satisfied. */ +/**@} */ + +#if defined(NRF52) || defined(NRF52_SERIES) +/** + * @defgroup socket_option_levels Values for socket_opt_lvl_t + * @ingroup iot_socket + * @{ + */ +#define SOL_SOCKET 1 /**< Standard socket options. */ +#define SOL_NRF_MEDIUM 2 /**< Nordic medium socket options. Use this to control medium parameters. */ +/**@} */ + +/**@defgroup socket_medium_options Medium socket option level types + * @ingroup iot_socket + * @{ + */ +#define MEDIUM_INIT_PARAMS 1 /**< Medium initialization parameters. */ +/**@} + */ +#endif + +/**@defgroup fcnt_commands fcntl commands + * @ingroup iot_socket + * @{ + */ +#define F_SETFL 1 /**< Set flag. */ +#define F_GETFL 2 /**< Get flag. */ +/**@} */ + +/**@defgroup fcnt_flags fcntl flags + * @ingroup iot_socket + * @{ + */ +#define O_NONBLOCK 0x01 /**< Use non-blocking I/O. */ +/**@} */ + +/** + * @brief Socket module size type. + */ +typedef uint32_t socklen_t; + +/** + * @brief Socket port type. + */ +typedef uint16_t in_port_t; + +/** + * @brief Structure specifying time interval. + */ +struct timeval +{ + uint32_t tv_sec; /**< Time interval seconds. */ + uint32_t tv_usec; /**< Time interval microseconds. */ +}; + +/** + * @brief Socket families. + * + * @details For a list of valid values, refer to @ref socket_families. + */ +typedef int socket_family_t; +typedef socket_family_t sa_family_t; + +/** + * @brief Socket types. + * + * @details For a list of valid values refer to @ref socket_types. + */ +typedef int socket_type_t; + +/** + * @brief Socket protocols. + * + * @details Use 0 if you do not want do specify socket protocol, which should be sufficient for most users. + * Other values are only provided for socket API compatibility, see @ref socket_protocols. + */ +typedef int socket_protocol_t; + +/** + * @if (IOT) + * @brief Socket option levels. + * + * @details For a list of valid values, refer to @ref socket_option_levels. + * @endif + */ +typedef int socket_opt_lvl_t; + +/** + * @brief Generic socket address. + * + * @details Only provided for API compatibility. + */ +struct sockaddr +{ + uint8_t sa_len; + socket_family_t sa_family; + char sa_data[]; +}; + +/** + * @brief IPv6 address. + */ +struct in6_addr +{ + uint8_t s6_addr[16]; +}; + +/** + * @brief IPv4 address. + */ +typedef uint32_t in_addr_t; + +/** + * @brief IPv4 address structure. + */ +struct in_addr +{ + in_addr_t s_addr; +}; + +/** + * @brief Global IPv6 any-address. + */ +extern const struct in6_addr in6addr_any; + +/** + * @brief Global IPv4 any-address. + */ +extern const struct in_addr inaddr_any; + +/** + * @brief Address record for IPv6 addresses. + * + * @details Contains the address and port of the host, as well as other socket options. All fields + * in this structure are compatible with the POSIX variant for API compatibility. + */ +struct sockaddr_in6 +{ + uint8_t sin6_len; /**< Length of this data structure. */ + sa_family_t sin6_family; /**< Socket family. */ + in_port_t sin6_port; /**< Port, in network byte order. */ + + uint32_t sin6_flowinfo; /**< IPv6 flow info parameters. Not used. */ + struct in6_addr sin6_addr; /**< IPv6 address. */ + uint32_t sin6_scope_id; /**< IPv6 scope ID. Not used. */ +}; + +/** + * @brief Address record for IPv4 addresses. + * + * @details Contains the address and port of the host. All fields + * in this structure are compatible with the POSIX variant for API compatibility. + */ +struct sockaddr_in +{ + uint8_t sin_len; /**< Length of this data structure. */ + sa_family_t sin_family; /**< Socket family. */ + in_port_t sin_port; /**< Port, in network byte order. */ + + struct in_addr sin_addr; /**< IPv4 address. */ +}; + +typedef struct sockaddr sockaddr_t; +typedef struct sockaddr_in6 sockaddr_in6_t; +typedef struct in6_addr in6_addr_t; +typedef struct sockaddr_in sockaddr_in_t; + +/** + * @brief Function for creating a socket. + * + * @details API to create a socket that can be used for network communication independently + * of lower protocol layers. + * + * @param[in] family The protocol family of the network protocol to use. Currently, only + * AF_INET6 is supported. + * @param[in] type The protocol type to use for this socket. + * @param[in] protocol The transport protocol to use for this socket. + * + * @return A non-negative socket descriptor on success, or -1 on error. + */ +int socket(socket_family_t family, socket_type_t type, socket_protocol_t protocol); + +/** + * @brief Function for closing a socket and freeing any resources held by it. + * + * @details If the socket is already closed, this function is a noop. + * + * @param[in] sock The socket to close. + * + * @return 0 on success, or -1 on error. + */ +int close(int sock); + +/** + * @brief Function for controlling file descriptor options. + * + * @details Set or get file descriptor options or flags. For a list of supported commands, refer to @ref fcnt_commands. + * For a list of supported flags, refer to @ref fcnt_flags. + * + * @param[in] fd The descriptor to set options on. + * @param[in] cmd The command class for options. + * @param[in] flags The flags to set. + */ +int fcntl(int fd, int cmd, int flags); + +/** + * @brief Function for connecting to an endpoint with a given address. + * + * @details The socket handle must be a valid handle that has not yet been connected. Running + * connect on a connected handle will return an error. + * + * @param[in] sock The socket to use for connection. + * @param[in] p_servaddr The address of the server to connect to. Currently, sockaddr_in6 is + * the only supported type. + * @param[in] addrlen The size of the p_servaddr argument. + * + * @return 0 on success, or -1 on error. + */ +int connect(int sock, const void * p_servaddr, socklen_t addrlen); + +/** + * @brief Function for sending data through a socket. + * + * @details By default, this function will block unless the O_NONBLOCK + * socket option has been set, OR MSG_DONTWAIT is passed as a flag. In that case, the + * method will return immediately. + * + * @param[in] sock The socket to write data to. + * @param[in] p_buff Buffer containing the data to send. + * @param[in] nbytes Size of data contained on p_buff. + * @param[in] flags Flags to control send behavior. + * + * @return The number of bytes that were sent on success, or -1 on error. + */ +ssize_t send(int sock, const void * p_buff, size_t nbytes, int flags); + +/** + * @brief Function for sending datagram through a socket. + * + * @details By default, this function will block if the lower layers are not able to process the + * packet, unless the O_NONBLOCK socket option has been set, OR MSG_DONTWAIT is passed as a flag. + * In that case, the method will return immediately. + * + * @param[in] sock The socket to write data to. + * @param[in] p_buff Buffer containing the data to send. + * @param[in] nbytes Size of data contained in p_buff. + * @param[in] flags Flags to control send behavior. + * @param[in] p_servaddr The address of the server to send to. Currently, sockaddr_in6 is + * the only supported type. + * @param[in] addrlen The size of the p_servaddr argument. + * + * @return The number of bytes that were sent on success, or -1 on error. + */ +ssize_t sendto(int sock, + const void * p_buff, + size_t nbytes, + int flags, + const void * p_servaddr, + socklen_t addrlen); + +/** + * @brief Function for writing data to a socket. See \ref send() for details. + * + * @param[in] sock The socket to write data to. + * @param[in] p_buff Buffer containing the data to send. + * @param[in] nbytes Size of data contained in p_buff. + * + * @return The number of bytes that were sent on success, or -1 on error. + */ +ssize_t write(int sock, const void * p_buff, size_t nbytes); + +/** + * @brief Function for receiving data on a socket. + * + * @details API for receiving data from a socket. By default, this function will block, unless the + * O_NONBLOCK socket option has been set, or MSG_DONTWAIT is passed as a flag. + * + * @param[in] sock The socket to receive data from. + * @param[out] p_buff Buffer to hold the data to be read. + * @param[in] nbytes Number of bytes to read. Should not be larger than the size of p_buff. + * @param[in] flags Flags to control receive behavior. + * + * @return The number of bytes that were read, or -1 on error. + */ +ssize_t recv(int sock, void * p_buff, size_t nbytes, int flags); + +/** + * @brief Function for receiving datagram on a socket. + * + * @details API for receiving data from a socket. By default, this function will block, unless the + * O_NONBLOCK socket option has been set, or MSG_DONTWAIT is passed as a flag. + * + * @param[in] sock The socket to receive data from. + * @param[out] p_buff Buffer to hold the data to be read. + * @param[in] nbytes Number of bytes to read. Should not be larger than the size of p_buff. + * @param[in] flags Flags to control receive behavior. + * @param[out] p_cliaddr Socket address that will be set to the client's address. + * @param[inout] p_addrlen The size of the p_cliaddr passed. Might be modified by the function. + * + * @return The number of bytes that were read, or -1 on error. + */ +ssize_t recvfrom(int sock, + void * p_buff, + size_t nbytes, + int flags, + void * p_cliaddr, + socklen_t * p_addrlen); + +/** + * @brief Function for reading data from a socket. See \ref recv() for details. + * + * @param[in] sock The socket to receive data from. + * @param[out] p_buff Buffer to hold the data to be read. + * @param[in] nbytes Number of bytes to read. Should not be larger than the size of p_buff. + * + * @return The number of bytes that were read, or -1 on error. + */ +ssize_t read(int sock, void * p_buff, size_t nbytes); + +/** + * @defgroup fd_set_api API for file descriptor set + * @ingroup iot_socket + * @details File descriptor sets are used as input to the select() function for doing I/O + * multiplexing. The maximum number of descriptors contained in a set is defined by + * FD_SETSIZE. + * + * @{ + */ +#ifndef FD_ZERO + +typedef uint32_t fd_set; +#define FD_ZERO(set) (*(set) = 0) /**< Clear the entire set. */ +#define FD_SET(fd, set) (*(set) |= (1u << (fd))) /**< Set a bit in the set. */ +#define FD_CLR(fd, set) (*(set) &= ~(1u << (fd))) /**< Clear a bit in the set. */ +#define FD_ISSET(fd, set) (*(set) & (1u << (fd))) /**< Check if a bit in the set is set. */ +#define FD_SETSIZE sizeof(fd_set) /**< The max size of a set. */ + +#endif +/**@} */ + +/** + * @brief Function for waiting for read, write, or exception events on a socket. + * + * @details Wait for a set of socket descriptors to be ready for reading, writing, or having + * exceptions. The set of socket descriptors is configured before calling this function. + * This function will block until any of the descriptors in the set has any of the required + * events. This function is mostly useful when using O_NONBLOCK or MSG_DONTWAIT options + * to enable async operation. + * + * @param[in] nfds The highest socket descriptor value contained in the sets. + * @param[inout] p_readset The set of descriptors for which to wait for read events. Set to NULL + * if not used. + * @param[inout] p_writeset The set of descriptors for which to wait for write events. Set to NULL + * if not used. + * @param[inout] p_exceptset The set of descriptors for which to wait for exception events. Set to + * NULL if not used. + * @param[in] p_timeout The timeout to use for select call. Set to NULL if waiting forever. + * + * @return The number of ready descriptors contained in the descriptor sets on success, or -1 on error. + */ +int select(int nfds, + fd_set * p_readset, + fd_set * p_writeset, + fd_set * p_exceptset, + const struct timeval * p_timeout); + +/** + * @brief Function for setting socket options for a given socket. + * + * @details The options are grouped by level, and the option value should be the expected for the + * given option, and the lifetime must be longer than that of the socket. + * + * @param[in] sock The socket for which to set the option. + * @param[in] level The level or group to which the option belongs. + * @param[in] optname The name of the socket option. + * @param[in] p_optval The value to be stored for this option. + * @param[in] optlen The size of p_optval. + * + * @return 0 on success, or -1 on error. + */ +int setsockopt(int sock, + socket_opt_lvl_t level, + int optname, + const void * p_optval, + socklen_t optlen); + +/** + * @brief Function for getting socket options for a given socket. + * + * @details The options are grouped by level, and the option value is the value described by the + * option name. + * + * @param[in] sock The socket for which to set the option. + * @param[in] level The level or group to which the option belongs. + * @param[in] optname The name of the socket option. + * @param[out] p_optval Pointer to the storage for the option value. + * @param[inout] p_optlen The size of p_optval. Can be modified to the actual size of p_optval. + * + * @return 0 on success, or -1 on error. + */ +int getsockopt(int sock, + socket_opt_lvl_t level, + int optname, + void * p_optval, + socklen_t * p_optlen); + +/** + * @brief Function for binding a socket to an address and port. + * + * @details The provided address must be supported by the socket protocol family. + * + * @param[in] sock The socket descriptor to bind. + * @param[in] p_myaddr The address to bind this socket to. + * @param[in] addrlen The size of p_myaddr. + * + * @return 0 on success, or -1 on error. + */ +int bind(int sock, const void * p_myaddr, socklen_t addrlen); + +/** + * @brief Function for marking a socket as listenable. + * + * @details Once a socket is marked as listenable, it cannot be unmarked. It is important to + * consider the backlog parameter, as it will affect how much memory your application will + * use in the worst case. + * + * @param[in] sock The socket descriptor on which to set the listening options. + * @param[in] backlog The max length of the queue of pending connections. A value of 0 means + * infinite. + * + * @return 0 on success, or -1 on error. + */ +int listen(int sock, int backlog); + +/** + * @brief Function for waiting for the next client to connect. + * + * @details This function will block if there are no clients attempting to connect. + * + * @param[in] sock The socket descriptor to use for waiting on client connections. + * @param[out] p_cliaddr Socket address that will be set to the client's address. + * @param[out] p_addrlen The size of the p_cliaddr passed. Might be modified by the function. + * + * @return A non-negative client descriptor on success, or -1 on error. + */ +int accept(int sock, void * p_cliaddr, socklen_t * p_addrlen); + +/** + * @brief Function for converting a human-readable IP address to a form usable by the socket API. + * + * @details This function will convert a string form of addresses and encode it into a byte array. + * + * @param[in] af Address family. Only AF_INET6 supported. + * @param[in] p_src Null-terminated string containing the address to convert. + * @param[out] p_dst Pointer to a struct in6_addr where the address will be stored. + * + * @return 1 on success, 0 if src does not contain a valid address, -1 if af is not a valid address + * family. + */ +int inet_pton(socket_family_t af, const char * p_src, void * p_dst); + +#ifdef __cplusplus +} +#endif + +#endif //SOCKET_API_H__ + +/**@} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/sys/select.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/sys/select.h new file mode 100644 index 0000000..3fb05fb --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/sys/select.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef SOCKET_SYS_SELECT_H__ +#define SOCKET_SYS_SELECT_H__ + +#include "socket_api.h" + +#endif diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/sys/socket.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/sys/socket.h new file mode 100644 index 0000000..c01fc3e --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/sys/socket.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef SOCKET_SYS_SOCKET_H__ +#define SOCKET_SYS_SOCKET_H__ + +#include "socket_api.h" + +#endif diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/unistd.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/unistd.h new file mode 100644 index 0000000..ac77bdf --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/api/unistd.h @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file unistd.h + * + * @defgroup iot_posix_unistd POSIX operating system API + * @ingroup iot_sdk_socket + * @{ + * @brief POSIX standard functions. + */ +#ifndef SOCKET_UNISTD_H__ +#define SOCKET_UNISTD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief POSIX sleep function. + * + * @note Uses busy looping nrf_delay. + * + * @param[in] seconds The number of seconds to sleep. + * + * @return The number of seconds slept. + */ +unsigned int sleep(unsigned int seconds); + +/** + * @brief POSIX usleep function. + * + * @note Uses busy looping nrf_delay. + * + * @param[in] useconds The number of microseconds to sleep. + * + * @return The number of microseconds slept. + */ +unsigned int usleep(unsigned int useconds); + +#ifdef __cplusplus +} +#endif + +#endif // SOCKET_UNISTD_H__ + +/**@} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/sleep.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/sleep.c new file mode 100644 index 0000000..94dd07a --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/sleep.c @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "unistd.h" +#include "nrf_delay.h" + +unsigned int sleep(unsigned int seconds) +{ + nrf_delay_ms(seconds * 1000); + return seconds; +} + +unsigned int usleep(unsigned int useconds) +{ + nrf_delay_ms(useconds / 1000); + return useconds; +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket.c new file mode 100644 index 0000000..fe7d6ca --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket.c @@ -0,0 +1,746 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nordic_common.h" +#include "sdk_common.h" +#include "sdk_config.h" +#include "nrf_sdm.h" +#include "app_scheduler.h" +#include "app_timer.h" +#include "iot_common.h" +#include "app_error.h" +#include "socket_api.h" +#include "socket_common.h" +#include "socket_trace.h" +#include "sdk_os.h" +#include "transport_if.h" +#include "portdb.h" +#include "errno.h" +#include "mem_manager.h" +#include "ipv6_parse.h" +#include "netinet/in.h" +#include "unistd.h" +#include "sdk_os.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_default_backends.h" + +#ifndef SOCKET_ENABLE_API_PARAM_CHECK +#define SOCKET_ENABLE_API_PARAM_CHECK 0 +#endif + +#include "socket_config.h" + +#if SOCKET_CONFIG_LOG_ENABLED == 1 + NRF_LOG_MODULE_REGISTER(); +#endif + +/** + * @defgroup api_param_check API Parameters check macros. + * + * @details Macros that verify parameters passed to the module in the APIs. These macros + * could be mapped to nothing in final versions of code to save execution and size. + * SOCKET_ENABLE_API_PARAM_CHECK should be set to 0 to disable these checks. + * + * @{ + */ +#if SOCKET_ENABLE_API_PARAM_CHECK == 1 + +/**@brief Macro to check is module is initialized before requesting one of the module procedures. */ +#define VERIFY_MODULE_IS_INITIALIZED() \ + do { \ + if (m_initialization_state == false) \ + { \ + return (SDK_ERR_MODULE_NOT_INITIALIZED | IOT_SOCKET_ERR_BASE);\ + } \ + } while (0) + + +/** + * @brief Verify NULL parameters are not passed to API by application. + */ +#define NULL_PARAM_CHECK(PARAM) \ + do { \ + if ((PARAM) == NULL) \ + { \ + set_errno(EFAULT); \ + return -1; \ + } \ + } while (0) + +/** + * @brief Verify socket id passed on the API by application is valid. + */ +#define VERIFY_SOCKET_ID(ID) \ + do { \ + if (((ID) < 0) || ((ID) >= NUM_SOCKETS)) \ + { \ + set_errno(EBADF); \ + return -1; \ + } \ + } while (0) + + +#else + +#define VERIFY_MODULE_IS_INITIALIZED() +#define NULL_PARAM_CHECK(PARAM) +#define VERIFY_SOCKET_ID(ID) +#endif + +/** @} */ +#define SOCKET_MUTEX_INIT() SDK_MUTEX_INIT(m_socket_mtx); +#define SOCKET_MUTEX_LOCK() SDK_MUTEX_LOCK(m_socket_mtx) +#define SOCKET_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_socket_mtx) +// note: one extra for configuration socket +#define NUM_SOCKETS SOCKET_MAX_SOCKET_COUNT + 1 + +SDK_MUTEX_DEFINE(m_socket_mtx) /**< Mutex for protecting m_socket_table (not individual entries). */ + +#define SCHED_QUEUE_SIZE 16 /**< Maximum number of events in the scheduler queue. */ +#define SCHED_MAX_EVENT_DATA_SIZE 192 /**< Maximum size of scheduler events. */ + +static bool m_initialization_state = false; /**< Variable to maintain module initialization state. */ +static volatile bool m_interface_up = false; /**< Interface state. */ +static socket_t m_socket_table[NUM_SOCKETS]; /**< Socket table. */ + +const struct in6_addr in6addr_any = { {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /**< IPv6 anycast address. */ + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u} }; + +#if defined (NRF_LOG_ENABLED) && (NRF_LOG_ENABLED == 1) + +void log_init(void) +{ + ret_code_t err_code = NRF_LOG_INIT(NULL); + APP_ERROR_CHECK(err_code); + + NRF_LOG_DEFAULT_BACKENDS_INIT(); +} + +#else // defined (NRF_LOG_ENABLED) && (NRF_LOG_ENABLED == 1) + +void log_init(void) +{ + ; +} + +#endif // defined (NRF_LOG_ENABLED) && (NRF_LOG_ENABLED == 1) + +uint32_t socket_init(void) +{ + memset(m_socket_table, 0, sizeof(m_socket_table)); + + SOCKET_MUTEX_INIT(); + + log_init(); + + uint32_t err_code = nrf_mem_init(); + APP_ERROR_CHECK(err_code); + + APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); + + err_code = app_timer_init(); + APP_ERROR_CHECK(err_code); + + err_code = config_socket_init(); + APP_ERROR_CHECK(err_code); + +#if SOCKET_TRANSPORT_ENABLE == 1 + err_code = portdb_init(SOCKET_MAX_SOCKET_COUNT); + APP_ERROR_CHECK(err_code); + + transport_handler_init(); +#endif + config_socket_start(); + m_initialization_state = true; + + SOCKET_TRACE("Socket init complete"); + + return NRF_SUCCESS; +} + +/** + * Finds a free entry in the socket table, marks it as used and returns it. Returns -1 if no entry + * was found. + */ +static int socket_allocate(socket_t ** pp_socket) +{ + int ret_sock = -1; + SOCKET_MUTEX_LOCK(); + for (int sock = 0; sock < NUM_SOCKETS; sock++) + { + SOCKET_TRACE("Looking at socket %d with state %d", (int)sock, m_socket_table[sock].so_state); + if (m_socket_table[sock].so_state == STATE_CLOSED) + { + m_socket_table[sock].so_state = STATE_OPEN; + ret_sock = sock; + *pp_socket = &m_socket_table[sock]; + break; + } + } + if (ret_sock < 0) + { + set_errno(EMFILE); + } + SOCKET_MUTEX_UNLOCK(); + return ret_sock; +} + +static socket_t * socket_find(int sock) +{ + SOCKET_MUTEX_LOCK(); + socket_t * p_socket = &m_socket_table[sock]; + SOCKET_MUTEX_UNLOCK(); + return p_socket; +} + +static void socket_free(int sock) +{ + SOCKET_TRACE("Freeing socket %d", (int)sock); + SOCKET_MUTEX_LOCK(); + memset(&m_socket_table[sock], 0, sizeof(m_socket_table[sock])); + m_socket_table[sock].so_state = STATE_CLOSED; + SOCKET_MUTEX_UNLOCK(); +} + +#if SOCKET_TRANSPORT_ENABLE == 1 +void transport_interface_up(void) +{ + m_interface_up = true; +} + +void transport_interface_down(void) +{ + m_interface_up = false; + for (int sock = 0; sock < NUM_SOCKETS; sock++) + { + (void) close(sock); + } +} +#endif + +int fcntl(int fd, int cmd, int flags) +{ + VERIFY_MODULE_IS_INITIALIZED(); + VERIFY_SOCKET_ID(fd); + + if (!((cmd == F_SETFL) || (cmd == F_GETFL))) + { + set_errno(EINVAL); + return -1; + } + socket_t * p_socket = socket_find(fd); + + if (cmd == F_SETFL) + { + p_socket->so_flags = flags; + } + else if (cmd == F_GETFL) + { + return p_socket->so_flags; + } + + return 0; +} + +static void socket_set_errno(uint32_t err_code) +{ + switch (err_code) { + case UDP_INTERFACE_NOT_READY: // fallthrough + case SOCKET_INTERFACE_NOT_READY: + set_errno(ENETDOWN); + break; + case SOCKET_WOULD_BLOCK: + set_errno(EAGAIN); + break; + case SOCKET_NO_ROUTE: + set_errno(ENETUNREACH); + break; + case NRF_ERROR_NO_MEM: // fallthrough + case SOCKET_NO_MEM: + set_errno(ENOMEM); + break; + case SOCKET_TIMEOUT: + set_errno(ETIMEDOUT); + break; + case SOCKET_NO_AVAILABLE_PORTS: + set_errno(EMFILE); + break; + case SOCKET_PORT_IN_USE: // fallthrough + case SOCKET_ADDRESS_IN_USE: + set_errno(EADDRINUSE); + break; + case SOCKET_INVALID_PARAM: + set_errno(EINVAL); + break; + case SOCKET_UNSUPPORTED_PROTOCOL: + set_errno(EPROTONOSUPPORT); + break; + case SOCKET_NOT_CONNECTED: + set_errno(ENOTCONN); + break; + } +} + + +int socket(socket_family_t family, socket_type_t type, socket_protocol_t protocol) +{ + if (m_initialization_state == false) + { + (void) socket_init(); + } + VERIFY_MODULE_IS_INITIALIZED(); + + int ret_sock = -1; + socket_t * p_socket = NULL; + int sock = socket_allocate(&p_socket); + SOCKET_TRACE("Got value %d from allocate", (int)sock); + if (sock >= 0) + { + p_socket->so_params.so_family = family; + p_socket->so_params.so_protocol = protocol; + p_socket->so_params.so_type = type; + p_socket->so_transport = NULL; + + if (family == AF_INET6) + { +#if SOCKET_TRANSPORT_ENABLE == 1 + p_socket->so_transport = &transport_impl; +#else + set_errno(EAFNOSUPPORT); +#endif + } + else if (family == AF_NRF_CFG || family == AF_NRF_CFG_INTERNAL) + { + p_socket->so_transport = &config_socket_transport; + } + else + { + set_errno(EAFNOSUPPORT); + } + + if (p_socket->so_transport != NULL) + { + uint32_t err_code = p_socket->so_transport->open(p_socket); + socket_set_errno(err_code); + ret_sock = (err_code == NRF_SUCCESS) ? sock : ret_sock; + } + + if (ret_sock < 0) + { + socket_free(sock); + } + } + SOCKET_TRACE("Returning socket value %d", (int)ret_sock); + return ret_sock; +} + +static uint32_t wait_interface_up(void) +{ + SOCKET_TRACE("Waiting for interface to come up"); + uint32_t err_code = NRF_SUCCESS; + while (err_code == NRF_SUCCESS && m_interface_up == false) + { + err_code = socket_wait(); + } + if (m_interface_up == true) + { + SOCKET_TRACE("Interface is up!"); + } + return err_code; +} + +static uint32_t socket_interface_up(bool is_blocking) +{ + uint32_t err_code = NRF_SUCCESS; + if (m_interface_up == false) + { + if (is_blocking) + { + (void) wait_interface_up(); + } + } + if (m_interface_up == false) + { + err_code = SOCKET_INTERFACE_NOT_READY; + } + return err_code; +} + +int connect(int sock, const void * p_addr, socklen_t addrlen) +{ + VERIFY_MODULE_IS_INITIALIZED(); + VERIFY_SOCKET_ID(sock); + NULL_PARAM_CHECK(p_addr); + + socket_t * p_socket = socket_find(sock); + bool is_blocking = ((p_socket->so_flags & O_NONBLOCK) == 0); + int ret = -1; + + uint32_t err_code = socket_interface_up(is_blocking); + if (err_code != NRF_SUCCESS) + { + socket_set_errno(err_code); + } + else if (p_socket->so_state == STATE_OPEN) + { + err_code = p_socket->so_transport->connect(p_socket, p_addr, addrlen); + if (err_code == NRF_SUCCESS) + { + p_socket->so_state = STATE_CONNECTED; + ret = 0; + } + socket_set_errno(err_code); + } + else if (p_socket->so_state == STATE_CONNECTED) + { + set_errno(EISCONN); + } + else if (p_socket->so_state == STATE_CLOSED) + { + set_errno(EBADF); + } + return ret; +} + + +ssize_t sendto(int sock, + const void * p_buf, + size_t buflen, + int flags, + const void * p_servaddr, + socklen_t addrlen) +{ + VERIFY_MODULE_IS_INITIALIZED(); + VERIFY_SOCKET_ID(sock); + NULL_PARAM_CHECK(p_buf); + + socket_t * p_socket = socket_find(sock); + + if ((p_socket->so_flags & O_NONBLOCK) != 0 && + (flags & MSG_WAITALL) == 0) + { + flags |= MSG_DONTWAIT; + } + + uint32_t err_code = socket_interface_up(((p_socket->so_flags & O_NONBLOCK) == 0) || ((flags & MSG_DONTWAIT) == 0)); + + ssize_t ret = -1; + if (err_code == NRF_SUCCESS) + { + err_code = p_socket->so_transport->send(p_socket, p_buf, buflen, flags, p_servaddr, addrlen); + if (err_code == NRF_SUCCESS) + { + ret = (ssize_t) buflen; + } + } + socket_set_errno(err_code); + return ret; +} + +ssize_t send(int sock, const void * p_buf, size_t buflen, int flags) +{ + return sendto(sock, p_buf, buflen, flags, NULL, 0); +} + +ssize_t write(int sock, const void * p_buf, size_t buflen) +{ + return send(sock, p_buf, buflen, 0); +} + +ssize_t recvfrom(int sock, + void * p_buf, + size_t buf_size, + int flags, + void * p_cliaddr, + socklen_t * p_addrlen) +{ + VERIFY_MODULE_IS_INITIALIZED(); + VERIFY_SOCKET_ID(sock); + NULL_PARAM_CHECK(p_buf); + + socket_t * p_socket = socket_find(sock); + ssize_t ret = -1; + uint32_t recv_size = buf_size; + + uint32_t err_code = p_socket->so_transport->recv(p_socket, + p_buf, + &recv_size, + flags, + p_cliaddr, + p_addrlen); + if (err_code == NRF_SUCCESS) + { + ret = (ssize_t) recv_size; + } + socket_set_errno(err_code); + return ret; +} + +ssize_t recv(int sock, void * p_buf, size_t buf_size, int flags) +{ + return recvfrom(sock, p_buf, buf_size, flags, NULL, NULL); +} + +ssize_t read(int sock, void * p_buf, size_t buf_size) +{ + return recv(sock, p_buf, buf_size, 0); +} + +int setsockopt(int sock, + socket_opt_lvl_t level, + int optname, + const void * p_optval, + socklen_t optlen) +{ + VERIFY_MODULE_IS_INITIALIZED(); + VERIFY_SOCKET_ID(sock); + + socket_t * p_socket = socket_find(sock); + + uint32_t err_code = p_socket->so_transport->setsockopt(p_socket, + level, + optname, + p_optval, + optlen); + socket_set_errno(err_code); + return (err_code == NRF_SUCCESS ? 0 : -1); +} + +int getsockopt(int sock, socket_opt_lvl_t level, int optname, void * p_optval, socklen_t * p_optlen) +{ + VERIFY_MODULE_IS_INITIALIZED(); + VERIFY_SOCKET_ID(sock); + + socket_t * p_socket = socket_find(sock); + + uint32_t err_code = p_socket->so_transport->getsockopt(p_socket, + level, + optname, + p_optval, + p_optlen); + socket_set_errno(err_code); + return (err_code == NRF_SUCCESS ? 0 : -1); +} + +int bind(int sock, const void * p_addr, socklen_t addrlen) +{ + VERIFY_MODULE_IS_INITIALIZED(); + VERIFY_SOCKET_ID(sock); + NULL_PARAM_CHECK(p_addr); + + socket_t * p_socket = socket_find(sock); + bool is_blocking = ((p_socket->so_flags & O_NONBLOCK) == 0); + int ret = -1; + + uint32_t err_code = socket_interface_up(is_blocking); + if (err_code == NRF_SUCCESS) + { + err_code = p_socket->so_transport->bind(p_socket, p_addr, addrlen); + } + if (err_code == NRF_SUCCESS) + { + ret = 0; + } + socket_set_errno(err_code); + return ret; +} + +int listen(int sock, int backlog) +{ + VERIFY_MODULE_IS_INITIALIZED(); + VERIFY_SOCKET_ID(sock); + + socket_t * p_socket = socket_find(sock); + + uint32_t err_code = p_socket->so_transport->listen(p_socket, backlog); + return (err_code == NRF_SUCCESS ? 0 : -1); +} + +int accept(int sock, void * p_cliaddr, socklen_t * p_addrlen) +{ + VERIFY_MODULE_IS_INITIALIZED(); + VERIFY_SOCKET_ID(sock); + NULL_PARAM_CHECK(p_cliaddr); + NULL_PARAM_CHECK(p_addrlen); + + socket_t * p_socket = socket_find(sock); + int ret = -1; + + if (p_socket->so_params.so_type != SOCK_STREAM) + { + set_errno(EOPNOTSUPP); + } + else + { + uint32_t err_code = NRF_SUCCESS; + socket_t * p_client = NULL; + int sock_cli = socket_allocate(&p_client); + if (sock_cli >= 0) + { + p_client->so_params = p_socket->so_params; + p_client->so_state = STATE_CONNECTED; + p_client->so_transport = p_socket->so_transport; + err_code = p_socket->so_transport->accept(p_socket, p_client, p_cliaddr, p_addrlen); + } + + if (err_code == NRF_SUCCESS) + { + ret = sock_cli; + } + else + { + socket_set_errno(err_code); + socket_free(sock_cli); + } + } + return ret; +} + +int close(int sock) +{ + VERIFY_MODULE_IS_INITIALIZED(); + VERIFY_SOCKET_ID(sock); + + socket_t * p_socket = socket_find(sock); + int ret = 0; + + if (p_socket->so_state != STATE_CLOSED) + { + uint32_t err_code = p_socket->so_transport->close(p_socket); + ret = (err_code == NRF_SUCCESS) ? 0 : -1; + SOCKET_TRACE("Close socket %d: ret: %d", (int)sock, ret); + socket_free(sock); + } + return ret; +} + +int fd_set_cmp(fd_set * set_a, fd_set * set_b) +{ + int ret = 0; + if (set_a != NULL && set_b != NULL) + { + for (uint32_t i = 0; i < FD_SETSIZE; i++) + { + if (FD_ISSET(i, set_a) != FD_ISSET(i, set_b)) + { + ret = 1; + break; + } + } + } + return ret; +} + +int select(int nfds, + fd_set * p_readset, + fd_set * p_writeset, + fd_set * p_exceptset, + const struct timeval * p_timeout) +{ + VERIFY_SOCKET_ID(nfds - 1); + + // Approximately 10 ms sleep between each iteration + uint32_t timestep = 10000; + uint32_t endtime = 0; + if (p_timeout != NULL) + { + endtime = (p_timeout->tv_sec * 1000000) + p_timeout->tv_usec; + } + fd_set readset; + FD_ZERO(&readset); + fd_set writeset; + FD_ZERO(&writeset); + fd_set exceptset; + FD_ZERO(&exceptset); + +#define SELECT_CHECK_SET(in_set, out_set, evt_var) \ + if ((in_set) != NULL) \ + { \ + if (FD_ISSET(sock, (in_set)) && (evt_var) > 0) \ + { \ + FD_SET(sock, (out_set)); \ + num_ready++; \ + } \ + else \ + { \ + FD_CLR(sock, (out_set)); \ + } \ + } + + int num_ready = 0; + uint32_t err_code = NRF_SUCCESS; + while (err_code == NRF_SUCCESS) + { + for (int sock = 0; sock < nfds; sock++) + { + socket_t * p_socket = socket_find(sock); + SELECT_CHECK_SET(p_readset, &readset, p_socket->so_read_evt); + SELECT_CHECK_SET(p_writeset, &writeset, p_socket->so_write_evt); + SELECT_CHECK_SET(p_exceptset, &exceptset, p_socket->so_except_evt); + } + // TODO: Check out how app events queue up while we checked the socket + if (fd_set_cmp(p_readset, &readset) == 0 && + fd_set_cmp(p_writeset, &writeset) == 0 && + fd_set_cmp(p_exceptset, &exceptset) == 0) + + { + break; + } + else + { + if (p_timeout == NULL) + { + err_code = socket_wait(); + } + else if (endtime - timestep < endtime) + { + (void) usleep(timestep); + endtime -= timestep; + } + else + { + break; + } + } + + } + + return num_ready; +} + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket_common.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket_common.h new file mode 100644 index 0000000..d9a0f8a --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket_common.h @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file socket_common.h + * + * @defgroup socket_common BSD Socket internal functions and structures + * @ingroup iot_sdk_socket + * @{ + * @brief Nordic socket interface internal functions and structures. + */ +#ifndef SOCKET_COMMON_H__ +#define SOCKET_COMMON_H__ + +#include <stdint.h> +#include "socket_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct socket_transport; + +#define AF_NRF_CFG_INTERNAL 41 /**< Socket family type, internal NRF configuration socket. */ + +/** + * @brief Function for initializing the socket API module. + * + * @return NRF_SUCCESS on success, otherwise error code is returned. + */ +uint32_t socket_init(void); + +/** + * @brief Waiting function for sockets. + * + * @details Must be implemented by specific modules such as BLEs. + * + * @return NRF_SUCCESS on success, otherwise error code is returned. + */ +uint32_t socket_wait(void); + +/** + * @brief Create parameters for a socket. + */ +typedef struct { + socket_family_t so_family; /**< Socket family. */ + socket_protocol_t so_protocol; /**< Socket protocol. */ + socket_type_t so_type; /**< Socket type. */ +} socket_params_t; + +/** + * @brief Different states a socket can be in. + */ +typedef enum { + STATE_CLOSED = 0, /**< Socket is closed. */ + STATE_OPEN, /**< Socket is opened. */ + STATE_CONNECTED, /**< Socket is connected. */ +} socket_state_t; + +/** + * @brief The state associated with a socket handle. + */ +typedef struct { + socket_params_t so_params; /**< Generic socket parameters. */ + void * so_ctx; /**< Transport specific context. */ + int so_flags; /**< Socket flags. */ + uint16_t so_read_evt; /**< Notifying of read events. */ + uint16_t so_write_evt; /**< Notifying of write events. */ + uint16_t so_except_evt; /**< Notifying of exceptional events. */ + struct socket_transport * so_transport; /**< Transport attached to this socket. */ + volatile socket_state_t so_state; /**< Socket state. */ +} socket_t; + +#ifdef __cplusplus +} +#endif + +#endif // SOCKET_COMMON_H__ + +/**@} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket_config.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket_config.h new file mode 100644 index 0000000..cce571e --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket_config.h @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file socket_config.h + * + * @defgroup iot_socket_config Configuration socket API + * @ingroup iot_sdk_socket + * @{ + * @brief Configuration socket API. + * + * This API is used internally by the socket handling to support the configuration + * socket type. The configuration socket is implemented using a special transport hook, which is + * implemented differently depending on the platform. + */ +#ifndef SOCKET_CONFIG_H__ +#define SOCKET_CONFIG_H__ + +#include "socket_common.h" +#include "transport_if.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for setting the default configuration. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +uint32_t config_socket_init(void); + +/** + * @brief Function for starting the configuration layer. + */ +void config_socket_start(void); + +extern socket_transport_t config_socket_transport; + +#ifdef __cplusplus +} +#endif + +#endif // SOCKET_CONFIG_H__ + +/**@} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket_trace.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket_trace.h new file mode 100644 index 0000000..87fafdf --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/socket_trace.h @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file socket_trace.h + * + * @defgroup iot_socket_debug_log Module's log macros + * @ingroup iot_sdk_socket + * @{ + * @brief Socket trace macros. + * + * @details Macros for creating module logs which can be useful in understanding the handling + * of events or actions on API requests. These are intended for debugging purposes and + * can be disabled by defining the SOCKET_CONFIG_LOG_ENABLED. + * @note If NRF_LOG_ENABLED is disabled, SOCKET_CONFIG_LOG_ENABLED has no effect. + */ +#ifndef SOCKET_TRACE_H__ +#define SOCKET_TRACE_H__ + +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOCKET_CONFIG_LOG_ENABLED == 1 +#if defined (NRF_LOG_ENABLED) && (NRF_LOG_ENABLED == 1) + +#define NRF_LOG_MODULE_NAME socket + +#define NRF_LOG_LEVEL SOCKET_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR SOCKET_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR SOCKET_CONFIG_DEBUG_COLOR + +#include "nrf_log.h" + +#define SOCKET_TRACE NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */ +#define SOCKET_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */ +#define SOCKET_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */ + +#else + +#define SOCKET_TRACE(...) \ + do { \ + (void) fprintf( stderr, "socket: " ); \ + (void) fprintf( stderr, __VA_ARGS__ ); \ + (void) fprintf( stderr, "\r\n" ); \ + } while (0) + +#endif + +#else // SOCKET_CONFIG_LOG_ENABLED + +#define SOCKET_TRACE(...) /**< Disables traces. */ +#define SOCKET_ERR(...) /**< Disables error logs. */ +#define SOCKET_DUMP(...) /**< Disables dumping of octet streams. */ + +#endif // SOCKET_CONFIG_LOG_ENABLED + + +#ifdef __cplusplus +} +#endif + +#endif // SOCKET_TRACE_H__ + +/**@} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/transport_if.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/transport_if.h new file mode 100644 index 0000000..75a86c1 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/common/transport_if.h @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file transport_if.h + * + * @defgroup iot_socket_transport_if Transport implementation interface + * @ingroup iot_sdk_socket + * @{ + * @brief Transport implementation interface. + * + * The transport interface defines the hook to be used for socket transport. The implementation of + * this interface would be different across platforms and event IP stacks (i.e. Nordic IPv6 vs LwIP). + */ +#ifndef TRANSPORT_IF_H__ +#define TRANSPORT_IF_H__ + +#include "iot_defines.h" +#include "socket_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for opening a socket. + */ +typedef uint32_t (*tr_open_t) (socket_t * p_socket); + +/** + * @brief Function for connecting a socket to an address. + */ +typedef uint32_t (*tr_connect_t)(socket_t * p_socket, const void * p_addr, socklen_t addrlen); + +/** + * @brief Function for sending data on a socket. + */ +typedef uint32_t (*tr_send_t)(socket_t * p_socket, + const void * p_buf, + uint32_t len, + int flags, + const void * p_destaddr, + socklen_t destaddr_len); + +/** + * @brief Function for receiving data from a socket. + */ +typedef uint32_t (*tr_recv_t)(socket_t * p_socket, + void * p_buf, + uint32_t * sz, + int flags, + void * p_srcaddr, + socklen_t * p_srcaddr_len); + +/** + * @brief Function for binding a socket to an address and port. + */ +typedef uint32_t (*tr_bind_t)(socket_t * p_socket, const void * p_addr, socklen_t addrlen); + +/** + * @brief Function for listening on a socket. + */ +typedef uint32_t (*tr_listen_t)(socket_t * p_socket, int backlog); + +/** + * @brief Function for accepting a connection on a socket. + */ +typedef uint32_t (*tr_accept_t)(socket_t * p_socket, + socket_t * p_client, + void * p_client_addr, + socklen_t * p_client_addr_len); + +/** + * @brief Function for closing a socket. + */ +typedef uint32_t (*tr_close_t)(socket_t * p_socket); + +/** + * @brief Function for setting options on a socket. + */ +typedef uint32_t (*tr_setsockopt_t)(socket_t * p_socket, + int level, + int optname, + const void * p_optval, + socklen_t optlen); + +/** + * @brief Function for getting options from a socket. + */ +typedef uint32_t (*tr_getsockopt_t)(socket_t * p_socket, + int level, + int optname, + void * p_optval, + socklen_t * p_optlen); + +/** + * @brief The transport interface. + */ +typedef struct socket_transport +{ + tr_open_t open; /**< Open a socket. */ + tr_connect_t connect; /**< Connect a socket to an address. */ + tr_send_t send; /**< Send data on a socket. */ + tr_recv_t recv; /**< Receive data from a socket. */ + tr_bind_t bind; /**< Bind a socket to an address and port. */ + tr_listen_t listen; /**< Listen on a socket. */ + tr_accept_t accept; /**< Accept connection on a socket. */ + tr_close_t close; /**< Close a socket. */ + tr_setsockopt_t setsockopt; /**< Set options on a socket. */ + tr_getsockopt_t getsockopt; /**< Get options from a socket. */ +} socket_transport_t; + +#if SOCKET_TRANSPORT_ENABLE == 1 +extern socket_transport_t transport_impl; +void transport_handler_init(void); +void transport_interface_up(void); +void transport_interface_down(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // TRANSPORT_IF_H__ + +/**@} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/config/medium/config_medium.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/config/medium/config_medium.c new file mode 100644 index 0000000..6b883dd --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/config/medium/config_medium.c @@ -0,0 +1,227 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_config.h" +#include "socket_api.h" +#include "config_medium.h" +#include "ipv6_medium.h" +#include "iot_errors.h" +#include "app_error.h" +#include "socket_config.h" + +static ipv6_medium_instance_t m_ipv6_medium; /**< IPv6 medium instance. */ +eui64_t eui64_local_iid; /**< Local EUI64 value that is used as the IID for*/ + +eui64_t * config_medium_local_iid(void) +{ + return &eui64_local_iid; +} + +void config_medium_start(void) +{ + uint32_t err_code = ipv6_medium_connectable_mode_enter(m_ipv6_medium.ipv6_medium_instance_id); + APP_ERROR_CHECK(err_code); +} + +static void on_ipv6_medium_evt(ipv6_medium_evt_t * p_ipv6_medium_evt) +{ + switch (p_ipv6_medium_evt->ipv6_medium_evt_id) + { + case IPV6_MEDIUM_EVT_CONN_UP: + { + // TODO: Signal + break; + } + case IPV6_MEDIUM_EVT_CONN_DOWN: + { + config_medium_start(); + break; + } + default: + { + break; + } + } +} + + +static void on_ipv6_medium_error(ipv6_medium_error_t * p_ipv6_medium_error) +{ + // Do something. +} + +static uint32_t config_medium_init(ipv6_medium_init_params_t * p_medium_params, + ipv6_medium_type_t medium_type) +{ + uint32_t err_code = ipv6_medium_init(p_medium_params, medium_type, &m_ipv6_medium); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + eui48_t ipv6_medium_eui48; + err_code = ipv6_medium_eui48_get(m_ipv6_medium.ipv6_medium_instance_id, &ipv6_medium_eui48); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + ipv6_medium_eui48.identifier[EUI_48_SIZE - 1] = 0x00; + + err_code = ipv6_medium_eui48_set(m_ipv6_medium.ipv6_medium_instance_id, &ipv6_medium_eui48); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = ipv6_medium_eui64_get(m_ipv6_medium.ipv6_medium_instance_id, &eui64_local_iid); + return err_code; +} + +uint32_t config_medium_init_default(void) +{ + static ipv6_medium_init_params_t ipv6_medium_init_params; + memset(&ipv6_medium_init_params, 0x00, sizeof(ipv6_medium_init_params)); + ipv6_medium_init_params.ipv6_medium_evt_handler = on_ipv6_medium_evt; + ipv6_medium_init_params.ipv6_medium_error_handler = on_ipv6_medium_error; + return config_medium_init(&ipv6_medium_init_params, IPV6_MEDIUM_ID_BLE); +} + +uint32_t config_medium_setopt(int optname, const void * p_optarg, socklen_t optlen) +{ + uint32_t err_code = SOCKET_INVALID_PARAM; + if (optname == MEDIUM_INIT_PARAMS) + { + if (optlen == sizeof(config_medium_params_t)) + { + const config_medium_params_t * p_cfg = (const config_medium_params_t *)p_optarg; + ipv6_medium_init_params_t ipv6_medium_init_params; + memset(&ipv6_medium_init_params, 0x00, sizeof(ipv6_medium_init_params)); + ipv6_medium_init_params.ipv6_medium_evt_handler = p_cfg->evt_handler; + ipv6_medium_init_params.ipv6_medium_error_handler = p_cfg->error_handler; + err_code = config_medium_init(&ipv6_medium_init_params, p_cfg->medium_type); + } + } + return err_code; +} + +uint32_t config_medium_getopt(int optname, void * p_optarg, socklen_t * p_optlen) +{ + (void) optname; + (void) p_optarg; + (void) p_optlen; + return SOCKET_INVALID_PARAM; +} + +uint32_t config_socket_init(void) +{ + uint32_t err_code = NRF_SUCCESS; +#if SOCKET_AUTOINIT_ENABLE == 1 + err_code = config_medium_init_default(); +#endif + return err_code; +} + +void config_socket_start(void) +{ +#if SOCKET_AUTOINIT_ENABLE == 1 + config_medium_start(); +#endif +} + +static uint32_t config_socket_open(socket_t * p_socket) +{ + (void) p_socket; + return NRF_ERROR_NULL; +} + +static uint32_t config_socket_close(socket_t * p_socket) +{ + (void) p_socket; + return NRF_ERROR_NULL; +} + +uint32_t config_socket_setopt(socket_t * p_socket, + int level, + int optname, + const void * p_optarg, + socklen_t optlen) +{ + uint32_t err_code = NRF_SUCCESS; + switch (level) + { + case SOL_NRF_MEDIUM: + err_code = config_medium_setopt(optname, p_optarg, optlen); + break; + default: + err_code = SOCKET_INVALID_PARAM; + break; + } + return err_code; +} + +uint32_t config_socket_getopt(socket_t * p_socket, + int level, + int optname, + void * p_optarg, + socklen_t * p_optlen) +{ + uint32_t err_code = NRF_SUCCESS; + switch (level) + { + case SOL_NRF_MEDIUM: + err_code = config_medium_getopt(optname, p_optarg, p_optlen); + break; + default: + err_code = SOCKET_INVALID_PARAM; + break; + } + return err_code; +} + +/** + * @brief Transport for configuration socket. + */ +socket_transport_t config_socket_transport = +{ + .open = config_socket_open, + .setsockopt = config_socket_setopt, + .getsockopt = config_socket_getopt, + .close = config_socket_close +}; diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/config/medium/config_medium.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/config/medium/config_medium.h new file mode 100644 index 0000000..e4b7c01 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/config/medium/config_medium.h @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file config_medium.h + * + * @defgroup iot_socket_config_medium Configuration socket based on ipv6_medium + * @ingroup iot_sdk_socket + * @{ + * @brief Configuration socket based on the ipv6_medium module. + * + * This module wraps the medium module in a configuration socket API. + */ +#ifndef CONFIG_MEDIUM_H__ +#define CONFIG_MEDIUM_H__ + +#include <stdint.h> +#include "iot_defines.h" +#include "ipv6_medium.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for initializing a configuration socket with default settings. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +uint32_t config_medium_init_default(void); + +/** + * @brief Function for starting the medium layer. + * + * For BLE, this means to start advertising. + */ +void config_medium_start(void); + +/** + * @brief Function for retrieving local interface ID assigned. + * + * @return Pointer to location of interface ID. + */ +eui64_t * config_medium_local_iid(void); + +/** + * @brief Function for setting configuration parameters for the medium layers using the socket option. + * + * @param optname Option name/type. + * @param p_optarg Pointer to option value. + * @param optlen Length of option value. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +uint32_t config_medium_setopt(int optname, const void * p_optarg, socklen_t optlen); + +/** + * @brief Function for getting configuration parameters for the medium layers using the socket option. + * + * @param optname Option name/type. + * @param p_optarg Pointer to the option value structure where the value should be stored. + * @param p_optlen Length of option value. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +uint32_t config_medium_getopt(int optname, void * p_optarg, socklen_t * p_optlen); + +/** + * @brief Parameters passed for the MEDIUM_INIT_PARAMS option. + * + * These are currently the same as for ipv6_medium initialization. + */ +typedef struct { + ipv6_medium_evt_handler_t evt_handler; /**< The medium event handler callback. */ + ipv6_medium_error_handler_t error_handler; /**< The medium error handler callback. */ + ipv6_medium_type_t medium_type; /**< The medium type. */ +} config_medium_params_t; + +#ifdef __cplusplus +} +#endif + +#endif // CONFIG_MEDIUM_H__ + +/**@} */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/addr_util/inet_pton.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/addr_util/inet_pton.c new file mode 100644 index 0000000..2fd1f4c --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/addr_util/inet_pton.c @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "socket_api.h" +#include "ipv6_parse.h" + +int inet_pton(socket_family_t af, const char * p_src, void * p_dst) +{ + int ret_val = 1; + if (af != AF_INET6) + { + ret_val = -1; + } + else + { + in6_addr_t * p_addr = (in6_addr_t *)p_dst; + uint32_t err_code = ipv6_parse_addr(p_addr->s6_addr, p_src, strlen(p_src)); + if (err_code != NRF_SUCCESS) + { + ret_val = 0; + } + } + return ret_val; +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/fifo/nrf_fifo.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/fifo/nrf_fifo.c new file mode 100644 index 0000000..1458b01 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/fifo/nrf_fifo.c @@ -0,0 +1,176 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "iot_defines.h" +#include "iot_errors.h" +#include "nrf_fifo.h" +#include "mem_manager.h" +#include "nrf.h" + +static __INLINE uint32_t fifo_inc(nrf_fifo_t * p_fifo, uint32_t pos) +{ + return (pos + 1) % p_fifo->nmemb; +} + +static __INLINE bool fifo_full(nrf_fifo_t * p_fifo) +{ + return fifo_inc(p_fifo, p_fifo->write_pos) == p_fifo->read_pos; +} + +static __INLINE bool fifo_empty(nrf_fifo_t * p_fifo) +{ + return p_fifo->read_pos == p_fifo->write_pos; +} + +static __INLINE void fifo_enq(nrf_fifo_t * p_fifo, void * p_ctx) +{ + p_fifo->pp_elements[p_fifo->write_pos] = p_ctx; + __DSB(); + p_fifo->write_pos = fifo_inc(p_fifo, p_fifo->write_pos); +} + + +static __INLINE void fifo_deq(nrf_fifo_t * p_fifo, void ** pp_ctx) +{ + *pp_ctx = p_fifo->pp_elements[p_fifo->read_pos]; + __DSB(); + p_fifo->read_pos = fifo_inc(p_fifo, p_fifo->read_pos); +} + +uint32_t nrf_fifo_init(nrf_fifo_t * p_fifo, uint32_t nmemb, fifo_wait_fn wait_fn, fifo_flush_fn flush_fn) +{ + uint32_t err_code = NRF_SUCCESS; + uint32_t nmemb_actual = nmemb + 1; // Required to allow detection of empty and full state + p_fifo->pp_elements = nrf_malloc(nmemb_actual * sizeof(void *)); + + if (p_fifo->pp_elements == NULL) + { + err_code = NRF_ERROR_NO_MEM; + } + else + { + p_fifo->nmemb = nmemb_actual; + p_fifo->wait = wait_fn; + p_fifo->flush = flush_fn; + p_fifo->read_pos = 0; + p_fifo->write_pos = 0; + } + return err_code; +} + +void nrf_fifo_deinit(nrf_fifo_t * p_fifo) +{ + if (p_fifo->flush != NULL) + { + void * p_data; + uint32_t err_code = nrf_fifo_deq(p_fifo, &p_data, false); + while (err_code == NRF_SUCCESS) + { + p_fifo->flush(p_data); + err_code = nrf_fifo_deq(p_fifo, &p_data, false); + } + } + nrf_free(p_fifo->pp_elements); + p_fifo->nmemb = 0; + p_fifo->read_pos = 0; + p_fifo->write_pos = 0; + p_fifo->wait = NULL; + p_fifo->flush = NULL; +} + +uint32_t nrf_fifo_enq(nrf_fifo_t * p_fifo, void * p_ctx, bool wait) +{ + uint32_t err_code = NRF_SUCCESS; + + if (fifo_full(p_fifo) == true) + { + if (wait == false || p_fifo->wait == NULL) + { + err_code = SOCKET_WOULD_BLOCK; + } + else + { + while (fifo_full(p_fifo) == true && err_code == NRF_SUCCESS) + { + err_code = p_fifo->wait(); + } + } + } + else + { + fifo_enq(p_fifo, p_ctx); + } + return err_code; +} + +uint32_t nrf_fifo_deq(nrf_fifo_t * p_fifo, void ** pp_ctx, bool wait) +{ + uint32_t err_code = NRF_SUCCESS; + + if (fifo_empty(p_fifo) == true) + { + if (wait == false || p_fifo->wait == NULL) + { + err_code = SOCKET_WOULD_BLOCK; + } + else + { + while (fifo_empty(p_fifo) == true && err_code == NRF_SUCCESS) + { + err_code = p_fifo->wait(); + } + } + } + + if (err_code == NRF_SUCCESS) + { + fifo_deq(p_fifo, pp_ctx); + } + return err_code; +} + +bool nrf_fifo_empty(nrf_fifo_t * p_fifo) +{ + return fifo_empty(p_fifo); +} + +bool nrf_fifo_full(nrf_fifo_t * p_fifo) +{ + return fifo_full(p_fifo); +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/fifo/nrf_fifo.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/fifo/nrf_fifo.h new file mode 100644 index 0000000..c6fb378 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/fifo/nrf_fifo.h @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_FIFO_H__ +#define NRF_FIFO_H__ + +#include <stdint.h> +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file nrf_fifo.h + * + * @defgroup iot_socket_fifo FIFO + * @ingroup iot_sdk_socket + * @{ + * @brief A wait-free bounded FIFO of pointers for single producer/single consumer use. + * + * This FIFO is safe to use in single producer/single consumer patterns. In addition, the following + * restrictions apply for init/deinit: + * + * a) nrf_fifo_enq() and nrf_fifo_deq() may only be called after nrf_fifo_init() is called. + * + * b) All calls to nrf_fifo_enq() and nrf_fifo_deq() must be finished and no new calls must be made before nrf_fifo_deinit() is called. + * + * These restrictions must be handled by the user of the module, for instance by using a mutex. + */ + +/** + * @brief Wait function for blocking enqueue/dequeue. + * + * Should return NRF_SUCCESS as long as there are no errors while waiting. + */ +typedef uint32_t (*fifo_wait_fn)(void); + +/** + * @brief Flush function called on deinit. + * + * On deinit, this function will be called with each remaining element in the FIFO as argument. This + * can be used to ensure that memory is deallocated properly. + * + * @param[in] p_data Pointer to data that is flushed from FIFO. + */ +typedef void (*fifo_flush_fn)(void * p_data); + +/** + * @brief FIFO data structure. + */ +typedef struct { + void ** pp_elements; /**< The array of elements in the FIFO. */ + uint32_t nmemb; /**< The number of elements in this FIFO. */ + fifo_wait_fn wait; /**< The wait function used if blocking. */ + fifo_flush_fn flush; /**< The flush function used on deinit. */ + volatile uint32_t read_pos; /**< Read pointer to next element to read. */ + volatile uint32_t write_pos; /**< Write pointer to next element to write. */ +} nrf_fifo_t; + +/** + * @brief Function for initializing the FIFO. + * + * @param[out] p_fifo The FIFO to initialize. + * @param[in] nmemb The maximum number of elements in the FIFO. + * @param[in] wait_fn The wait function to use for blocking enqueue/dequeue. If NULL, the enq/deq + * functions will never block. + * @param[in] flush_fn The flush function to call on deinit. If NULL, the flush function will not + * be called. + * + * @retval NRF_SUCCESS if fifo was initialized successfully. + */ +uint32_t nrf_fifo_init(nrf_fifo_t * p_fifo, uint32_t nmemb, fifo_wait_fn wait_fn, fifo_flush_fn flush_fn); + +/** + * @brief Function for deinitializing the FIFO. + * + * Frees all memory allocated by this FIFO. All elements are removed. If a flush function was + * specified in nrf_fifo_init(), the function will be called for each remaining element in the + * FIFO. + * + * @param[in, out] p_fifo The FIFO to deinitialize. + */ +void nrf_fifo_deinit(nrf_fifo_t * p_fifo); + +/** + * @brief Function for enqueuing an element on the FIFO. + * + * @param[in, out] p_fifo The FIFO to enqueue elements on. + * @param[in] p_ctx The pointer to enqueue. + * @param[in] wait If true, this function will block until the FIFO has available space. Any + * errors returned by this function will be propagated to the caller. + * + * @retval NRF_SUCCESS if the element was queued. + * @retval NRF_ERROR_NO_MEM if wait was set to false and no space was available. + */ +uint32_t nrf_fifo_enq(nrf_fifo_t * p_fifo, void * p_ctx, bool wait); + +/** + * @brief Function for dequeuing an element from the FIFO. + * + * @param[in, out] p_fifo The FIFO to dequeue elements from. + * @param[out] pp_ctx Pointer to where the dequeued element should be stored. + * @param[in] wait If true, this function will block until the FIFO has elements for dequeuing. + * Any errors returned by this function will be propagated to the caller. + * + * @retval NRF_SUCCESS if the element was queued. + * @retval NRF_ERROR_NO_MEM if wait was set to false and no space was available. + */ +uint32_t nrf_fifo_deq(nrf_fifo_t * p_fifo, void ** pp_ctx, bool wait); + +/** + * @brief Function for checking if the FIFO is empty. + * + * @param[in] p_fifo The FIFO to check. + * @return true if empty, false if not. + */ +bool nrf_fifo_empty(nrf_fifo_t * p_fifo); + +/** + * @brief Function for checking if the FIFO is full. + * + * @param[in] p_fifo The FIFO to check. + * @return true if full, false if not. + */ +bool nrf_fifo_full(nrf_fifo_t * p_fifo); + +/**@} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_FIFO_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/mbuf/mbuf.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/mbuf/mbuf.c new file mode 100644 index 0000000..d4b0c79 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/mbuf/mbuf.c @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "iot_defines.h" +#include "iot_errors.h" +#include "sdk_config.h" +#include "mem_manager.h" +#include "mbuf.h" +#include "nrf_fifo.h" +#include "socket_common.h" + +uint32_t mbuf_init(mbuf_t * p_mbuf, + mbuf_read_fn read_fn, + mbuf_buf_len_fn buf_len_fn, + mbuf_free_fn free_fn, + uint32_t nmemb) +{ + p_mbuf->p_current = NULL; + p_mbuf->read_pos = 0; + p_mbuf->read = read_fn; + p_mbuf->buf_len = buf_len_fn; + p_mbuf->free = free_fn; + return nrf_fifo_init(&p_mbuf->fifo, nmemb, socket_wait, free_fn); +} + +void mbuf_deinit(mbuf_t * p_mbuf) +{ + if (p_mbuf->p_current != NULL) + { + p_mbuf->free(p_mbuf->p_current); + p_mbuf->p_current = NULL; + } + + p_mbuf->read_pos = 0; + p_mbuf->read = NULL; + p_mbuf->buf_len = NULL; + p_mbuf->free = NULL; + nrf_fifo_deinit(&p_mbuf->fifo); +} + +static bool mbuf_empty_current(mbuf_t * p_mbuf) +{ + return (p_mbuf->buf_len(p_mbuf->p_current) == p_mbuf->read_pos); +} + +bool mbuf_empty(mbuf_t * p_mbuf) +{ + return ((p_mbuf->p_current == NULL || mbuf_empty_current(p_mbuf)) && + nrf_fifo_empty(&p_mbuf->fifo)); +} + +uint32_t mbuf_write(mbuf_t * p_mbuf, void * p_ctx) +{ + return nrf_fifo_enq(&p_mbuf->fifo, p_ctx, false); +} + +static void mbuf_load(mbuf_t * p_mbuf) +{ + if (p_mbuf->p_current == NULL) + { + (void)nrf_fifo_deq(&p_mbuf->fifo, &p_mbuf->p_current, false); + } +} + +uint32_t mbuf_read(mbuf_t * p_mbuf, void * p_buf, uint32_t buf_size) +{ + uint32_t nbytes = 0; + while (nbytes < buf_size && mbuf_empty(p_mbuf) == false) + { + mbuf_load(p_mbuf); + void * p_current = p_mbuf->p_current; + const uint32_t copy_len = p_mbuf->read(p_current, + p_mbuf->read_pos, + ((uint8_t *)p_buf) + nbytes, + buf_size - nbytes); + p_mbuf->read_pos += copy_len; + nbytes += copy_len; + if (mbuf_empty_current(p_mbuf) == true) + { + p_mbuf->free(p_mbuf->p_current); + p_mbuf->p_current = NULL; + p_mbuf->read_pos = 0; + } + } + return nbytes; +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/mbuf/mbuf.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/mbuf/mbuf.h new file mode 100644 index 0000000..884c650 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/mbuf/mbuf.h @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef MBUF_H__ +#define MBUF_H__ + +/** + * @file mbuf.h + * + * @defgroup iot_socket_mbuf Memory management for socket + * @ingroup iot_sdk_socket + * @{ + * @brief Memory management for socket. + */ + +#include <stdbool.h> +#include "nrf_fifo.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Function for reading data from a buffer. */ +typedef uint32_t (*mbuf_read_fn)(void * p_ctx, + uint32_t read_offset, + uint8_t * p_dest, + uint32_t dest_len); + +/**@brief Function for checking buffer length. */ +typedef uint32_t (*mbuf_buf_len_fn)(void * p_ctx); + +/**@brief Function for freeing a buffer. */ +typedef void (*mbuf_free_fn)(void * p_ctx); + +/**@brief Memory management structure. */ +typedef struct +{ + nrf_fifo_t fifo; /**< FIFO for storing data buffers. */ + mbuf_read_fn read; /**< Function for reading data from a buffer. */ + mbuf_buf_len_fn buf_len; /**< Function for checking buffer length. */ + mbuf_free_fn free; /**< Function for freeing a buffer. */ + uint32_t read_pos; /**< Read position in the currently processed buffer. */ + void * p_current; /**< Pointer to the currently processed buffer. */ +} mbuf_t; + +/** + * @brief Function for initializing the memory buffer manager. + * + * This function allocates resources for the mbuf FIFO and initializes the mbuf. + * + * @param[in, out] p_mbuf Pointer to the mbuf structure to initialize. + * @param[in] read_fn Function for reading data from a buffer. + * @param[in] buf_len_fn Function for checking buffer length. + * @param[in] free_fn Function for freeing a buffer. + * @param[in] nmemb Maximum number of data buffers. + * + * @return NRF_SUCCESS on success, otherwise error code is returned. + */ +uint32_t mbuf_init(mbuf_t * p_mbuf, + mbuf_read_fn read_fn, + mbuf_buf_len_fn buf_len_fn, + mbuf_free_fn free_fn, + uint32_t nmemb); + +/** + * @brief Function for deinitializing the memory buffer manager. + * + * This function releases any resources allocated for mbuf instance pointed by p_mbuf. + * + * @param[in, out] p_mbuf Pointer to the mbuf structure to deinitialize. + */ +void mbuf_deinit(mbuf_t * p_mbuf); + +/** + * @brief Function for putting a data buffer in the mbuf. + * + * @param[in, out] p_mbuf Pointer to the mbuf structure that shall store the buffer. + * @param[in] p_ctx Pointer to the data buffer to store. + * + * @return NRF_SUCCESS on success, otherwise error code is returned. + */ +uint32_t mbuf_write(mbuf_t * p_mbuf, void * p_ctx); + +/** + * @brief Function for reading data from the mbuf. + * + * @param[in, out] p_mbuf Pointer to the mbuf structure to read data from. + * @param[in] p_buf Pointer to the buffer where data shall be read from. + * @param[out] buf_size Size of the buffer pointed by p_buf. + * + * @return NRF_SUCCESS on success, otherwise error code is returned. + */ +uint32_t mbuf_read(mbuf_t * p_mbuf, void * p_buf, uint32_t buf_size); + +/** + * @brief Function for checking if the mbuf is empty. + * + * @param[in] p_mbuf Pointer to the mbuf structure that shall be checked. + * + * @return True if mbuf is empty, false otherwise. + */ +bool mbuf_empty(mbuf_t * p_mbuf); + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // MBUF_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/portdb/portdb.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/portdb/portdb.c new file mode 100644 index 0000000..7bfbcc4 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/portdb/portdb.c @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "portdb.h" +#include <string.h> +#include "iot_common.h" +#include "iot_errors.h" +#include "mem_manager.h" +#include "nrf_error.h" + +#define IANA_EPHEMRAL_BEGIN 49152u /**< Minimum port number of the ephemeral port range. */ +#define IANA_EPHEMRAL_END 65535u /**< Maximum port number of the ephemeral port range. */ + +static uint16_t * m_portdb; /**< A pointer to the port database. */ +static uint32_t m_portdb_len; /**< Length of the port database. */ + + + +static __INLINE uint32_t db_size_get(void) +{ + return m_portdb_len * sizeof(uint16_t); +} + + +static __INLINE void db_reset(void) +{ + memset(&m_portdb[0], 0, db_size_get()); +} + + +uint32_t portdb_init(uint32_t max_ports) +{ + uint32_t err_code = NRF_SUCCESS; + m_portdb_len = max_ports; + m_portdb = nrf_malloc(db_size_get()); + if (m_portdb == NULL) + { + err_code = NRF_ERROR_NO_MEM; + } + else + { + db_reset(); + } + return err_code; +} + + +void portdb_deinit(void) +{ + nrf_free(m_portdb); + m_portdb = NULL; + m_portdb_len = 0; +} + + +void portdb_reset(void) +{ + db_reset(); +} + + +static inline uint32_t check_port_in_use(uint16_t port) +{ + uint32_t err_code = NRF_SUCCESS; + + for (uint32_t i = 0; i < m_portdb_len; i++) + { + if (m_portdb[i] == port) + { + err_code = SOCKET_PORT_IN_USE; + break; + } + } + return err_code; +} + +static inline uint32_t find_free_index(uint32_t * p_idx) +{ + uint32_t err_code = SOCKET_NO_AVAILABLE_PORTS; + + for (uint32_t i = 0; i < m_portdb_len; i++) + { + if (m_portdb[i] == 0) + { + *p_idx = i; + err_code = NRF_SUCCESS; + break; + } + } + return err_code; +} + +static uint32_t portdb_find_available_index(uint32_t * p_idx, uint16_t port) +{ + uint32_t err_code = SOCKET_NO_AVAILABLE_PORTS; + + err_code = check_port_in_use(port); + + if (err_code == NRF_SUCCESS) + { + err_code = find_free_index(p_idx); + } + return err_code; +} + +uint32_t portdb_register(uint16_t port) +{ + uint32_t idx = 0; + uint32_t err_code = portdb_find_available_index(&idx, port); + + if (err_code == NRF_SUCCESS) + { + m_portdb[idx] = port; + } + return err_code; +} + +uint32_t portdb_alloc(uint16_t * p_port) +{ + uint32_t err_code = SOCKET_NO_AVAILABLE_PORTS; + for (uint32_t i = IANA_EPHEMRAL_BEGIN; i <= IANA_EPHEMRAL_END; i++) + { + uint16_t port = (uint16_t)i; + err_code = portdb_register(port); + + if (err_code == NRF_SUCCESS) + { + *p_port = port; + break; + } + else if (err_code == SOCKET_NO_AVAILABLE_PORTS) + { + break; + } + } + return err_code; +} + +void portdb_free(uint16_t port) +{ + for (uint32_t i = 0; i < m_portdb_len; i++) + { + if (m_portdb[i] == port) + { + m_portdb[i] = 0; + break; + } + } +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/portdb/portdb.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/portdb/portdb.h new file mode 100644 index 0000000..94f0d38 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/libraries/portdb/portdb.h @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef PORTDB_H__ +#define PORTDB_H__ + +/** + * @file portdb.h + * + * @defgroup iot_socket_portdb Port Database + * @ingroup iot_sdk_socket + * @{ + * @brief Port database for sockets. + * + * The port database provides a functionality for registering, allocating, and freeing ports. + */ + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for initializing the port database. + * + * This must be called before allocating and freeing ports. + * + * @param max_len The max length of the portdb. + * + * @retval NRF_SUCCESS If successfully initialized. + */ +uint32_t portdb_init(uint32_t max_len); + +/** + * @brief Function for deinitializing the portdb. + * + * This will free all memory allocated by this portdb. + */ +void portdb_deinit(void); + +/** + * @brief Function to reset all ports without freeing any memories. + */ +void portdb_reset(void); + +/** + * @brief Function for allocating a port. + * + * Looks for an available port in the database and allocates it to the caller. + * + * @param[out] p_port Pointer to a variable where the allocated port number should be stored. + * + * @retval NRF_SUCCESS If a free port was located and successfully allocated. + * @retval SOCKET_NO_AVAILABLE_PORTS If no available ports were found. + */ +uint32_t portdb_alloc(uint16_t * p_port); + +/** + * @brief Function for registering a port. + * + * Marks a given port in the database as being in use. + * + * @param[in] port The port to mark as in use. + * + * @retval NRF_SUCCESS If port was successfully marked as in use. + * @retval SOCKET_NO_AVAILABLE_PORTS If there was no slot in which to register the port. + * @retval SOCKET_PORT_IN_USE If the port has already been registered or allocated. + */ +uint32_t portdb_register(uint16_t port); + +/** + * @brief Function for freeing a port. + * + * Mark a given port as free and make it available for others to register or allocate. + * + * @param[in] port The port to mark as free. + */ +void portdb_free(uint16_t port); + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // PORTDB_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/platform/ble/socket_ble.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/platform/ble/socket_ble.c new file mode 100644 index 0000000..da2cc7b --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/platform/ble/socket_ble.c @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include <stdint.h> +#include "nrf_soc.h" +#include "app_scheduler.h" + +uint32_t socket_wait(void) +{ + // Execute event schedule. + app_sched_execute(); + + return sd_app_evt_wait(); +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/transport/ipv6/transport_handler.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/transport/ipv6/transport_handler.c new file mode 100644 index 0000000..a9d6edd --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/transport/ipv6/transport_handler.c @@ -0,0 +1,387 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "iot_defines.h" +#include "iot_errors.h" +#include "sdk_config.h" +#include "socket_trace.h" +#include "socket_common.h" +#include "socket_config.h" +#include "config_medium.h" +#include "transport_if.h" +#include "udp_api.h" +#include "portdb.h" +#include "nrf_soc.h" +#include "nrf_fifo.h" + +/**@brief Verify that IPv6 address length is correct. */ +#define VERIFY_ADDRESS_LEN(len) \ + do { \ + if ((len) != sizeof(sockaddr_in6_t)) { \ + return NRF_ERROR_NULL | IOT_SOCKET_ERR_BASE; \ + } \ + } while (0) + +#define SOCKET_MAX_PENDING_PACKETS 32 /**< Maximum number of pending received packets. */ + +/**@brief Nordic IPv6 handle structure. */ +typedef struct +{ + udp6_socket_t socket; /**< UDP socket. */ + nrf_fifo_t recv_queue; /**< Received packets queue. */ + uint16_t local_port; /**< Local port number. */ +} ipv6_handle_t; + +static const char * unused = "UNUSED"; /**< A pointer indicating an unused socket. */ +static ipv6_handle_t ipv6_handles[SOCKET_MAX_SOCKET_COUNT]; /**< IPv6 handle array. */ + +void free_pbuffer(void * p_data) +{ + (void) iot_pbuffer_free((iot_pbuffer_t *)p_data, true); +} + +static ipv6_handle_t * ipv6_handle_allocate(socket_t * p_socket) +{ + ipv6_handle_t * p_handle = NULL; + for (uint32_t i = 0; i < SOCKET_MAX_SOCKET_COUNT; i++) + { + if (ipv6_handles[i].socket.p_app_data == unused) + { + p_handle = &ipv6_handles[i]; + p_handle->socket.p_app_data = p_socket; + (void) nrf_fifo_init(&p_handle->recv_queue, SOCKET_MAX_PENDING_PACKETS, socket_wait, free_pbuffer); + uint32_t err_code = udp6_socket_app_data_set(&p_handle->socket); + if (err_code != NRF_SUCCESS) + { + p_handle = NULL; + } + break; + } + } + return p_handle; +} + +static uint32_t ipv6_handle_free(ipv6_handle_t * p_handle) +{ + p_handle->local_port = 0; + p_handle->socket.p_app_data = (void *)unused; + return udp6_socket_app_data_set(&p_handle->socket); +} + +void transport_event_handler(iot_interface_t * p_interface, ipv6_event_t * p_event) +{ + (void) p_interface; + + switch (p_event->event_id) + { + case IPV6_EVT_INTERFACE_ADD: + transport_interface_up(); + break; + case IPV6_EVT_INTERFACE_DELETE: + transport_interface_down(); + break; + case IPV6_EVT_INTERFACE_RX_DATA: + break; + default: + break; + } +} + +void transport_handler_init(void) +{ + ipv6_init_t init_param; + init_param.p_eui64 = config_medium_local_iid(); + init_param.event_handler = transport_event_handler; + + uint32_t err_code = ipv6_init(&init_param); + (void) err_code; + // APP_ERROR_CHECK(err_code); + for (uint32_t i = 0; i< SOCKET_MAX_SOCKET_COUNT; i++) + { + ipv6_handles[i].local_port = 0; + ipv6_handles[i].socket.socket_id = 0; + ipv6_handles[i].socket.p_app_data = (void *)unused; + } +} + +static uint32_t ipv6_transport_open(socket_t * p_socket) +{ + uint32_t err_code = NRF_SUCCESS; + if (p_socket->so_params.so_type != SOCK_DGRAM) + { + err_code = SOCKET_UNSUPPORTED_PROTOCOL; + } + if (err_code == NRF_SUCCESS) + { + ipv6_handle_t * p_ipv6_handle = ipv6_handle_allocate(p_socket); + if (p_ipv6_handle == NULL) + { + err_code = NRF_ERROR_NULL; + } + else + { + err_code = udp6_socket_allocate(&p_ipv6_handle->socket); + if (err_code == NRF_SUCCESS) + { + p_socket->so_ctx = p_ipv6_handle; + } + else + { + (void) ipv6_handle_free(p_ipv6_handle); + } + } + } + return err_code; +} + +static uint32_t ipv6_transport_close(socket_t * p_socket) +{ + ipv6_handle_t * p_ipv6_handle = (ipv6_handle_t *) p_socket->so_ctx; + if (p_ipv6_handle->local_port > 0) + { + portdb_free(p_ipv6_handle->local_port); + } + + uint32_t err_code = udp6_socket_free(&p_ipv6_handle->socket); + if (err_code == NRF_SUCCESS) + { + err_code = ipv6_handle_free(p_ipv6_handle); + } + return err_code; +} + +static uint32_t ipv6_transport_recv_callback(const udp6_socket_t * p_udp_socket, + const ipv6_header_t * p_ip_header, + const udp6_header_t * p_udp_header, + uint32_t process_result, + iot_pbuffer_t * p_rx_packet) +{ + uint32_t err_code = process_result; + socket_t * p_socket = (socket_t *)p_udp_socket->p_app_data; + ipv6_handle_t * p_ipv6_handle = (ipv6_handle_t *)p_socket->so_ctx; + if (err_code == NRF_SUCCESS) + { + err_code = nrf_fifo_enq(&p_ipv6_handle->recv_queue, p_rx_packet, false); + if (err_code == NRF_SUCCESS) + { + p_socket->so_read_evt++; + err_code = IOT_IPV6_ERR_PENDING; + } + } + return err_code; +} + +static uint32_t ipv6_transport_bind(socket_t * p_socket, const void * p_addr, socklen_t addr_len) +{ + VERIFY_ADDRESS_LEN(addr_len); + const sockaddr_in6_t * p_addr_in6 = (const sockaddr_in6_t *)p_addr; + ipv6_handle_t * p_ipv6_handle = (ipv6_handle_t *)p_socket->so_ctx; + udp6_socket_t * p_udp_socket = &p_ipv6_handle->socket; + + p_ipv6_handle->local_port = HTONS(p_addr_in6->sin6_port); + uint32_t err_code = portdb_register(p_ipv6_handle->local_port); + if (err_code == NRF_SUCCESS) + { + ipv6_addr_t * p_ipv6_addr = (ipv6_addr_t *)&p_addr_in6->sin6_addr; + err_code = udp6_socket_bind(p_udp_socket, p_ipv6_addr, p_ipv6_handle->local_port); + } + if (err_code == NRF_SUCCESS) + { + err_code = udp6_socket_recv(p_udp_socket, ipv6_transport_recv_callback); + } + return err_code; +} + +static uint32_t ipv6_transport_bind_any(ipv6_handle_t * p_ipv6_handle) +{ + udp6_socket_t * p_udp_socket = &p_ipv6_handle->socket; + uint32_t err_code = portdb_alloc(&p_ipv6_handle->local_port); + if (err_code == NRF_SUCCESS) + { + SOCKET_TRACE("Binding to port %hu\r\n", p_ipv6_handle->local_port); + err_code = udp6_socket_bind(p_udp_socket, IPV6_ADDR_ANY, p_ipv6_handle->local_port); + } + + if (err_code == NRF_SUCCESS) + { + err_code = udp6_socket_recv(p_udp_socket, ipv6_transport_recv_callback); + } + return err_code; +} + +static uint32_t ipv6_transport_connect(socket_t * p_socket, const void * p_addr, socklen_t addr_len) +{ + VERIFY_ADDRESS_LEN(addr_len); + + ipv6_handle_t * p_ipv6_handle = (ipv6_handle_t *)p_socket->so_ctx; + udp6_socket_t * p_udp_socket = &p_ipv6_handle->socket; + const sockaddr_in6_t * p_addr_in6 = (const sockaddr_in6_t *)p_addr; + uint32_t err_code = NRF_SUCCESS; + + // Port might already have been bound with an explicit call to bind() + if (p_ipv6_handle->local_port == 0) + { + err_code = ipv6_transport_bind_any(p_ipv6_handle); + } + + if (err_code == NRF_SUCCESS) + { + // These data structures are compatible, and can therefore be cast + err_code = udp6_socket_connect(p_udp_socket, + (ipv6_addr_t *)&p_addr_in6->sin6_addr, + HTONS(p_addr_in6->sin6_port)); + } + + return err_code; +} + +static uint32_t ipv6_transport_send(socket_t * p_socket, + const void * p_buf, + uint32_t len, + int flags, + const void * p_destaddr, + socklen_t destaddr_len) +{ + ipv6_handle_t * p_ipv6_handle = (ipv6_handle_t *)p_socket->so_ctx; + udp6_socket_t * p_udp_socket = &p_ipv6_handle->socket; + uint32_t err_code = NRF_SUCCESS; + iot_pbuffer_alloc_param_t pbuff_param; + + // Ensure that port is bound before sending packet + if (p_ipv6_handle->local_port == 0) + { + err_code = ipv6_transport_bind_any(p_ipv6_handle); + } + + if (err_code == NRF_SUCCESS) + { + pbuff_param.flags = PBUFFER_FLAG_DEFAULT; + pbuff_param.type = UDP6_PACKET_TYPE; + pbuff_param.length = len; + + iot_pbuffer_t * p_buffer = NULL; + err_code = iot_pbuffer_allocate(&pbuff_param, &p_buffer); + if (err_code == NRF_SUCCESS) + { + memcpy(p_buffer->p_payload, p_buf, len); + if (p_destaddr != NULL && destaddr_len == sizeof(sockaddr_in6_t)) + { + sockaddr_in6_t * p_addr_in6 = (sockaddr_in6_t *)p_destaddr; + err_code = udp6_socket_sendto(p_udp_socket, + (ipv6_addr_t *)&p_addr_in6->sin6_addr, + HTONS(p_addr_in6->sin6_port), + p_buffer); + } + else + { + err_code = udp6_socket_send(p_udp_socket, p_buffer); + } + } + } + return err_code; +} + +static uint32_t ipv6_transport_recv(socket_t * p_socket, + void * p_buf, + uint32_t * p_sz, + int flags, + void * p_srcaddr, + socklen_t * p_srcaddr_len) +{ + if ((p_socket->so_flags & O_NONBLOCK) != 0 && + (flags & MSG_WAITALL) == 0) + { + flags |= MSG_DONTWAIT; + } + + ipv6_handle_t * p_ipv6_handle = (ipv6_handle_t *)p_socket->so_ctx; + iot_pbuffer_t * p_pbuffer = NULL; + uint32_t err_code = nrf_fifo_deq(&p_ipv6_handle->recv_queue, + (void **)&p_pbuffer, + (flags & MSG_DONTWAIT) == 0); + if (err_code == NRF_SUCCESS) + { + uint32_t copy_len = MIN(*p_sz, p_pbuffer->length); + memcpy(p_buf, p_pbuffer->p_payload, copy_len); + *p_sz = copy_len; + + if (p_srcaddr != NULL && p_srcaddr_len != NULL) + { + const udp6_header_t * p_udp_header = + (udp6_header_t *)(p_pbuffer->p_payload - UDP_HEADER_SIZE); + const ipv6_header_t * p_ipv6_header = + (ipv6_header_t *)(p_pbuffer->p_payload - UDP_HEADER_SIZE - IPV6_IP_HEADER_SIZE); + sockaddr_in6_t * p_srcsockaddr = (sockaddr_in6_t *)p_srcaddr; + + *p_srcaddr_len = sizeof(sockaddr_in6_t); + p_srcsockaddr->sin6_addr = *((in6_addr_t *)&p_ipv6_header->srcaddr); + p_srcsockaddr->sin6_port = HTONS(p_udp_header->srcport); + p_srcsockaddr->sin6_len = *p_srcaddr_len; + p_srcsockaddr->sin6_family = AF_INET6; + p_srcsockaddr->sin6_flowinfo = 0; + p_srcsockaddr->sin6_scope_id = 0; + } + + (void) iot_pbuffer_free(p_pbuffer, true); + p_socket->so_read_evt = 0; + } + return err_code; +} + +static uint32_t ipv6_transport_listen(socket_t * p_socket, int backlog) +{ + // Ignore as this does not make sense for UDP + (void) p_socket; + (void) backlog; + return NRF_SUCCESS; +} + +/** + * @brief Transport for Nordic IPv6 socket. + */ +socket_transport_t transport_impl = +{ + .open = ipv6_transport_open, + .bind = ipv6_transport_bind, + .connect = ipv6_transport_connect, + .send = ipv6_transport_send, + .recv = ipv6_transport_recv, + .listen = ipv6_transport_listen, + .close = ipv6_transport_close +}; diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/transport/lwip/transport_handler.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/transport/lwip/transport_handler.c new file mode 100644 index 0000000..4537053 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/socket/transport/lwip/transport_handler.c @@ -0,0 +1,630 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "iot_defines.h" +#include "iot_errors.h" +#include "sdk_config.h" +#include "socket_common.h" +#include "socket_trace.h" +#include "transport_if.h" +#include "portdb.h" +#include "app_timer.h" +#include "mem_manager.h" +#include "nrf_fifo.h" +#include "mbuf.h" +#include "app_util.h" +#include "nrf_platform_port.h" +#include "app_util_platform.h" + +#include "lwip/opt.h" +#include "lwip/init.h" +#include "lwip/tcp.h" +#include "lwip/timers.h" + +/**@brief Verify that IPv6 address length is correct. */ +#define VERIFY_ADDRESS_LEN(len) \ + do { \ + if ((len) != sizeof(sockaddr_in6_t)) { \ + return NRF_ERROR_NULL | IOT_SOCKET_ERR_BASE; \ + } \ + } while (0) + +#define LWIP_SYS_TIMER_INTERVAL APP_TIMER_TICKS(100) /**< Interval for timer used as trigger to send. */ + +#define SOCKET_MAX_PENDING_PACKETS 32 /**< Maximum number of pending received packets. */ +#define SOCKET_MAX_PENDING_CONNECTIONS 10 /**< Maximum number of simultaneous connections. */ + +/**@brief TCP state */ +typedef enum +{ + TCP_STATE_IDLE, + TCP_STATE_REQUEST_CONNECTION, + TCP_STATE_CONNECTED, + TCP_STATE_DATA_TX_IN_PROGRESS, + TCP_STATE_TCP_SEND_PENDING, + TCP_STATE_DISCONNECTED +} tcp_state_t; + +/**@brief LwIP handle structure. */ +typedef struct { + struct tcp_pcb * p_pcb; /**< A pointer to LwIP TCP protocol control block. */ + socket_t * p_socket; /**< A pointer to corresponding socket. */ + nrf_fifo_t conn_queue; /**< Connections queue. */ + mbuf_t mbuf; /**< Memory management queue. */ + volatile tcp_state_t tcp_state; /**< TCP state. */ +} lwip_handle_t; + +static lwip_handle_t lwip_handles[SOCKET_MAX_SOCKET_COUNT]; /**< LwIP handle array. */ + +/**@brief Timer for LwIP. */ +APP_TIMER_DEF(m_lwip_timer_id); + +static err_t lwip_recv_callback(void * p_arg, + struct tcp_pcb * p_pcb, + struct pbuf * p_pbuf, + err_t err); + +static uint32_t lwip_buf_read(void * p_ctx, + uint32_t read_offset, + uint8_t * p_destbuf, + uint32_t destbuf_len) +{ + struct pbuf * p_pbuf = (struct pbuf *)p_ctx; + uint32_t copy_len = MIN(destbuf_len, (p_pbuf->len - read_offset)); + memcpy(p_destbuf, (void *)(((uint8_t *)p_pbuf->payload) + read_offset), copy_len); + return copy_len; +} + +static uint32_t lwip_buf_len(void * p_ctx) +{ + struct pbuf * p_pbuf = (struct pbuf *)p_ctx; + return p_pbuf->len; +} + +static void lwip_buf_free(void * p_ctx) +{ + nrf_free(((struct pbuf *)p_ctx)->payload); + (void) pbuf_free((struct pbuf *)p_ctx); +} + +static void lwip_timer_callback(void * p_ctx) +{ + (void) p_ctx; + sys_check_timeouts(); +} + +void nrf_driver_interface_up(iot_interface_t const * p_interface) +{ + UNUSED_PARAMETER(p_interface); + transport_interface_up(); +} + +void nrf_driver_interface_down(iot_interface_t const * p_interface) +{ + UNUSED_PARAMETER(p_interface); + transport_interface_down(); +} + +void transport_handler_init(void) +{ + lwip_init(); + uint32_t err_code = nrf_driver_init(); + APP_ERROR_CHECK(err_code); + for (uint32_t i = 0; i < SOCKET_MAX_SOCKET_COUNT; i++) + { + lwip_handles[i].p_pcb = NULL; + lwip_handles[i].p_socket = NULL; + lwip_handles[i].tcp_state = TCP_STATE_IDLE; + } + err_code = app_timer_create(&m_lwip_timer_id, + APP_TIMER_MODE_REPEATED, + lwip_timer_callback); + APP_ERROR_CHECK(err_code); + err_code = app_timer_start(m_lwip_timer_id, LWIP_SYS_TIMER_INTERVAL, NULL); + APP_ERROR_CHECK(err_code); + SOCKET_TRACE("Initialized LWIP transport handler\r\n"); +} + +static void lwip_error_handler(void * p_arg, err_t err) +{ + (void) p_arg; + SOCKET_TRACE("Error occured: %d\r\n", (int)err); + if(err == ERR_ABRT) + { + portdb_reset(); + } +} + +static err_t lwip_poll_handler(void * p_arg, struct tcp_pcb * p_pcb) +{ + (void) p_arg; + (void) p_pcb; + + return ERR_OK; +} + +static void lwip_drop_connection(void * p_ctx) +{ + struct tcp_pcb * p_pcb = (struct tcp_pcb *)p_ctx; + tcp_abort(p_pcb); +} + +static lwip_handle_t * lwip_handle_allocate(socket_t * p_socket, struct tcp_pcb * p_pcb) +{ + lwip_handle_t * p_handle = NULL; + for (uint32_t i = 0; i < SOCKET_MAX_SOCKET_COUNT; i++) + { + if (lwip_handles[i].p_pcb == NULL) + { + p_handle = &lwip_handles[i]; + (void)mbuf_init(&p_handle->mbuf, + lwip_buf_read, + lwip_buf_len, + lwip_buf_free, + SOCKET_MAX_PENDING_PACKETS); + (void) nrf_fifo_init(&p_handle->conn_queue, + SOCKET_MAX_PENDING_CONNECTIONS, + socket_wait, + lwip_drop_connection); + p_handle->p_socket = p_socket; + p_handle->tcp_state = TCP_STATE_IDLE; + if (p_pcb == NULL) + { + p_handle->p_pcb = tcp_new(); + } + else + { + p_handle->p_pcb = p_pcb; + } + tcp_arg(p_handle->p_pcb, p_handle); + tcp_setprio(p_handle->p_pcb, TCP_PRIO_MIN); + tcp_recv(p_handle->p_pcb, lwip_recv_callback); + tcp_err(p_handle->p_pcb, lwip_error_handler); + tcp_poll(p_handle->p_pcb, lwip_poll_handler, 0); + break; + } + } + SOCKET_TRACE("Allocated LWIP socket handle\r\n"); + return p_handle; +} + +static void lwip_handle_free(lwip_handle_t * p_handle) +{ + nrf_fifo_deinit(&p_handle->conn_queue); + mbuf_deinit(&p_handle->mbuf); + p_handle->p_pcb = NULL; + p_handle->p_socket = NULL; + p_handle->tcp_state = TCP_STATE_IDLE; + SOCKET_TRACE("Released LWIP socket handle\r\n"); +} + +static uint32_t lwip_transport_open(socket_t * p_socket) +{ + lwip_handle_t * p_handle = NULL; + uint32_t err_code = NRF_SUCCESS; + switch (p_socket->so_params.so_type) + { + case SOCK_STREAM: + p_handle = lwip_handle_allocate(p_socket, NULL); + if (p_handle == NULL) + { + err_code = NRF_ERROR_NULL; + } + else + { + p_socket->so_ctx = p_handle; + } + break; + default: + err_code = NRF_ERROR_NULL; + break; + } + return err_code; +} + +uint32_t lwip_error_convert(err_t lwip_err) +{ + uint32_t err_code = NRF_ERROR_NULL; + switch (lwip_err) + { + case ERR_OK: + err_code = NRF_SUCCESS; + break; + case ERR_MEM: + err_code = SOCKET_NO_MEM; + break; + case ERR_TIMEOUT: + err_code = SOCKET_TIMEOUT; + break; + case ERR_RTE: + err_code = SOCKET_NO_ROUTE; + break; + default: + err_code = NRF_ERROR_NULL; + break; + } + return err_code; +} + +static uint32_t lwip_transport_close(socket_t * p_socket) +{ + lwip_handle_t * p_handle = (lwip_handle_t *)p_socket->so_ctx; + portdb_free((uint16_t)p_handle->p_pcb->local_port); + err_t err_code = tcp_close(p_handle->p_pcb); + if (err_code == ERR_OK) + { + lwip_handle_free(p_handle); + } + return lwip_error_convert(err_code); +} + +static err_t lwip_connect_callback(void * p_arg, struct tcp_pcb * p_pcb, err_t err) +{ + lwip_handle_t * p_handle = (lwip_handle_t *)p_arg; + // TODO: Error check + SOCKET_TRACE("New connection\r\n"); + p_handle->tcp_state = TCP_STATE_CONNECTED; + return ERR_OK; +} + +static err_t lwip_recv_callback(void * p_arg, + struct tcp_pcb * p_pcb, + struct pbuf * p_pbuf, + err_t err) +{ + lwip_handle_t * p_handle = (lwip_handle_t *)p_arg; + socket_t * p_socket = p_handle->p_socket; + if (err == ERR_OK) + { + uint8_t * p_payload_cp = nrf_malloc(p_pbuf->len); + struct pbuf * p_pbuf_cp = pbuf_alloc(PBUF_RAW, p_pbuf->len, PBUF_REF); + + memcpy(p_payload_cp, p_pbuf->payload, p_pbuf->len); + p_pbuf_cp->payload = p_payload_cp; + p_pbuf_cp->len = p_pbuf->len; + p_pbuf_cp->tot_len = p_pbuf->tot_len; + + uint32_t err_code = mbuf_write(&p_handle->mbuf, p_pbuf_cp); + if (err_code == NRF_SUCCESS) + { + p_socket->so_read_evt++; + } + else + { + err = ERR_MEM; + } + } + return err; +} + +static uint32_t lwip_wait_for_state(lwip_handle_t * p_handle, tcp_state_t state) +{ + uint32_t err_code = NRF_SUCCESS; + while (err_code == NRF_SUCCESS && + p_handle->tcp_state != state && + p_handle->tcp_state != TCP_STATE_DISCONNECTED) + { + err_code = socket_wait(); + } + if (err_code == NRF_SUCCESS && p_handle->tcp_state != state) + { + err_code = NRF_ERROR_NULL; + } + return err_code; +} + +static void lwipaddr_to_sockaddr(const ip6_addr_t * p_lwip_addr, sockaddr_in6_t * p_addr_in6) +{ + struct in6_addr * addr = &p_addr_in6->sin6_addr; + addr->s6_addr[0] = p_lwip_addr->addr[0] & 0xFF; + addr->s6_addr[1] = (p_lwip_addr->addr[0] >> 8) & 0xFF; + addr->s6_addr[2] = (p_lwip_addr->addr[0] >> 16) & 0xFF; + addr->s6_addr[3] = (p_lwip_addr->addr[0] >> 24) & 0xFF; + + addr->s6_addr[4] = p_lwip_addr->addr[1] & 0xFF; + addr->s6_addr[5] = (p_lwip_addr->addr[1] >> 8) & 0xFF; + addr->s6_addr[6] = (p_lwip_addr->addr[1] >> 16) & 0xFF; + addr->s6_addr[7] = (p_lwip_addr->addr[1] >> 24) & 0xFF; + + addr->s6_addr[8] = p_lwip_addr->addr[2] & 0xFF; + addr->s6_addr[9] = (p_lwip_addr->addr[2] >> 8) & 0xFF; + addr->s6_addr[10] = (p_lwip_addr->addr[2] >> 16) & 0xFF; + addr->s6_addr[11] = (p_lwip_addr->addr[2] >> 24) & 0xFF; + + addr->s6_addr[12] = p_lwip_addr->addr[3] & 0xFF; + addr->s6_addr[13] = (p_lwip_addr->addr[3] >> 8) & 0xFF; + addr->s6_addr[14] = (p_lwip_addr->addr[3] >> 16) & 0xFF; + addr->s6_addr[15] = (p_lwip_addr->addr[3] >> 24) & 0xFF; +} + +static void sockaddr_to_lwipaddr(const sockaddr_in6_t * p_addr_in6, ip6_addr_t * p_lwip_addr) +{ + const struct in6_addr * addr = &p_addr_in6->sin6_addr; + IP6_ADDR_PART(p_lwip_addr, 0, addr->s6_addr[0], addr->s6_addr[1], addr->s6_addr[2], addr->s6_addr[3]); + IP6_ADDR_PART(p_lwip_addr, 1, addr->s6_addr[4], addr->s6_addr[5], addr->s6_addr[6], addr->s6_addr[7]); + IP6_ADDR_PART(p_lwip_addr, 2, addr->s6_addr[8], addr->s6_addr[9], addr->s6_addr[10], addr->s6_addr[11]); + IP6_ADDR_PART(p_lwip_addr, 3, addr->s6_addr[12], addr->s6_addr[13], addr->s6_addr[14], addr->s6_addr[15]); +} + +static uint32_t lwip_transport_bind(socket_t * p_socket, const void * p_addr, socklen_t addr_len) +{ + VERIFY_ADDRESS_LEN(addr_len); + const sockaddr_in6_t * p_addr_in6 = (const sockaddr_in6_t *)p_addr; + lwip_handle_t * p_handle = (lwip_handle_t *)p_socket->so_ctx; + + uint16_t port = HTONS(p_addr_in6->sin6_port); + uint32_t err_code = portdb_register(port); + if (err_code == NRF_SUCCESS) + { + ip6_addr_t lwip_addr; + sockaddr_to_lwipaddr(p_addr_in6, &lwip_addr); + err_t err = tcp_bind(p_handle->p_pcb, &lwip_addr, port); + err_code = lwip_error_convert(err); + } + return err_code; +} + +static uint32_t lwip_transport_connect(socket_t * p_socket, + const void * p_addr, + socklen_t addr_len) +{ + VERIFY_ADDRESS_LEN(addr_len); + + bool is_blocking = ((p_socket->so_flags & O_NONBLOCK) == 0); + lwip_handle_t * p_handle = (lwip_handle_t *)p_socket->so_ctx; + const sockaddr_in6_t * p_addr_in6 = (const sockaddr_in6_t *)p_addr; + uint16_t port = 0; + uint32_t err_code = portdb_alloc(&port); + + SOCKET_TRACE("Binding to port %d\r\n", (int)port); + if (err_code == NRF_SUCCESS) + { + ip6_addr_t any_addr; + ip6_addr_set_any(&any_addr); + err_t err = tcp_bind (p_handle->p_pcb, &any_addr, port); + SOCKET_TRACE("Err %d from bind\r\n", (int)err); + err_code = lwip_error_convert(err); + } + + if (err_code == NRF_SUCCESS) + { + ip6_addr_t remote_addr; + sockaddr_to_lwipaddr(p_addr_in6, &remote_addr); + + p_handle->tcp_state = TCP_STATE_REQUEST_CONNECTION; + err_t err = tcp_connect(p_handle->p_pcb, &remote_addr, HTONS(p_addr_in6->sin6_port), lwip_connect_callback); + SOCKET_TRACE("Err %d from connect\r\n", (int)err); + err_code = lwip_error_convert(err); + + if (err_code == NRF_SUCCESS && is_blocking) + { + err_code = lwip_wait_for_state(p_handle, TCP_STATE_CONNECTED); + } + } + if (err_code != NRF_SUCCESS) + { + SOCKET_TRACE("Error %d when connecting to socket\r\n", (int)err_code); + portdb_free(port); + } + else + { + SOCKET_TRACE("Successfully connected to remote host!\r\n"); + } + + return err_code; +} + +static err_t lwip_send_complete(void * p_arg, struct tcp_pcb * p_pcb, u16_t len) +{ + lwip_handle_t * p_handle = (lwip_handle_t *)p_arg; + if (p_handle->tcp_state == TCP_STATE_TCP_SEND_PENDING) + { + p_handle->tcp_state = TCP_STATE_DATA_TX_IN_PROGRESS; + } + return ERR_OK; +} + +static inline uint32_t lwip_check_connected(socket_t * p_socket) +{ + return (p_socket->so_state == STATE_CONNECTED || p_socket->so_params.so_type == SOCK_DGRAM) ? + NRF_SUCCESS : SOCKET_NOT_CONNECTED; +} + + +static uint32_t lwip_transport_send(socket_t * p_socket, + const void * p_buf, + uint32_t buf_len, + int flags, + const void * p_destaddr, + socklen_t destaddr_len) +{ + (void) p_destaddr; + (void) destaddr_len; + + lwip_handle_t * p_handle = (lwip_handle_t *)p_socket->so_ctx; + if ((p_socket->so_flags & O_NONBLOCK) != 0 && + (flags & MSG_WAITALL) == 0) + { + flags |= MSG_DONTWAIT; + } + + uint32_t err_code = lwip_check_connected(p_socket); + if (err_code == NRF_SUCCESS) + { + uint32_t len = tcp_sndbuf(p_handle->p_pcb); + if (len >= buf_len) + { + tcp_sent(p_handle->p_pcb, lwip_send_complete); + p_handle->tcp_state = TCP_STATE_TCP_SEND_PENDING; + err_t err = tcp_write(p_handle->p_pcb, p_buf, buf_len, 1); + err_code = lwip_error_convert(err); + if (err_code == NRF_SUCCESS && + (flags & MSG_DONTWAIT) == 0) + { + err_code = lwip_wait_for_state(p_handle, TCP_STATE_DATA_TX_IN_PROGRESS); + } + } + else + { + err_code = SOCKET_NO_MEM; + } + } + return err_code; +} + + +static uint32_t lwip_transport_recv(socket_t * p_socket, + void * p_buf, + uint32_t * p_buf_size, + int flags, + void * p_srcaddr, + socklen_t * p_srcaddr_len) +{ + lwip_handle_t * p_handle = (lwip_handle_t *)p_socket->so_ctx; + if ((p_socket->so_flags & O_NONBLOCK) != 0 && + (flags & MSG_WAITALL) == 0) + { + flags |= MSG_DONTWAIT; + } + uint32_t err_code = lwip_check_connected(p_socket); + if (err_code == NRF_SUCCESS) + { + if (mbuf_empty(&p_handle->mbuf) == true) + { + if ((flags & MSG_DONTWAIT) != 0) + { + err_code = SOCKET_WOULD_BLOCK; + } + else + { + while ((mbuf_empty(&p_handle->mbuf) == true) && (err_code == NRF_SUCCESS)) + { + err_code = socket_wait(); + } + } + } + } + + if (err_code == NRF_SUCCESS) + { + *p_buf_size = mbuf_read(&p_handle->mbuf, p_buf, *p_buf_size); + tcp_recved(p_handle->p_pcb, *p_buf_size); + p_socket->so_read_evt = 0; + } + return err_code; +} + +static err_t lwip_accept_callback(void * p_arg, struct tcp_pcb * p_pcb, err_t err) +{ + lwip_handle_t * p_handle = (lwip_handle_t *)p_arg; + socket_t * p_socket = p_handle->p_socket; + if (err == ERR_OK) + { + (void) nrf_fifo_enq(&p_handle->conn_queue, p_pcb, true); + // TODO: Error check + p_socket->so_read_evt++; + } + return err; +} + +static uint32_t lwip_transport_listen(socket_t * p_socket, int backlog) +{ + lwip_handle_t * p_handle = (lwip_handle_t *)p_socket->so_ctx; + uint32_t err_code = NRF_SUCCESS; + struct tcp_pcb * p_pcb = tcp_listen_with_backlog(p_handle->p_pcb, backlog); + if (p_pcb == NULL) + { + err_code = SOCKET_ADDRESS_IN_USE; + } + else + { + p_handle->p_pcb = p_pcb; + tcp_accept(p_handle->p_pcb, lwip_accept_callback); + } + return err_code; +} + +static uint32_t lwip_transport_accept(socket_t * p_socket, + socket_t * p_client, + void * p_cliaddr, + socklen_t * p_cliaddr_len) +{ + VERIFY_ADDRESS_LEN(*p_cliaddr_len); + struct tcp_pcb * p_client_pcb = NULL; + lwip_handle_t * p_lwip_handle = (lwip_handle_t *)p_socket->so_ctx; + uint32_t err_code = nrf_fifo_deq(&p_lwip_handle->conn_queue, + (void **)&p_client_pcb, + (p_socket->so_flags & O_NONBLOCK) == 0); + + if (err_code == NRF_SUCCESS) + { + lwip_handle_t * p_lwip_client = lwip_handle_allocate(p_client, p_client_pcb); + sockaddr_in6_t * p_sockaddr = (sockaddr_in6_t *)p_cliaddr; + + p_client->so_ctx = p_lwip_client; + + lwipaddr_to_sockaddr(&p_client_pcb->remote_ip, p_sockaddr); + p_sockaddr->sin6_port = p_client_pcb->remote_port; + p_sockaddr->sin6_len = *p_cliaddr_len; + p_sockaddr->sin6_family = AF_INET6; + p_sockaddr->sin6_flowinfo = 0; + p_sockaddr->sin6_scope_id = 0; + + /*lint -save -e548 */ + tcp_accepted(p_lwip_handle->p_pcb); + /*lint -restore */ + } + + return err_code; +} + +/** + * @brief Transport for LwIP socket. + */ +socket_transport_t transport_impl = +{ + .open = lwip_transport_open, + .bind = lwip_transport_bind, + .connect = lwip_transport_connect, + .send = lwip_transport_send, + .recv = lwip_transport_recv, + .listen = lwip_transport_listen, + .accept = lwip_transport_accept, + .close = lwip_transport_close +}; |