1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

posix: redo socket API to use conn

This commit is contained in:
Martine Lenders 2015-08-17 13:48:08 +02:00 committed by Martine Lenders
parent fda6155071
commit 624530c7d0
12 changed files with 1372 additions and 542 deletions

View File

@ -1,9 +1,5 @@
ifneq (,$(filter libcoap,$(USEPKG)))
USEMODULE += pnet
endif
ifneq (,$(filter pnet,$(USEMODULE)))
USEMODULE += vtimer
USEMODULE += posix_sockets
endif
ifneq (,$(filter gnrc_%,$(filter-out gnrc_netapi gnrc_netreg gnrc_netif% gnrc_pktbuf,$(USEMODULE))))
@ -276,6 +272,11 @@ ifneq (,$(filter newlib,$(USEMODULE)))
USEMODULE += uart_stdio
endif
ifneq (,$(filter posix_sockets,$(USEMODULE)))
USEMODULE += posix
USEMODULE += random
endif
ifneq (,$(filter posix,$(USEMODULE)))
USEMODULE += timex
USEMODULE += vtimer

View File

@ -1,5 +1,5 @@
ifneq (,$(filter pnet,$(USEMODULE)))
DIRS += posix/pnet
ifneq (,$(filter posix_sockets,$(USEMODULE)))
DIRS += posix/sockets
endif
ifneq (,$(filter pthread,$(USEMODULE)))
DIRS += posix/pthread

View File

@ -18,7 +18,7 @@ ifneq (,$(filter posix,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter pnet,$(USEMODULE)))
ifneq (,$(filter posix_sockets,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
endif
ifneq (,$(filter pthread,$(USEMODULE)))

View File

@ -31,29 +31,13 @@
#include "net/af.h"
#include "net/ipv4/addr.h"
#include "net/ipv6/addr.h"
#include "socket_base/socket.h"
#include "sys/bytes.h"
#include "netinet/in.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef uint16_t in_port_t; /**< Internet port type */
typedef uint32_t in_addr_t; /**< IPv4 address type */
/**
* @brief Alias to @ref IPV4_ADDR_MAX_STR_LEN
*/
#ifndef INET_ADDRSTRLEN
#define INET_ADDRSTRLEN (IPV4_ADDR_MAX_STR_LEN)
#endif
/**
* @brief Alias to @ref IPV6_ADDR_MAX_STR_LEN
*/
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN (IPV6_ADDR_MAX_STR_LEN)
#endif
/**
* @brief Size in byte of an IPv4 address
*/
@ -68,66 +52,6 @@ typedef uint32_t in_addr_t; /**< IPv4 address type */
#define IN6ADDRSZ (sizeof(ipv6_addr_t))
#endif
/**
* @brief IPv4 address structure type.
*/
struct in_addr {
in_addr_t s_addr; ///< an IPv4 address
};
/**
* @brief Convert values between host and network byte order.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/htonl.html">
* The Open Group Base Specification Issue 7, htonl
* </a>
*
* @param[in] hostlong A 32 bit number.
* @return The argument value converted from host to network byte
* order.
*/
#define htonl(hostlong) HTONL(hostlong)
/**
* @brief Convert values between host and network byte order.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/htons.html">
* The Open Group Base Specification Issue 7, htons
* </a>
*
* @param[in] hostshort A 16 bit number.
* @return The argument value converted from host to network byte
* order.
*/
#define htons(hostshort) HTONS(hostshort)
/**
* @brief Convert values between host and network byte order.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/ntohl.html">
* The Open Group Base Specification Issue 7, ntohl
* </a>
*
* @param[in] netlong A 32-bit integer number.
* @return The argument value converted from network to host byte
* order.
*/
#define ntohl(netlong) NTOHL(netlong)
/**
* @brief Convert values between host and network byte order.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/ntohs.html">
* The Open Group Base Specification Issue 7, ntohs
* </a>
*
* @param[in] netshort A 16-bit integer number.
* @return The argument value converted from network to host byte
* order.
*/
#define ntohs(netshort) NTOHS(netshort)
/**
* @brief Converts an IP address to its string representation
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 Freie Universität Berlin
* Copyright (C) 2013-15 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -7,7 +7,7 @@
*/
/**
* @addtogroup pnet
* @addtogroup posix_sockets
* @{
*/
@ -25,105 +25,17 @@
#include <inttypes.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "net/gnrc/ipv6.h"
#include "socket_base/socket.h"
#include "net/protnum.h"
#include "net/ipv6/addr.h"
#include "sys/bytes.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* IPv4 socket address type.
*/
struct sockaddr_in {
sa_family_t sin_family; ///< Protocol family, always AF_INET.
in_port_t sin_port; ///< Port number
struct in_addr sin_addr; ///< IPv4 address
};
/**
* IPv6 address structure type.
*/
struct in6_addr {
/**
* Private RIOT-internal data, needs not to be touched by the user.
*/
ipv6_addr_t __in6_u;
/**
* IPv6 Address represented as sequence of 8-bit numbers. Member of
* struct in6_addr.
*/
#define s6_addr __in6_u.uint8
/**
* IPv6 Address represented as sequence of 16-bit numbers. Member of
* struct in6_addr.
*/
#define s6_addr16 __in6_u.uint16
/**
* IPv6 Address represented as sequence of 32-bit numbers. Member of
* struct in6_addr.
*/
#define s6_addr32 __in6_u.uint32
};
/**
* IPv6 socket address type.
*/
struct sockaddr_in6 {
/**
* Private RIOT-internal data, needs not to be touched by the user.
*/
sockaddr6_t __in6_a;
/**
* Protocol family, always AF_INET6. Member of struct sockaddr_in6
*/
#define sin6_family __in6_a.sin6_family
/**
* Port number. Member of struct sockaddr_in6
*/
#define sin6_port __in6_a.sin6_port
/**
* IPv6 traffic class and flow information. Member of struct sockaddr_in6
*/
#define sin6_flowinfo __in6_a.sin6_flowinfo
/**
* IPv6 address. Member of struct sockaddr_in6
*/
#define sin6_addr __in6_a.sin6_addr
/**
* Set of interfaces for a scope.
*/
uint32_t sin6_scope_id;
};
/**
* IPv6 wildcard address.
*/
#define IN6ADDR_ANY_INIT {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}
/**
* IPv6 loopback address.
*/
#define IN6ADDR_LOOPBACK_INIT {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}}
/**
* IPv6 socket address for the wildcard address.
*/
extern const struct sockaddr_in6 in6addr_any;
/**
* IPv6 socket address for the loopback address.
*/
extern const struct sockaddr_in6 in6addr_loopback;
#define INET_ADDRSTRLEN (16) /**< Length of the string form for IPv4. */
#define INET6_ADDRSTRLEN (46) /**< Length of the string form for IPv6. */
/**
* IPv4 local host address.
@ -136,24 +48,221 @@ extern const struct sockaddr_in6 in6addr_loopback;
#define INADDR_BROADCAST ((in_addr_t)0xffffffff)
/**
* Multicast hop limit option name for getsockopt() or setsockopt()
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html">
* The Open Group Base Specification Issue 7, getsockopt
* </a>
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html">
* The Open Group Base Specification Issue 7, setsockopt
* </a>
* IPv6 wildcard address.
*/
#define IPV6_MULTICAST_HOPS 0x12
#define IN6ADDR_ANY_INIT IPV6_ADDR_UNSPECIFIED
/**
* Test for IPv6 multicast address.
*
* @param[in] a An IPv6 address.
* @return 1 if *a* is an multicast address, 0 if not.
* IPv6 loopback address.
*/
#define IN6_IS_ADDR_MULTICAST(a) (((const uint8_t *) (a))[0] == 0xff)
#define IN6ADDR_LOOPBACK_INIT IPV6_ADDR_LOOPBACK
/**
* @name IPv6 address macros
* @{
*/
/**
* @brief Check if address is the unspecified address (`::`).
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not the unspecified address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_UNSPECIFIED(addr) ((int)(ipv6_addr_is_unspecified((const ipv6_addr_t *)(addr))))
/**
* @brief Check if address is the loopback address (`::1`).
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not the loopback address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_LOOPBACK(addr) ((int)(ipv6_addr_is_loopback((const ipv6_addr_t *)(addr))))
/**
* @brief Check if address is a multicast address.
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not a multicast address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_MULTICAST(addr) ((int)(ipv6_addr_is_multicast((const ipv6_addr_t *)(addr))))
/**
* @brief Check if address is a link-local address.
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not a link-local address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_LINKLOCAL(addr) ((int)(ipv6_addr_is_link_local((const ipv6_addr_t *)addr)))
/**
* @brief Check if address is a site-local address.
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not a site-local address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_SITELOCAL(addr) ((int)(ipv6_addr_is_site_local((const ipv6_addr_t *)addr)))
/**
* @brief Check if address is an IPv4 mapped address.
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not an IPv4 mapped address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_V4MAPPED(addr) ((int)(ipv6_addr_is_ipv4_mapped((const ipv6_addr_t *)addr)))
/**
* @brief Check if address is an IPv4-compatible address.
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not an IPv4-compatible address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_V4COMPAT(addr) ((int)(ipv6_addr_is_ipv4_compat((const ipv6_addr_t *)addr)))
/**
* @brief Check if address is a multicast node-local address.
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not a multicast node-local address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_MC_NODELOCAL(addr) (IN6_IS_ADDR_MULTICAST(addr) && \
(int)((addr->s6_addr[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_IF_LOCAL))
/**
* @brief Check if address is a multicast link-local address.
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not a multicast link-local address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_MC_LINKLOCAL(addr) (IN6_IS_ADDR_MULTICAST(addr) && \
(int)((addr->s6_addr[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_LINK_LOCAL))
/**
* @brief Check if address is a multicast site-local address.
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not a multicast site-local address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_MC_SITELOCAL(addr) (IN6_IS_ADDR_MULTICAST(addr) && \
(int)((addr->s6_addr[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_SITE_LOCAL))
/**
* @brief Check if address is a multicast organization-local address.
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not a multicast organization-local address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_MC_ORGLOCAL(addr) (IN6_IS_ADDR_MULTICAST(addr) && \
(int)((addr->s6_addr[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_ORG_LOCAL))
/**
* @brief Check if address is a multicast global address.
*
* @param[in] addr address of type `const struct in6_addr *`
*
* @return 0, when an address is not a multicast global address.
* @return any other value otherwise.
*/
#define IN6_IS_ADDR_MC_GLOBAL(addr) (IN6_IS_ADDR_MULTICAST(addr) && \
(int)((addr->s6_addr[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_GLOBAL))
/** @} */
/**
* @name Protocol numbers for option
* @{
*/
#define IPPROTO_IP (PROTNUM_IPV4) /**< Internet Protocol version 4 */
#define IPPROTO_IPV6 (PROTNUM_IPV6) /**< Internet Protocol version 6 */
#define IPPROTO_ICMP (PROTNUM_ICMP) /**< Internet Control Message Protocol */
#define IPPROTO_ICMPV6 (PROTNUM_ICMPV6) /**< ICMP for IPv6 */
#define IPPROTO_RAW (PROTNUM_RESERVED) /**< Raw IP packets protocol */
#define IPPROTO_TCP (PROTNUM_TCP) /**< Transmission control protocol */
#define IPPROTO_UDP (PROTNUM_UDP) /**< User datagram protocol */
/** @} */
/**
* @todo IPv6 option names
*/
typedef uint16_t in_port_t; /**< Internet port type */
typedef uint32_t in_addr_t; /**< IPv4 address type */
/**
* IPv4 address structure type.
*/
struct in_addr {
in_addr_t s_addr; /**< an IPv4 address */
};
/**
* @brief IPv6 address structure type.
*/
struct in6_addr {
uint8_t s6_addr[16]; /**< unsigned 8-bit integer array */
};
/**
* @brief IPv4 socket address type.
* @extends struct sockaddr
*/
struct sockaddr_in {
sa_family_t sin_family; /**< Protocol family, always AF_INET */
in_port_t sin_port; /**< Port number */
struct in_addr sin_addr; /**< IPv4 address */
};
/**
* IPv6 socket address type.
* @extends struct sockaddr
*/
struct sockaddr_in6 {
/**
* Protocol family, always AF_INET6. Member of struct sockaddr_in6
*/
int sin6_family; /**< Protocol family, always AF_INET6 */
in_port_t sin6_port; /**< Port number */
uint32_t sin6_flowinfo; /**< IPv6 traffic class and flow information */
struct in6_addr sin6_addr; /**< IPv6 address */
uint32_t sin6_scope_id; /**< Set of interfaces for a scope */
};
/**
* @brief IPv6 multicast request.
*/
struct ipv6_mreq {
struct in6_addr ipv6mr_multiaddr; /**< an IPv6 multicast address */
unsigned ipv6mr_interface; /**< interface index, leave 0 for default */
};
/**
* IPv6 socket address for the wildcard address.
*/
extern const struct sockaddr_in6 in6addr_any;
/**
* IPv6 socket address for the loopback address.
*/
extern const struct sockaddr_in6 in6addr_loopback;
#ifdef __cplusplus
}

View File

@ -0,0 +1,96 @@
/*
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @addtogroup posix_sockets
*/
/**
* @{
*
* @file
* @brief System-internal byte operations.
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef BYTES_H_
#define BYTES_H_
#include "byteorder.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Convert values between host and network byte order.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/htonl.html">
* The Open Group Base Specification Issue 7, htonl
* </a>
*
* @param[in] hostlong A 32 bit number.
* @return The argument value converted from host to network byte
* order.
*/
#ifndef htonl
#define htonl(hostlong) HTONL(hostlong)
#endif
/**
* @brief Convert values between host and network byte order.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/htons.html">
* The Open Group Base Specification Issue 7, htons
* </a>
*
* @param[in] hostshort A 16 bit number.
* @return The argument value converted from host to network byte
* order.
*/
#ifndef htons
#define htons(hostshort) HTONS(hostshort)
#endif
/**
* @brief Convert values between host and network byte order.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/ntohl.html">
* The Open Group Base Specification Issue 7, ntohl
* </a>
*
* @param[in] netlong A 32-bit integer number.
* @return The argument value converted from network to host byte
* order.
*/
#ifndef ntohl
#define ntohl(netlong) NTOHL(netlong)
#endif
/**
* @brief Convert values between host and network byte order.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/ntohs.html">
* The Open Group Base Specification Issue 7, ntohs
* </a>
*
* @param[in] netshort A 16-bit integer number.
* @return The argument value converted from network to host byte
* order.
*/
#ifndef ntohs
#define ntohs(netshort) NTOHS(netshort)
#endif
typedef size_t socklen_t; /**< socket address length */
#ifdef __cplusplus
}
#endif
#endif /* BYTES_H_ */
/** @} */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 Freie Universität Berlin
* Copyright (C) 2013-15 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -7,7 +7,7 @@
*/
/**
* @addtogroup pnet
* @addtogroup posix_sockets
* @{
*/
@ -18,6 +18,12 @@
* The Open Group Base Specifications Issue 7, <sys/socket.h>
* </a>
*
* @todo Omitted from original specification for now:
* * struct msghdr, struct cmesghdr, and struct linger and all related defines
* * getsockopt()/setsockopt() and all related defines.
* * shutdown() and all related defines.
* * sockatmark()
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef _SYS_SOCKET_H
@ -32,135 +38,81 @@
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))
#endif
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h>
#include "cpu.h"
#include "kernel_types.h"
#include "net/af.h"
#include "socket_base/socket.h"
#include "sys/bytes.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Maximum data length for a socket address.
*
* It is assumed that struct sockaddr_in6 is currently the longest socket address struct.
* As such it's data length is taken consisting of the IPv6 address (16 byte), the port (2 byte),
* the flow information (4 byte) and the scope ID (4 byte)
*/
#define SOCKADDR_MAX_DATA_LEN (26)
/**
* @name Socket types
* @{
*/
#define SOCK_DGRAM (1) /**< Datagram socket */
#define SOCK_RAW (2) /**< Raw socket */
#define SOCK_SEQPACKET (3) /**< Sequenced-packet socket */
#define SOCK_STREAM (4) /**< Stream socket */
/** @} */
#define SOL_SOCKET (-1) /**< Options to be accessed at socket level, not protocol level */
/**
* @name Option names
* @brief Option names for getsockopt() and setsockopt()
* @{
*/
#define SO_ACCEPTCONN (0) /**< Socket is accepting connections. */
#define SO_BROADCAST (1) /**< Transmission of broadcast messages is supported. */
#define SO_DEBUG (2) /**< Debugging information is being recorded. */
#define SO_DONTROUTE (3) /**< Bypass normal routing. */
#define SO_ERROR (4) /**< Socket error status. */
#define SO_KEEPALIVE (5) /**< Connections are kept alive with periodic messages. */
#define SO_LINGER (6) /**< Socket lingers on close. */
#define SO_OOBINLINE (7) /**< Out-of-band data is transmitted in line. */
#define SO_RCVBUF (8) /**< Receive buffer size. */
#define SO_RCVLOWAT (9) /**< Receive "low water mark". */
#define SO_RCVTIMEO (10) /**< Receive timeout. */
#define SO_REUSEADDR (11) /**< Reuse of local addresses is supported. */
#define SO_SNDBUF (12) /**< Send buffer size. */
#define SO_SNDLOWAT (13) /**< Send "low water mark". */
#define SO_SNDTIMEO (14) /**< Send timeout. */
#define SO_TYPE (15) /**< Socket type. */
/** @} */
typedef unsigned int sa_family_t; /**< address family type */
/**
* @brief Used to define the socket address.
*/
struct __attribute__((packed)) sockaddr {
sa_family_t sa_family; ///< Address family
char sa_data[14]; ///< Socket address (variable length data)
struct sockaddr {
sa_family_t sa_family; /**< Address family */
char sa_data[SOCKADDR_MAX_DATA_LEN]; /**< Socket address (variable length data) */
};
/**
* @brief Implementation based socket address table.
* @extends struct sockaddr
*/
struct __attribute__((packed)) sockaddr_storage {
sa_family_t ss_family; ///< Address family
char ss_data[14]; ///< address data
struct sockaddr_storage {
sa_family_t ss_family; /**< Address family */
uint8_t ss_data[SOCKADDR_MAX_DATA_LEN]; /**< Socket address */
};
/*
* Omitted from original specification for now are struct msghdr,
* struct cmesghdr, and struct linger and all related defines
*/
/**
* @brief *level* value for getsockopt() or setsockopt().
*/
#define SOL_SOCKET 1 ///< Options to be accessed at socket level, not
///< protocol level.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_ACCEPTCONN 1 ///< Socket is accepting connections.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_BROADCAST 2 ///< Transmission of broadcast messages is supported.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_DEBUG 3 ///< Debugging information is being recorded.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_DONTROUTE 4 ///< Bypass normal routing.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_ERROR 5 ///< Socket error status.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_KEEPALIVE 6 ///< Connections are kept alive with periodic messages.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_OOBINLINE 7 ///< Out-of-band data is transmitted in line.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_RCVBUF 8 ///< Receive buffer size.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_RCVLOWAT 9 ///< Receive "low water mark".
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_RCVTIMEO 10 ///< Receive timeout.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_REUSEADDR 11 ///< Reuse of local addresses is supported.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_SNDBUF 12 ///< Send buffer size.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_SNDLOWAT 13 ///< Send "low water mark".
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_SNDTIMEO 14 ///< Send timeout.
/**
* @brief *option_name* value for getsockopt() or setsockopt()
*/
#define SO_TYPE 15 ///< Socket type.
#define SOMAXCONN 16 ///< Maximum *backlog* size for listen()
/**
* @brief *how* value for shutdown()
*/
#define SHUT_WR 1 ///< Disables further send operations.
/**
* @brief *how* value for shutdown()
*/
#define SHUT_RD 2 ///< Disables further receive operations.
/**
* @brief *how* value for shutdown()
*/
#define SHUT_RDWR 3 ///< Disables further send and receive operations.
/**
* @brief Accept a new connection on a socket
@ -260,27 +212,56 @@ int bind(int socket, const struct sockaddr *address,
int connect(int socket, const struct sockaddr *address, socklen_t address_len);
/**
* @brief Get the socket options.
* @brief Get the name of the peer socket.
* @details The getpeername() function shall retrieve the peer address of the specified socket,
* store this address in the sockaddr structure pointed to by the @p address argument,
* and store the length of this address in the object pointed to by the @p address_len
* argument.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html">
* The Open Group Base Specification Issue 7, getsockopt
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html">
* The Open Group Base Specification Issue 7, getpeername
* </a>
*
* @param[in] socket Specifies the file descriptor associated with the socket.
* @param[in] level Protocol level this option applies to. Valid values
* are defined in <sys/socket.h>, prefixed with
* ``SOL_``.
* @param[in] option_name Defines the option to get. Valid values are defined
* in <sys/socket.h>, prefixed with ``SO_``.
* @param[out] option_value Buffer to write the current value of the socket
* option into.
* @param[out] option_len Length of the option value in byte.
*
* @return Upon successful completion, getsockopt() shall return 0; otherwise,
* @param[in] socket Specifies the file descriptor associated with the
* socket.
* @param[out] address Points to a sockaddr structure containing the peer
* address. The length and format of the address depend
* on the address family of the socket.
* @param[in,out] address_len Specifies the length of the sockaddr structure on input and the
* length of the stored address on output. If the address is greater
* than the length of the supplied sockaddr structure, the stored
* address shal be truncated.
* @return Upon successful completion, getpeername() shall return 0; otherwise,
* -1 shall be returned and errno set to indicate the error.
*/
int getsockopt(int socket, int level, int option_name,
void *__restrict option_value, socklen_t *__restrict option_len);
int getpeername(int socket, struct sockaddr *__restrict address,
socklen_t *__restrict address_len);
/**
* @brief Get the socket name.
* @details The getsockname() function shall retrieve the locally-bound name of the specified
* socket, store this address in the sockaddr structure pointed to by the @p address
* argument, and store the length of this address in the object pointed to by the
* @p address_len argument.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html">
* The Open Group Base Specification Issue 7, getsockname
* </a>
*
* @param[in] socket Specifies the file descriptor associated with the
* socket.
* @param[out] address Points to a sockaddr structure containing the peer
* address. The length and format of the address depend
* on the address family of the socket.
* @param[in,out] address_len Specifies the length of the sockaddr structure on input and the
* length of the stored address on output. If the address is greater
* than the length of the supplied sockaddr structure, the stored
* address shal be truncated.
* @return Upon successful completion, getsockname() shall return 0; otherwise,
* -1 shall be returned and errno set to indicate the error.
*/
int getsockname(int socket, struct sockaddr *__restrict address,
socklen_t *__restrict address_len);
/**
* @brief Listen for socket connections and limit the queue of incoming
@ -396,9 +377,9 @@ ssize_t send(int socket, const void *buffer, size_t length, int flags);
* @details Shall send a message through a connection-mode or
* connectionless-mode socket. If the socket is a connectionless-mode
* socket, the message shall be sent to the address specified by
* *dest_addr* if no pre-specified peer address has been set. If a
* @p address if no pre-specified peer address has been set. If a
* peer address has been pre-specified, either the message shall be
* sent to the address specified by *dest_addr* (overriding the
* sent to the address specified by @p address (overriding the
* pre-specified peer address), or the function shall return -1 and
* set errno to EISCONN.
*
@ -406,45 +387,23 @@ ssize_t send(int socket, const void *buffer, size_t length, int flags);
* The Open Group Base Specification Issue 7, sendto
* </a>
*
* @param[in] socket Specifies the socket file descriptor.
* @param[in] message Points to the buffer containing the message to send.
* @param[in] length Specifies the length of the message in bytes.
* @param[in] flags Specifies the type of message reception. Support
* for values other than 0 is not implemented yet.
* @param[in] dest_addr Points to a sockaddr structure containing the
* destination address. The length and format of the
* address depend on the address family of the socket.
* @param[in] dest_len Specifies the length of the sockaddr structure pointed
* to by the *dest_addr* argument.
* @param[in] socket Specifies the socket file descriptor.
* @param[in] buffer Points to the buffer containing the message to send.
* @param[in] length Specifies the length of the message in bytes.
* @param[in] flags Specifies the type of message reception. Support
* for values other than 0 is not implemented yet.
* @param[in] address Points to a sockaddr structure containing the
* destination address. The length and format of the
* address depend on the address family of the socket.
* @param[in] address_len Specifies the length of the sockaddr structure pointed
* to by the @p address argument.
*
* @return Upon successful completion, send() shall return the number of bytes
* sent. Otherwise, -1 shall be returned and errno set to indicate the
* error.
*/
ssize_t sendto(int socket, const void *message, size_t length, int flags,
const struct sockaddr *dest_addr, socklen_t dest_len);
/**
* @brief Set the socket options.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html">
* The Open Group Base Specification Issue 7, setsockopt
* </a>
*
* @param[in] socket Specifies the file descriptor associated with the socket.
* @param[in] level Protocol level this option applies to. Valid values
* are defined in <sys/socket.h>, prefixed with
* ``SOL_``.
* @param[in] option_name Defines the option to set. Valid values are defined
* in <sys/socket.h>, prefixed with ``SO_``.
* @param[in] option_value Value for the option to set.
* @param[in] option_len Length of the option value in byte.
*
* @return Upon successful completion, setsockopt() shall return 0; otherwise,
* -1 shall be returned and errno set to indicate the error.
*/
int setsockopt(int socket, int level, int option_name, const void *option_value,
socklen_t option_len);
ssize_t sendto(int socket, const void *buffer, size_t length, int flags,
const struct sockaddr *address, socklen_t address_len);
/**
* @brief Create an endpoint for communication.
@ -469,6 +428,34 @@ int setsockopt(int socket, int level, int option_name, const void *option_value,
*/
int socket(int domain, int type, int protocol);
/**
* @todo implement out these functions
* @{
*/
static inline int getsockopt(int socket, int level, int option_name, void *option_value,
socklen_t *option_len)
{
(void)socket;
(void)level;
(void)option_name;
(void)option_value;
(void)option_len;
return -1;
}
static inline int setsockopt(int socket, int level, int option_name, const void *option_value,
socklen_t option_len)
{
(void)socket;
(void)level;
(void)option_name;
(void)option_value;
(void)option_len;
return -1;
}
/** @} */
#ifdef __cplusplus
}
#endif

View File

@ -1,25 +0,0 @@
/*
* Copyright (C) 2013 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
* @file
* @brief Providing values for in6addr_any and in6addr_loopback.
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#include <netinet/in.h>
const struct sockaddr_in6 in6addr_any = {{AF_INET6, 0, 0, IN6ADDR_ANY_INIT}, 0};
const struct sockaddr_in6 in6addr_loopback = {{
AF_INET6, 0, 0, IN6ADDR_LOOPBACK_INIT
}, 0
};
/**
* @}
*/

View File

@ -1,154 +0,0 @@
/*
* Copyright (C) 2013 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
* @file
* @brief Providing implementation for POSIX socket wrapper.
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @todo
*/
#include "sys/socket.h"
int flagless_send(int fd, const void *buf, size_t len)
{
(void)fd;
(void)buf;
(void)len;
return -1;
}
int flagless_recv(int fd, void *buf, size_t len)
{
return (int)socket_base_recv(fd, buf, (uint32_t)len, 0);
}
int socket(int domain, int type, int protocol)
{
(void)domain;
(void)type;
(void)protocol;
return -1;
}
int accept(int socket, struct sockaddr *restrict address,
socklen_t *restrict address_len)
{
(void)socket;
(void)address;
(void)address_len;
return -1;
}
int bind(int socket, const struct sockaddr *address, socklen_t address_len)
{
(void)socket;
(void)address;
(void)address_len;
return -1;
}
int connect(int socket, const struct sockaddr *address, socklen_t address_len)
{
(void)socket;
(void)address;
(void)address_len;
return -1;
}
int getsockopt(int socket, int level, int option_name,
void *restrict option_value, socklen_t *restrict option_len)
{
// TODO
(void) socket;
(void) level;
(void) option_name;
(void) option_value;
(void) option_len;
return -1;
}
int listen(int socket, int backlog)
{
(void)socket;
(void)backlog;
return -1;
}
ssize_t recv(int socket, void *buffer, size_t length, int flags)
{
(void)socket;
(void)buffer;
(void)length;
(void)flags;
return -1;
}
ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
struct sockaddr *restrict address,
socklen_t *restrict address_len)
{
(void)socket;
(void)buffer;
(void)length;
(void)flags;
(void)address;
(void)address_len;
return -1;
}
ssize_t send(int socket, const void *buffer, size_t length, int flags)
{
(void)socket;
(void)buffer;
(void)length;
(void)flags;
return -1;
}
ssize_t sendto(int socket, const void *message, size_t length, int flags,
const struct sockaddr *dest_addr, socklen_t dest_len)
{
// TODO
(void)socket;
(void)message;
(void)length;
(void)flags;
(void)dest_addr;
(void)dest_len;
return -1;
}
int setsockopt(int socket, int level, int option_name, const void *option_value,
socklen_t option_len)
{
// TODO
(void) socket;
(void) level;
(void) option_name;
(void) option_value;
(void) option_len;
return -1;
}
/**
* @}
*/

View File

@ -1 +1,3 @@
MODULE = posix_sockets
include $(RIOTBASE)/Makefile.base

View File

@ -7,8 +7,8 @@
*/
/**
* @defgroup pnet Network related POSIX wrapper of RIOT
* @brief Network related POSIX header files
* @defgroup posix_sockets POSIX sockets
* @brief POSIX socket wrapper of RIOT's @ref net_conn
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/">
* The Open Group Specifications Issue 7
* </a>

View File

@ -0,0 +1,890 @@
/*
* Copyright (C) 2015 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
* @file
* @brief Providing implementation for POSIX socket wrapper.
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @todo
*/
#include <arpa/inet.h>
#include <errno.h>
#include <stdbool.h>
#include <string.h>
#include "fd.h"
#include "mutex.h"
#include "net/conn.h"
#include "net/ipv4/addr.h"
#include "net/ipv6/addr.h"
#include "random.h"
#include "sys/socket.h"
#include "netinet/in.h"
#define SOCKET_POOL_SIZE (4)
/**
* @brief Unitfied connection type.
*/
typedef union {
/* is not supposed to be used */
/* cppcheck-suppress unusedStructMember */
int undef; /**< for case that no connection module is present */
#ifdef MODULE_CONN_IP
conn_ip_t raw; /**< raw IP connection */
#endif /* MODULE_CONN_IP */
#ifdef MODULE_CONN_TCP
conn_tcp_t tcp; /**< TCP connection */
#endif /* MODULE_CONN_TCP */
#ifdef MODULE_CONN_UDP
conn_udp_t udp; /**< UDP connection */
#endif /* MODULE_CONN_UDP */
} socket_conn_t;
typedef struct {
int fd;
sa_family_t domain;
int type;
int protocol;
bool bound;
socket_conn_t conn;
} socket_t;
socket_t _pool[SOCKET_POOL_SIZE];
mutex_t _pool_mutex = MUTEX_INIT;
const struct sockaddr_in6 in6addr_any = {AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0};
const struct sockaddr_in6 in6addr_loopback = {
AF_INET6, 0, 0, IN6ADDR_LOOPBACK_INIT, 0
};
static socket_t *_get_free_socket(void)
{
for (int i = 0; i < SOCKET_POOL_SIZE; i++) {
if (_pool[i].domain == AF_UNSPEC) {
return &_pool[i];
}
}
return NULL;
}
static socket_t *_get_socket(int fd)
{
for (int i = 0; i < SOCKET_POOL_SIZE; i++) {
if (_pool[i].fd == fd) {
return &_pool[i];
}
}
return NULL;
}
static inline int _choose_ipproto(int type, int protocol)
{
switch (type) {
#ifdef MODULE_CONN_TCP
case SOCK_STREAM:
if ((protocol == 0) || (protocol == IPPROTO_TCP)) {
return protocol;
}
else {
errno = EPROTOTYPE;
}
break;
#endif
#ifdef MODULE_CONN_UDP
case SOCK_DGRAM:
if ((protocol == 0) || (protocol == IPPROTO_UDP)) {
return protocol;
}
else {
errno = EPROTOTYPE;
}
break;
#endif
#ifdef MODULE_CONN_IP
case SOCK_RAW:
return protocol;
#endif
default:
(void)protocol;
break;
}
errno = EPROTONOSUPPORT;
return -1;
}
static inline void _htons_port(uint16_t *port)
{
*port = htons(*port);
}
static inline ipv4_addr_t *_in_addr_ptr(struct sockaddr_storage *addr)
{
return (ipv4_addr_t *)(&((struct sockaddr_in *)addr)->sin_addr);
}
static inline uint16_t *_in_port_ptr(struct sockaddr_storage *addr)
{
return &((struct sockaddr_in *)addr)->sin_port;
}
static inline ipv6_addr_t *_in6_addr_ptr(struct sockaddr_storage *addr)
{
return (ipv6_addr_t *)(&((struct sockaddr_in6 *)addr)->sin6_addr);
}
static inline uint16_t *_in6_port_ptr(struct sockaddr_storage *addr)
{
return &((struct sockaddr_in6 *)addr)->sin6_port;
}
static inline socklen_t _addr_truncate(struct sockaddr *out, socklen_t out_len,
struct sockaddr_storage *in, socklen_t target_size)
{
out_len = (out_len < target_size) ? out_len : target_size;
memcpy(out, in, out_len);
return out_len;
}
static inline int _get_data_from_sockaddr(const struct sockaddr *address, size_t address_len,
void **addr, size_t *addr_len, uint16_t *port)
{
switch (address->sa_family) {
case AF_INET:
if (address_len < sizeof(struct sockaddr_in)) {
errno = EINVAL;
return -1;
}
struct sockaddr_in *in_addr = (struct sockaddr_in *)address;
*addr = &in_addr->sin_addr;
*addr_len = sizeof(ipv4_addr_t);
/* XXX sin_port is in network byteorder */
*port = ntohs(in_addr->sin_port);
break;
case AF_INET6:
if (address_len < sizeof(struct sockaddr_in6)) {
errno = EINVAL;
return -1;
}
struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)address;
*addr = &in6_addr->sin6_addr;
*addr_len = sizeof(ipv6_addr_t);
/* XXX sin6_port is in network byteorder */
*port = ntohs(in6_addr->sin6_port);
break;
default:
errno = EAFNOSUPPORT;
return -1;
}
return 0;
}
static int socket_close(int socket)
{
socket_t *s;
int res = 0;
if ((unsigned)(socket - 1) > (SOCKET_POOL_SIZE - 1)) {
return -1;
}
mutex_lock(&_pool_mutex);
s = &_pool[socket];
if (s->bound) {
switch (s->domain) {
case AF_INET:
case AF_INET6:
switch (s->type) {
#ifdef MODULE_CONN_UDP
case SOCK_DGRAM:
conn_udp_close(&s->conn.udp);
break;
#endif
#ifdef MODULE_CONN_IP
case SOCK_RAW:
conn_ip_close(&s->conn.raw);
break;
#endif
#ifdef MODULE_CONN_TCP
case SOCK_STREAM:
conn_tcp_close(&s->conn.tcp);
break;
#endif
default:
errno = EOPNOTSUPP;
res = -1;
break;
}
default:
res = -1;
break;
}
}
s->domain = AF_UNSPEC;
mutex_unlock(&_pool_mutex);
return res;
}
static ssize_t socket_read(int socket, void *buf, size_t n)
{
return recv(socket, buf, n, 0);
}
static ssize_t socket_write(int socket, const void *buf, size_t n)
{
return send(socket, buf, n, 0);
}
int socket(int domain, int type, int protocol)
{
int res = 0;
socket_t *s;
mutex_lock(&_pool_mutex);
s = _get_free_socket();
if (s == NULL) {
errno = ENFILE;
mutex_unlock(&_pool_mutex);
return -1;
}
switch (domain) {
case AF_INET:
case AF_INET6:
s->domain = domain;
s->type = type;
if ((s->protocol = _choose_ipproto(type, protocol)) < 0) {
res = -1;
}
break;
default:
(void)type;
(void)protocol;
errno = EAFNOSUPPORT;
res = -1;
}
if (res == 0) {
/* TODO: add read and write */
int fd = fd_new(s - _pool, socket_read, socket_write, socket_close);
if (fd < 0) {
errno = ENFILE;
res = -1;
}
else {
s->fd = res = fd;
}
}
s->bound = false;
mutex_unlock(&_pool_mutex);
return res;
}
int accept(int socket, struct sockaddr *restrict address,
socklen_t *restrict address_len)
{
socket_t *s, *new_s = NULL;
int res = 0;
/* May be kept unassigned if no conn module is available */
/* cppcheck-suppress unassignedVariable */
struct sockaddr_storage tmp;
void *addr;
uint16_t *port;
socklen_t tmp_len;
mutex_lock(&_pool_mutex);
s = _get_socket(socket);
if (s == NULL) {
mutex_unlock(&_pool_mutex);
errno = ENOTSOCK;
return -1;
}
if (!s->bound) {
mutex_unlock(&_pool_mutex);
errno = EINVAL;
return -1;
}
switch (s->domain) {
case AF_INET:
addr = _in_addr_ptr(&tmp);
port = _in_port_ptr(&tmp);
tmp_len = sizeof(struct sockaddr_in);
break;
case AF_INET6:
addr = _in6_addr_ptr(&tmp);
port = _in6_port_ptr(&tmp);
tmp_len = sizeof(struct sockaddr_in6);
break;
default:
(void)address;
(void)address_len;
(void)new_s;
(void)tmp;
(void)addr;
(void)port;
(void)tmp_len;
errno = EPROTO;
res = -1;
break;
}
switch (s->type) {
#ifdef MODULE_CONN_TCP
case SOCK_STREAM:
new_s = _get_free_socket();
if (new_s == NULL) {
errno = ENFILE;
res = -1;
break;
}
if ((res = conn_tcp_accept(&s->conn.tcp, &new_s->conn.tcp)) < 0) {
errno = -res;
res = -1;
break;
}
else if ((address != NULL) && (address_len != NULL)) {
/* TODO: add read and write */
int fd = fd_new(new_s - _pool, NULL, NULL, socket_close);
if (fd < 0) {
errno = ENFILE;
res = -1;
break;
}
else {
new_s->fd = res = fd;
}
new_s->domain = s->domain;
new_s->type = s->type;
new_s->protocol = s->protocol;
tmp.ss_family = s->domain;
if ((res = conn_tcp_getpeeraddr(&s->conn.tcp, addr, port)) < 0) {
errno = -res;
res = -1;
break;
}
_htons_port(port); /* XXX: sin(6)_port is supposed to be network byte
* order */
*address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
}
break;
#endif
default:
errno = EOPNOTSUPP;
res = -1;
break;
}
mutex_unlock(&_pool_mutex);
return res;
}
int bind(int socket, const struct sockaddr *address, socklen_t address_len)
{
socket_t *s;
int res = 0;
void *addr;
size_t addr_len;
uint16_t port;
mutex_lock(&_pool_mutex);
s = _get_socket(socket);
mutex_unlock(&_pool_mutex);
if (s == NULL) {
errno = ENOTSOCK;
return -1;
}
if (address->sa_family != s->domain) {
errno = EAFNOSUPPORT;
return -1;
}
if (_get_data_from_sockaddr(address, address_len, &addr, &addr_len, &port) < 0) {
return -1;
}
switch (s->type) {
#ifdef MODULE_CONN_IP
case SOCK_RAW:
(void)port;
if ((res = conn_ip_create(&s->conn.raw, addr, addr_len, s->domain, s->protocol)) < 0) {
errno = -res;
return -1;
}
break;
#endif
#ifdef MODULE_CONN_TCP
case SOCK_STREAM:
if ((res = conn_tcp_create(&s->conn.tcp, addr, addr_len, s->domain, port)) < 0) {
errno = -res;
return -1;
}
break;
#endif
#ifdef MODULE_CONN_UDP
case SOCK_DGRAM:
if ((res = conn_udp_create(&s->conn.udp, addr, addr_len, s->domain, port)) < 0) {
errno = -res;
return -1;
}
break;
#endif
default:
(void)addr;
(void)addr_len;
(void)port;
(void)res;
errno = EOPNOTSUPP;
return -1;
}
s->bound = true;
return 0;
}
int connect(int socket, const struct sockaddr *address, socklen_t address_len)
{
socket_t *s;
int res = 0;
void *addr;
size_t addr_len;
uint16_t port;
mutex_lock(&_pool_mutex);
s = _get_socket(socket);
mutex_unlock(&_pool_mutex);
if (s == NULL) {
errno = ENOTSOCK;
return -1;
}
if (!s->bound) {
errno = EINVAL;
return -1;
}
if (address->sa_family != s->domain) {
errno = EAFNOSUPPORT;
return -1;
}
if (_get_data_from_sockaddr(address, address_len, &addr, &addr_len, &port) < 0) {
return -1;
}
switch (s->type) {
#ifdef MODULE_CONN_TCP
case SOCK_STREAM:
/* XXX sin_port is in network byteorder */
if ((res = conn_tcp_connect(&s->conn.tcp, addr, addr_len, port)) < 0) {
errno = -res;
return -1;
}
break;
#endif
default:
(void)res;
errno = EPROTOTYPE;
return -1;
}
return 0;
}
int getpeername(int socket, struct sockaddr *__restrict address,
socklen_t *__restrict address_len)
{
socket_t *s;
int res = 0;
/* May be kept unassigned if no conn module is available */
/* cppcheck-suppress unassignedVariable */
struct sockaddr_storage tmp;
void *addr;
uint16_t *port;
socklen_t tmp_len;
mutex_lock(&_pool_mutex);
s = _get_socket(socket);
mutex_unlock(&_pool_mutex);
if (s == NULL) {
errno = ENOTSOCK;
return -1;
}
switch (s->domain) {
case AF_INET:
addr = _in_addr_ptr(&tmp);
port = _in_port_ptr(&tmp);
tmp_len = sizeof(struct sockaddr_in);
break;
case AF_INET6:
addr = _in6_addr_ptr(&tmp);
port = _in6_port_ptr(&tmp);
tmp_len = sizeof(struct sockaddr_in6);
break;
default:
(void)address;
(void)address_len;
(void)tmp;
(void)addr;
(void)port;
(void)tmp_len;
(void)res;
errno = EBADF;
return -1;
}
if (*address_len != tmp_len) {
errno = EINVAL;
return -1;
}
switch (s->type) {
#ifdef MODULE_CONN_TCP
case SOCK_STREAM:
if ((res = conn_tcp_getpeeraddr(&s->conn.tcp, addr, port)) < 0) {
errno = -res;
return -1;
}
break;
#endif
default:
errno = ENOTCONN;
return -1;
}
tmp.ss_family = s->domain;
_htons_port(port); /* XXX: sin(6)_port is supposed to be network byte
* order */
*address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
return 0;
}
int getsockname(int socket, struct sockaddr *__restrict address,
socklen_t *__restrict address_len)
{
socket_t *s;
int res = 0;
/* May be kept unassigned if no conn module is available */
/* cppcheck-suppress unassignedVariable */
struct sockaddr_storage tmp;
void *addr;
uint16_t *port;
socklen_t tmp_len;
mutex_lock(&_pool_mutex);
s = _get_socket(socket);
mutex_unlock(&_pool_mutex);
if (s == NULL) {
errno = ENOTSOCK;
return -1;
}
if (!s->bound) {
memset(address, 0, *address_len);
return 0;
}
switch (s->domain) {
case AF_INET:
addr = _in_addr_ptr(&tmp);
port = _in_port_ptr(&tmp);
tmp_len = sizeof(struct sockaddr_in);
break;
case AF_INET6:
addr = _in6_addr_ptr(&tmp);
port = _in6_port_ptr(&tmp);
tmp_len = sizeof(struct sockaddr_in6);
break;
default:
(void)address;
(void)address_len;
(void)tmp;
(void)addr;
(void)port;
(void)tmp_len;
(void)res;
errno = EBADF;
return -1;
}
if (*address_len != tmp_len) {
errno = EINVAL;
return -1;
}
switch (s->type) {
#ifdef MODULE_CONN_UDP
case SOCK_DGRAM:
if ((res = conn_udp_getlocaladdr(&s->conn.udp, addr, port)) < 0) {
errno = -res;
return -1;
}
break;
#endif
#ifdef MODULE_CONN_IP
case SOCK_RAW:
if ((res = conn_ip_getlocaladdr(&s->conn.raw, addr)) < 0) {
errno = -res;
return -1;
}
break;
#endif
#ifdef MODULE_CONN_TCP
case SOCK_STREAM:
if ((res = conn_tcp_getlocaladdr(&s->conn.tcp, addr, port)) < 0) {
errno = -res;
return -1;
}
break;
#endif
default:
errno = EOPNOTSUPP;
return -1;
}
tmp.ss_family = AF_INET;
_htons_port(port); /* XXX: sin(6)_port is supposed to be network byte
* order */
*address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
return 0;
}
int listen(int socket, int backlog)
{
socket_t *s;
int res = 0;
mutex_lock(&_pool_mutex);
s = _get_socket(socket);
mutex_unlock(&_pool_mutex);
if (!s->bound) {
errno = EINVAL;
return -1;
}
switch (s->domain) {
case AF_INET:
case AF_INET6:
switch (s->type) {
#ifdef MODULE_CONN_TCP
case SOCK_STREAM:
if ((res = conn_tcp_listen(&s->conn.tcp, backlog)) < 0) {
errno = -res;
return -1;
}
break;
#endif
default:
errno = EOPNOTSUPP;
return -1;
}
break;
default:
(void)backlog;
(void)res;
errno = EAFNOSUPPORT;
return -1;
}
return 0;
}
ssize_t recv(int socket, void *buffer, size_t length, int flags)
{
return recvfrom(socket, buffer, length, flags, NULL, NULL);
}
ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
struct sockaddr *restrict address,
socklen_t *restrict address_len)
{
socket_t *s;
int res = 0;
/* May be kept unassigned if no conn module is available */
/* cppcheck-suppress unassignedVariable */
struct sockaddr_storage tmp;
void *addr;
size_t addr_len;
uint16_t *port;
socklen_t tmp_len;
(void)flags;
mutex_lock(&_pool_mutex);
s = _get_socket(socket);
mutex_unlock(&_pool_mutex);
if (s == NULL) {
errno = ENOTSOCK;
return -1;
}
if (!s->bound) {
errno = EINVAL;
return -1;
}
switch (s->domain) {
case AF_INET:
addr = _in_addr_ptr(&tmp);
port = _in_port_ptr(&tmp);
addr_len = sizeof(ipv4_addr_t);
tmp_len = sizeof(struct sockaddr_in);
break;
case AF_INET6:
addr = _in6_addr_ptr(&tmp);
port = _in6_port_ptr(&tmp);
addr_len = sizeof(ipv6_addr_t);
tmp_len = sizeof(struct sockaddr_in6);
break;
default:
(void)buffer;
(void)length;
(void)address;
(void)address_len;
(void)tmp;
(void)addr;
(void)port;
(void)tmp_len;
errno = EAFNOSUPPORT;
return -1;
}
switch (s->type) {
#ifdef MODULE_CONN_UDP
case SOCK_DGRAM:
if ((res = conn_udp_recvfrom(&s->conn.udp, buffer, length, addr, &addr_len,
port)) < 0) {
errno = -res;
return -1;
}
break;
#endif
#ifdef MODULE_CONN_IP
case SOCK_RAW:
if ((res = conn_ip_recvfrom(&s->conn.raw, buffer, length, addr, &addr_len)) < 0) {
errno = -res;
return -1;
}
break;
#endif
#ifdef MODULE_CONN_TCP
case SOCK_STREAM:
if ((res = conn_tcp_recv(&s->conn.tcp, buffer, length)) < 0) {
errno = -res;
return -1;
}
if ((res = conn_tcp_getpeeraddr(&s->conn.tcp, addr, port)) < 0) {
errno = -res;
return -1;
}
break;
#endif
default:
(void)addr_len;
errno = EOPNOTSUPP;
return -1;
}
if ((address != NULL) && (address_len != NULL)) {
tmp.ss_family = s->domain;
_htons_port(port); /* XXX: sin_port is supposed to be network byte
* order */
*address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
}
return res;
}
ssize_t send(int socket, const void *buffer, size_t length, int flags)
{
return sendto(socket, buffer, length, flags, NULL, 0);
}
ssize_t sendto(int socket, const void *buffer, size_t length, int flags,
const struct sockaddr *address, socklen_t address_len)
{
socket_t *s;
int res = 0;
void *addr = NULL;
size_t addr_len = 0;
uint16_t port = 0;
(void)flags;
mutex_lock(&_pool_mutex);
s = _get_socket(socket);
mutex_unlock(&_pool_mutex);
if (s == NULL) {
errno = ENOTSOCK;
return -1;
}
if (address != NULL) {
if (address->sa_family != s->domain) {
errno = EAFNOSUPPORT;
return -1;
}
if (_get_data_from_sockaddr(address, address_len, &addr, &addr_len, &port) < 0) {
return -1;
}
}
switch (s->type) {
#ifdef MODULE_CONN_IP
case SOCK_RAW:
if ((address != NULL) && (s->bound)) {
uint8_t src_addr[sizeof(ipv6_addr_t)];
size_t src_len;
int res = conn_ip_getlocaladdr(&s->conn.raw, src_addr);
if (res < 0) {
errno = ENOTSOCK; /* Something seems to be wrong with the socket */
return -1;
}
src_len = (size_t)res;
/* cppcheck bug? res is read below in l824 */
/* cppcheck-suppress unreadVariable */
res = conn_ip_sendto(buffer, length, src_addr, src_len, addr, addr_len, s->domain,
s->protocol);
}
else if (address != NULL) {
res = conn_ip_sendto(buffer, length, NULL, 0, addr, addr_len, s->domain,
s->protocol);
}
else {
errno = ENOTCONN;
return -1;
}
if (res < 0) {
errno = -res;
return -1;
}
break;
#endif
#ifdef MODULE_CONN_TCP
case SOCK_STREAM:
if (!s->bound) {
errno = ENOTCONN;
return -1;
}
if (address != NULL) {
errno = EISCONN;
return -1;
}
if ((res = conn_tcp_send(&s->conn.tcp, buffer, length)) < 0) {
errno = -res;
return -1;
}
break;
#endif
#ifdef MODULE_CONN_UDP
case SOCK_DGRAM:
if ((address != NULL) && (s->bound)) {
uint8_t src_addr[sizeof(ipv6_addr_t)];
size_t src_len;
uint16_t sport;
int res = conn_udp_getlocaladdr(&s->conn.udp, src_addr, &sport);
if (res < 0) {
errno = ENOTSOCK; /* Something seems to be wrong with the socket */
return -1;
}
src_len = (size_t)res;
/* cppcheck bug? res is read below in l824 */
/* cppcheck-suppress unreadVariable */
res = conn_udp_sendto(buffer, length, src_addr, src_len, addr, addr_len, s->domain,
sport, port);
}
else if (address != NULL) {
uint16_t sport = (uint16_t)genrand_uint32_range(1LU << 10U, 1LU << 16U);
res = conn_udp_sendto(buffer, length, NULL, 0, addr, addr_len, s->domain,
sport, port);
}
else {
errno = ENOTCONN;
return -1;
}
if (res < 0) {
errno = -res;
return -1;
}
break;
#endif
default:
(void)buffer;
(void)length;
errno = EOPNOTSUPP;
return -1;
}
return res;
}
/**
* @}
*/