diff --git a/Makefile.dep b/Makefile.dep index b3b66a8b13..4ae604dd6c 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -7,6 +7,25 @@ ifneq (,$(findstring vtimer,$(USEMODULE))) endif endif + +ifneq (,$(findstring pnet, $(USEMODULE))) + ifeq (,$(findstring posix, $(USEMODULE))) + USEMODULE += posix + endif + ifeq (,$(findstring destiny, $(USEMODULE))) + USEMODULE += destiny + endif + ifeq (,$(findstring net_help, $(USEMODULE))) + USEMODULE += net_help + endif +endif + +ifneq (,$(findstring posix, $(USEMODULE))) + ifeq (,$(findstring uart0, $(USEMODULE))) + USEMODULE += uart0 + endif +endif + ifneq (,$(findstring uart0,$(USEMODULE))) ifeq (,$(findstring lib,$(USEMODULE))) USEMODULE += lib diff --git a/sys/Makefile b/sys/Makefile index 58020bfd19..95cbae2d59 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -18,6 +18,9 @@ ifneq (,$(findstring posix,$(USEMODULE))) INCLUDES += -I$(RIOTBASE)/sys/posix/include DIRS += posix endif +ifneq (,$(findstring pnet,$(USEMODULE))) + DIRS += posix/pnet +endif ifneq (,$(findstring shell,$(USEMODULE))) DIRS += shell endif diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 0e8dce72b7..ef752455af 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -55,6 +55,10 @@ #include "rtc.h" #endif +#ifdef MODULE_DESTINY +#include "destiny.h" +#endif + #define ENABLE_DEBUG (0) #include "debug.h" @@ -105,5 +109,10 @@ void auto_init(void) extern void profiling_init(void); profiling_init(); #endif +#ifdef MODULE_DESTINY + DEBUG("Auto init transport layer [destiny] module.\n"); + destiny_init_transport_layer(); +#endif + main(); } diff --git a/sys/include/fd.h b/sys/include/fd.h new file mode 100644 index 0000000000..9b5fa98bec --- /dev/null +++ b/sys/include/fd.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2013 INRIA. + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @addtogroup posix + * @{ + */ + +/** + * @file fd.h + * @brief Unifies diverse identifiers of RIOT to POSIX like file descriptors. + * + * @author Freie Universität Berlin + * @author Martin Lenders + * @author Christian Mehlis + */ +#ifndef FD_H +#define FD_H +#include +#include + +/** + * File descriptor table. + */ +typedef struct { + /** private status of this fd_t */ + int __active; + + /** the internal filedescriptor */ + int fd; + + /** + * Read *n* into *buf* from *fd*. Return the + * number read, -1 for errors or 0 for EOF. + */ + ssize_t (*read)(int fd, void *buf, size_t n); + + /** Write *n* bytes of *buf* to *fd*. Return the number written, or -1. */ + ssize_t (*write)(int fd, const void *buf, size_t n); + + /** Close the file descriptor *fd*. */ + int (*close)(int fd); +} fd_t; + +/** + * @brief Initializes file descriptors + * + * @return maximum number of available file descriptors. + */ +int fd_init(void); + +/** + * @brief Creates a new file descriptor. + * + * @param[in] internal_fd RIOT-internal identifier for the new FD. + * @param[in] internal_read Function to read from new FD. + * @param[in] internal_write Function to write into new FD. + * @param[in] internal_close Function to close new FD. + * + * @return 0 on success, -1 otherwise. *errno* is set accordingly. + */ +int fd_new(int internal_fd, ssize_t (*internal_read)(int, void *, size_t), + ssize_t (*internal_write)(int, const void *, size_t), + int (*internal_close)(int)); + +/** + * @brief Gets the file descriptor table entry associated with file + * descriptor *fd*. + * + * @param[in] fd A POSIX-like file descriptor. + * + * @return The file descriptor table entry associated with file descriptor + *fd* or NULL if there is non. + */ +fd_t *fd_get(int fd); + +/** + * @brief Removes file descriptor table entry associated with *fd* from table. + * + * @param[in] fd A POSIX-like file descriptor. + */ +void fd_destroy(int fd); + +#endif /* FD_H */ diff --git a/sys/posix/fd.c b/sys/posix/fd.c new file mode 100644 index 0000000000..6029826c7d --- /dev/null +++ b/sys/posix/fd.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +#include +#include +#include +#include + +#include "posix_io.h" +#include "board_uart0.h" +#include "unistd.h" + +#include "fd.h" + +#if BOARD == MSB-430 +#define FD_MAX 5 +#else +#define FD_MAX 15 +#endif + +static fd_t fd_table[FD_MAX]; + +int fd_init(void) +{ + memset(fd_table, 0, sizeof(fd_t) * FD_MAX); + + posix_open(uart0_handler_pid, 0); + fd_t fd = { + .__active = 1, + .fd = uart0_handler_pid, + .read = (ssize_t ( *)(int, void *, size_t))posix_read, + .write = (ssize_t ( *)(int, const void *, size_t))posix_write, + .close = posix_close + }; + memcpy(&fd_table[STDIN_FILENO], &fd, sizeof(fd_t)); + memcpy(&fd_table[STDOUT_FILENO], &fd, sizeof(fd_t)); + memcpy(&fd_table[STDERR_FILENO], &fd, sizeof(fd_t)); + return FD_MAX; +} + +static int fd_get_next_free(void) +{ + for (int i = 0; i < FD_MAX; i++) { + fd_t *cur = &fd_table[i]; + + if (!cur->__active) { + return i; + } + } + + return -1; +} + +int fd_new(int internal_fd, ssize_t (*internal_read)(int, void *, size_t), + ssize_t (*internal_write)(int, const void *, size_t), + int (*internal_close)(int)) +{ + int fd = fd_get_next_free(); + + if (fd >= 0) { + fd_t *fd_s = fd_get(fd); + fd_s->__active = 1; + fd_s->fd = internal_fd; + fd_s->read = internal_read; + fd_s->write = internal_write; + fd_s->close = internal_close; + } + else { + errno = ENFILE; + return -1; + } + + return fd; +} + +fd_t *fd_get(int fd) +{ + if (fd >= 0 && fd < FD_MAX) { + return &fd_table[fd]; + } + + return NULL; +} + +void fd_destroy(int fd) +{ + fd_t *cur = fd_get(fd); + + if (!cur) { + return; + } + + memset(cur, 0, sizeof(fd_t)); +} diff --git a/sys/posix/include/unistd.h b/sys/posix/include/unistd.h new file mode 100644 index 0000000000..5ec8ec9cf5 --- /dev/null +++ b/sys/posix/include/unistd.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @addtogroup posix + * @{ + */ + +/** + * @file unistd.h + * @brief standard symbolic constants and types + * @see + * The Open Group Base Specifications Issue 7, + * + * + * @author Freie Universität Berlin + * @author Martin Lenders + */ +#ifndef _UNISTD_H +#define _UNISTD_H + +#define STDIN_FILENO 0 ///< stdin file descriptor +#define STDOUT_FILENO 1 ///< stdout file descriptor +#define STDERR_FILENO 2 ///< stderr file descriptor + +/** + * @brief Close a file descriptor. + * @details shall deallocate the file descriptor indicated by *fildes*. To + * deallocate means to make the file descriptor available for return + * by subsequent calls to open() or other functions that allocate file + * descriptors. All outstanding record locks owned by the process on + * the file associated with the file descriptor shall be removed (that + * is, unlocked). + * + * @see + * The Open Group Base Specification Issue 7, close + * + * + * @param[in] fildes The file descriptor to the file which is to close. + * @return Upon successful completion, 0 shall be returned; otherwise, -1 + * shall be returned and errno set to indicate the error. + */ +int close(int fildes); + +/** + * @} + */ +#endif /* _UNISTD_H */ diff --git a/sys/posix/pnet/Makefile b/sys/posix/pnet/Makefile new file mode 100644 index 0000000000..8549b59171 --- /dev/null +++ b/sys/posix/pnet/Makefile @@ -0,0 +1,5 @@ +MODULE =pnet + +CFLAGS += -isystem $(RIOTBASE)/sys/posix/pnet/include + +include $(RIOTBASE)/Makefile.base diff --git a/sys/posix/pnet/doc.txt b/sys/posix/pnet/doc.txt new file mode 100644 index 0000000000..591b484950 --- /dev/null +++ b/sys/posix/pnet/doc.txt @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2013 INRIA. + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @defgroup pnet Network related POSIX wrapper of RIOT + * @brief Network related POSIX header files + * @see + * The Open Group Specifications Issue 7 + * + * @ingroup posix + */ diff --git a/sys/posix/pnet/include/arpa/inet.h b/sys/posix/pnet/include/arpa/inet.h new file mode 100644 index 0000000000..192cecaccf --- /dev/null +++ b/sys/posix/pnet/include/arpa/inet.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @addtogroup pnet + * @{ + */ + +/** + * @file arpa/inet.h + * @brief Definitions for internet operations + * @see + * The Open Group Base Specifications Issue 7, + * + * + * @author Freie Universität Berlin + * @author Martin Lenders + */ +#ifndef ARPA_INET_H +#define ARPA_INET_H + +#include + +#include "net_help.h" +#include "inet_ntop.h" +#include "inet_pton.h" + +typedef uint16_t in_port_t; ///< Internet port type +typedef uint32_t in_addr_t; ///< IPv4 address type + +#define INET_ADDRSTRLEN 16 ///< Length of the string form for IPv4. +#define INET6_ADDRSTRLEN 46 ///< Length of the string form for IPv6. + +/** + * 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 + * The Open Group Base Specification Issue 7, htonl + * + * + * @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 + * The Open Group Base Specification Issue 7, htons + * + * + * @param[in] hostlong 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 + * The Open Group Base Specification Issue 7, ntohl + * + * + * @param[in] hostlong 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 + * The Open Group Base Specification Issue 7, ntohs + * + * + * @param[in] hostlong A 16-bit integer number. + * @return The argument value converted from network to host byte + * order. + */ +#define ntohs(netshort) NTOHS(netshort) + +/** + * @} + */ +#endif /* ARPA_INET_H */ diff --git a/sys/posix/pnet/include/netinet/in.h b/sys/posix/pnet/include/netinet/in.h new file mode 100644 index 0000000000..d4244a90bf --- /dev/null +++ b/sys/posix/pnet/include/netinet/in.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @addtogroup pnet + * @{ + */ + +/** + * @file netinet/in.h + * @brief Main socket header + * @see + * The Open Group Base Specifications Issue 7, + * + * + * @author Freie Universität Berlin + * @author Martin Lenders + */ +#ifndef _NETINET_IN_H +#define _NETINET_IN_H + +#include +#include +#include +#include "ipv6.h" +#include "destiny/socket.h" + +/** + * 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; + +/** + * IPv4 local host address. + */ +#define INADDR_ANY {(in_addr_t)0x00000000} + +/** + * IPv4 broadcast address. + */ +#define INADDR_BROADCAST {(in_addr_t)0xffffffff} + +/** + * Multicast hop limit option name for getsockopt() or setsockopt() + * + * @see + * The Open Group Base Specification Issue 7, getsockopt + * + * @see + * The Open Group Base Specification Issue 7, setsockopt + * + */ +#define IPV6_MULTICAST_HOPS 0x12 + +/** + * Test for IPv6 multicast address. + * + * @param[in] a An IPv6 address. + * @return 1 if *a* is an multicast address, 0 if not. + */ +#define IN6_IS_ADDR_MULTICAST(a) (((const uint8_t *) (a))[0] == 0xff) + +/** + * @} + */ +#endif /* _NETINET_IN_H */ diff --git a/sys/posix/pnet/include/sys/socket.h b/sys/posix/pnet/include/sys/socket.h new file mode 100644 index 0000000000..0322a71831 --- /dev/null +++ b/sys/posix/pnet/include/sys/socket.h @@ -0,0 +1,469 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @addtogroup pnet + * @{ + */ + +/** + * @file sys/socket.h + * @brief Main socket header + * @see + * The Open Group Base Specifications Issue 7, + * + * + * @author Freie Universität Berlin + * @author Martin Lenders + */ +#ifndef _SYS_SOCKET_H +#define _SYS_SOCKET_H + +#if BOARD == NATIVE +/* Ignore Linux definitions in native */ +#define _BITS_SOCKADDR_H 1 +#define __SOCKADDR_COMMON(sa_prefix) \ + sa_family_t sa_prefix##family + +#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int)) +#endif + +#include + +#include "destiny/socket.h" + +/** + * @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) +}; + +/** + * @brief Implementation based socket address table. + */ +struct __attribute__((packed)) sockaddr_storage { + sa_family_t ss_family; ///< Address family + char ss_data[14]; ///< address data +}; + +/* + * 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 + * @details The accept() function shall extract the first connection on the + * queue of pending connections, create a new socket with the same + * socket type protocol and address family as the specified socket, + * and allocate a new file descriptor for that socket. + * If the listen queue is empty of connection requests and O_NONBLOCK + * is not set on the file descriptor for the socket, accept() shall + * block until a connection is present. If the listen() queue is + * empty of connection requests and O_NONBLOCK is set on the file + * descriptor for the socket, accept() shall fail and set errno + * to [EAGAIN] or [EWOULDBLOCK]. The accepted socket cannot itself + * accept more connections. The original socket remains open and can + * accept more connections. + * + * @see + * The Open Group Base Specification Issue 7, accept + * + * + * @param[in] socket Specifies a socket that was created with socket(), + * has been bound to an address with bind(), + * and has issued a successful call to listen(). + * @param[out] address Either a null pointer, or a pointer to a sockaddr + * structure where the address of the connecting socket + * shall be returned. If *address* is not a null + * pointer, the address of the peer for the accepted + * connection shall be stored in the sockaddr + * structure pointed to by *address*, and the length + * of this address shall be stored in the object + * pointed to by *address_len*. If the actual length + * of the address is greater than the length of the + * supplied sockaddr structure, the stored address + * shall be truncated. If the protocol permits + * connections by unbound clients, and the peer is not + * bound, then the value stored in the object pointed + * to by address is unspecified. + * @param[out] address_len Either a null pointer, if *address* is a null + * pointer, or a pointer to a socklen_t object which + * on input specifies the length of the supplied + * sockaddr structure, and on output specifies the + * length of the stored address. + * @return Upon successful completion, accept() shall return the non-negative + * file descriptor of the accepted socket. Otherwise, -1 shall be + * returned and errno set to indicate the error. + */ +int accept(int socket, struct sockaddr *restrict address, + socklen_t *restrict address_len); + +/** + * @brief Bind a name to a socket. + * @detail The bind() function shall assign a local socket address *address* + * to a socket identified by descriptor socket that has no local + * socket address assigned. Sockets created with the socket() function + * are initially unnamed; they are identified only by their address + * family. + * + * @see + * The Open Group Base Specification Issue 7, bind + * + * + * @param socket Specifies the file descriptor of the socket to be bound. + * @param address Points to a sockaddr structure containing the address + * to be bound to the socket. The length and format of the + * address depend on the address family of the socket. + * If the address family of the socket is AF_UNIX and the + * pathname in address names a symbolic link, bind() shall + * fail and set errno to [EADDRINUSE]. + * @param address_len Specifies the length of the sockaddr structure pointed + * to by the *address* argument. + * @return Upon successful completion, bind() shall return 0; otherwise, -1 + * shall be returned and errno set to indicate the error. + */ +int bind(int socket, const struct sockaddr *address, + socklen_t address_len); + +/** + * @brief Connect a socket. + * @detail The connect() function shall attempt to make a connection on a + * connection-mode socket or to set or reset the peer address of a + * connectionless-mode socket. + * + * @see + * The Open Group Base Specification Issue 7, connect + * + * + * @param[in] socket Specifies the file descriptor associated with the + * socket. + * @param[in] 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] address_len Specifies the length of the sockaddr structure + * pointed to by the address argument. + * @return Upon successful completion, connect() shall return 0; otherwise, + * -1 shall be returned and errno set to indicate the error. + */ +int connect(int socket, const struct sockaddr *address, socklen_t address_len); + +/** + * @brief Get the socket options. + * + * @see + * The Open Group Base Specification Issue 7, getsockopt + * + * + * @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 , prefixed with + * ``SOL_``. + * @param[in] option_name Defines the option to get. Valid values are defined + * in , 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, + * -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); + +/** + * @brief Listen for socket connections and limit the queue of incoming + * connections. + * + * @see + * The Open Group Base Specification Issue 7, listen + * + * + * @param[in] socket Specifies the file descriptor associated with the socket. + * @param[in] backlog Provides a hint to the implementation which the + * implementation shall use to limit the number of + * outstanding connections in the socket's listen queue. + * Implementations may impose a limit on backlog and + * silently reduce the specified value. Normally, a + * larger backlog argument value shall result in a larger + * or equal length of the listen queue. Implementations + * shall support values of backlog up to SOMAXCONN, + * defined in . + * @return Upon successful completions, listen() shall return 0; otherwise, + * -1 shall be returned and errno set to indicate the error. + */ +int listen(int socket, int backlog); + +/** + * @brief Receive a message from a connected socket. + * @detail Shall receive a message from a connection-mode or + * connectionless-mode socket. It is normally used with connected + * sockets because it does not permit the application to retrieve the + * source address of received data. + * + * @see + * The Open Group Base Specification Issue 7, recv + * + * + * @param[in] socket Specifies the socket file descriptor. + * @param[out] buffer Points to a buffer where the message should be stored. + * @param[in] length Specifies the length in bytes of the buffer pointed to + * by the buffer argument. + * @param[in] flags Specifies the type of message reception. Support for + * values other than 0 is not implemented yet. + * + * @return Upon successful completion, recv() shall return the length of the + * message in bytes. If no messages are available to be received and + * the peer has performed an orderly shutdown, recv() shall return 0. + * Otherwise, -1 shall be returned and errno set to indicate the error. + */ +ssize_t recv(int socket, void *buffer, size_t length, int flags); + +/** + * @brief Receive a message from a socket. + * @detail The recvfrom() function shall receive a message from a + * connection-mode or connectionless-mode socket. It is normally used + * with connectionless-mode sockets because it permits the application + * to retrieve the source address of received data. + * + * @see + * The Open Group Base Specification Issue 7, recvfrom + * + * + * @param[in] socket Specifies the socket file descriptor. + * @param[out] buffer Points to a buffer where the message should be i + * stored. + * @param[in] length Specifies the length in bytes of the buffer pointed + * to by the buffer argument. + * @param[in] flags Specifies the type of message reception. Support + * for values other than 0 is not implemented yet. + * @param[out] address A null pointer, or points to a sockaddr structure + * in which the sending address is to be stored. The + * length and format of the address depend on the + * address family of the socket. + * @param[out] address_len Either a null pointer, if address is a null pointer, + * or a pointer to a socklen_t object which on input + * specifies the length of the supplied sockaddr + * structure, and on output specifies the length of + * the stored address. + * + * @return Upon successful completion, recvfrom() shall return the length of + * the message in bytes. If no messages are available to be received + * and the peer has performed an orderly shutdown, recvfrom() shall + * return 0. Otherwise, the function shall return -1 and set errno to + * indicate the error. + */ +ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, + struct sockaddr *restrict address, + socklen_t *restrict address_len); + +/** + * @brief Send a message on a socket. + * @detail Shall initiate transmission of a message from the specified socket + * to its peer. The send() function shall send a message only when the + * socket is connected. If the socket is a connectionless-mode socket, + * the message shall be sent to the pre-specified peer address. + * + * @see + * The Open Group Base Specification Issue 7, send + * + * + * @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. + * + * @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 send(int socket, const void *buffer, size_t length, int flags); + +/** + * @brief Send a message on a socket. + * @detail 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 + * peer address has been pre-specified, either the message shall be + * sent to the address specified by *dest_addr* (overriding the + * pre-specified peer address), or the function shall return -1 and + * set errno to EISCONN. + * + * @see + * The Open Group Base Specification Issue 7, sendto + * + * + * @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] 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. + * + * @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 + * The Open Group Base Specification Issue 7, setsockopt + * + * + * @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 , prefixed with + * ``SOL_``. + * @param[in] option_name Defines the option to set. Valid values are defined + * in , 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); + +/** + * @brief Create an endpoint for communication. + * @detail Shall create an unbound socket in a communications domain, and + * return a file descriptor that can be used in later function calls + * that operate on sockets. + * + * @param[in] domain Specifies the communications domain in which a socket + * is to be created. Valid values are prefixed with ``AF_` + * and defined in @ref destiny/socket.h. + * @param[in] type Specifies the type of socket to be created. Valued + * values are prefixed with ``SOCK_`` and defined in + * @ref destiny/socket.h. + * @param[in] protocol Specifies a particular protocol to be used with the + * socket. Specifying a protocol of 0 causes socket() to + * use an unspecified default protocol appropriate for + * the requested socket type. + * + * @return Upon successful completion, socket() shall return a non-negative + * integer, the socket file descriptor. Otherwise, a value of -1 shall + * be returned and errno set to indicate the error. + */ +int socket(int domain, int type, int protocol); + +/** + * @} + */ +#endif /* SYS_SOCKET_H */ diff --git a/sys/posix/pnet/netinet_in.c b/sys/posix/pnet/netinet_in.c new file mode 100644 index 0000000000..27e3340de7 --- /dev/null +++ b/sys/posix/pnet/netinet_in.c @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ +#include + +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 +}; diff --git a/sys/posix/pnet/sys_socket.c b/sys/posix/pnet/sys_socket.c new file mode 100644 index 0000000000..4d539c63f0 --- /dev/null +++ b/sys/posix/pnet/sys_socket.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +#include + +#include "destiny/socket.h" +#include "fd.h" + +#include "sys/socket.h" + +int flagless_send(int fd, const void *buf, size_t len) +{ + return (int)destiny_socket_send(fd, buf, (uint32_t)len, 0); +} + +int flagless_recv(int fd, void *buf, size_t len) +{ + return (int)destiny_socket_recv(fd, buf, (uint32_t)len, 0); +} + +int socket(int domain, int type, int protocol) +{ + int internal_socket = destiny_socket(domain, type, protocol); + + if (internal_socket < 0) { + errno = ENFILE; + return -1; + } + + return fd_new(internal_socket, flagless_recv, flagless_send, + destiny_socket_close); +} + + +#define sock_func_wrapper(func, sockfd, ...) \ + ((fd_get(sockfd)) ? \ + func(fd_get(sockfd)->fd, __VA_ARGS__) : \ + (errno = EBADF, -1)) + +int accept(int socket, struct sockaddr *restrict address, + socklen_t *restrict address_len) +{ + int res = sock_func_wrapper(destiny_socket_accept, socket, + (sockaddr6_t *)address, + (socklen_t *)address_len); + + if (res < 0) { + // destiny needs more granular error handling + errno = EOPNOTSUPP; + return -1; + } + + return res; +} + +int bind(int socket, const struct sockaddr *address, socklen_t address_len) +{ + int res = sock_func_wrapper(destiny_socket_bind, socket, + (sockaddr6_t *)address, address_len); + + if (res < 0) { + // destiny needs more granular error handling + errno = EOPNOTSUPP; + return -1; + } + + return res; +} + +int connect(int socket, const struct sockaddr *address, socklen_t address_len) +{ + int res = sock_func_wrapper(destiny_socket_connect, socket, + (sockaddr6_t *)address, address_len); + + if (res < 0) { + // destiny needs more granular error handling + errno = ECONNREFUSED; + return -1; + } + + return res; +} + +int getsockopt(int socket, int level, int option_name, + void *restrict option_value, socklen_t *restrict option_len) +{ + // TODO + return -1; +} + +int listen(int socket, int backlog) +{ + int res = sock_func_wrapper(destiny_socket_listen, socket, backlog); + + if (res < 0) { + // destiny needs more granular error handling + errno = ECONNREFUSED; + return -1; + } + + return res; +} + +ssize_t recv(int socket, void *buffer, size_t length, int flags) +{ + int32_t res = sock_func_wrapper(destiny_socket_recv, socket, buffer, + (uint32_t) length, flags); + + if (res < 0) { + // destiny needs more granular error handling + errno = ENOTCONN; + return -1; + } + + return (ssize_t)res; +} + +ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, + struct sockaddr *restrict address, + socklen_t *restrict address_len) +{ + int32_t res = sock_func_wrapper(destiny_socket_recvfrom, socket, buffer, + (uint32_t) length, flags, + (sockaddr6_t *)address, + (socklen_t *)address_len); + + if (res < 0) { + // destiny needs more granular error handling + errno = ENOTCONN; + return -1; + } + + return (ssize_t)res; +} + +ssize_t send(int socket, const void *buffer, size_t length, int flags) +{ + int32_t res = sock_func_wrapper(destiny_socket_send, socket, buffer, + (uint32_t) length, flags); + + if (res < 0) { + // destiny needs more granular error handling + errno = ENOTCONN; + return -1; + } + + return (ssize_t)res; +} + +ssize_t sendto(int socket, const void *message, size_t length, int flags, + const struct sockaddr *dest_addr, socklen_t dest_len) +{ + int32_t res = sock_func_wrapper(destiny_socket_sendto, socket, message, + (uint32_t) length, flags, + (sockaddr6_t *)dest_addr, + (socklen_t)dest_len); + + if (res < 0) { + // destiny needs more granular error handling + errno = ENOTCONN; + return -1; + } + + return (ssize_t)res; +} + +int setsockopt(int socket, int level, int option_name, const void *option_value, + socklen_t option_len) +{ + // TODO + return -1; +} diff --git a/sys/posix/unistd.c b/sys/posix/unistd.c new file mode 100644 index 0000000000..0030a0d446 --- /dev/null +++ b/sys/posix/unistd.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ +#include + +#include "fd.h" +#include "unistd.h" + +int close(int fildes) +{ + fd_t *fd_obj = fd_get(fildes); + + if (!fd_obj) { + errno = EBADF; + return -1; + } + + if (fd_obj->close(fd_obj->fd) < 0) { + errno = EIO; // EINTR may not occur since RIOT has no signals yet. + return -1; + } + + fd_destroy(fd_obj->fd); + + return 0; +} diff --git a/tests/test_pnet/Makefile b/tests/test_pnet/Makefile new file mode 100644 index 0000000000..01f53df6f9 --- /dev/null +++ b/tests/test_pnet/Makefile @@ -0,0 +1,52 @@ +#### +#### Sample Makefile for building apps with the RIOT OS +#### +#### The Sample Filesystem Layout is: +#### /this makefile +#### ../../RIOT +#### ../../boards for board definitions (if you have one or more) +#### + +# name of your project +export PROJECT =test_pnet + +# for easy switching of boards +ifeq ($(strip $(BOARD)),) + export BOARD = native +endif + +# this has to be the absolute path of the RIOT-base dir +export RIOTBASE =$(CURDIR)/../.. +export RIOTBOARD =$(RIOTBASE)/boards + +ifeq ($(BOARD),stm32f4discovery) + include Makefile.$(BOARD) +endif + +## Modules to include. + +USEMODULE += auto_init +USEMODULE += posix +USEMODULE += pnet +USEMODULE += vtimer +ifeq ($(strip $(BOARD)),native) + USEMODULE += nativenet +else ifeq ($(strip $(BOARD)),msba2) + USEMODULE += cc110x_ng +endif + +ifeq ($(BOARD),native) + CFLAGS += -isystem $(RIOTBASE)/sys/net/include \ + -isystem $(RIOTBASE)/sys/posix/pnet/include +else + export INCLUDES += -I$(RIOTBASE)/sys/net/include \ + -I$(RIOTBASE)/sys/posix/pnet/include \ + -I$(RIOTBASE)/sys/posix/include +endif + +ifeq ($(BOARD),msba2) + export INCLUDES += -I$(RIOTBASE)/drivers/cc110x_ng/include \ + -I$(RIOTBASE)/boards/msba2-common/include +endif + +include $(RIOTBASE)/Makefile.include diff --git a/tests/test_pnet/main.c b/tests/test_pnet/main.c new file mode 100644 index 0000000000..1fc46bd287 --- /dev/null +++ b/tests/test_pnet/main.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "transceiver.h" +#include "ipv6.h" + +#ifdef MODULE_NATIVENET +#define TRANSCEIVER TRANSCEIVER_NATIVE +#else +#define TRANSCEIVER TRANSCEIVER_CC1100 +#endif + +#ifndef R_ADDR +#define R_ADDR (1) +#endif + +#define PORT (1234) + +void init_local_address(uint16_t r_addr) { + ipv6_addr_t std_addr; + ipv6_addr_init(&std_addr, 0xabcd, 0xef12, 0, 0, 0x1034, 0x00ff, 0xfe00, + r_addr); + sixlowpan_lowpan_adhoc_init(TRANSCEIVER, &std_addr, r_addr); +} + +int main(void) { + int sockfd, res; + struct sockaddr_in6 my_addr, their_addr = { + .sin6_family = AF_INET6, +#if R_ADDR == 1 + .sin6_port = PORT, +#else + .sin6_port = 0, +#endif + .sin6_flowinfo = 0, +#if R_ADDR == 1 + .sin6_addr = {{{0xab, 0xcd, 0xef, 0x12, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x34, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x02}}}, +#else + .sin6_addr = {{{0xab, 0xcd, 0xef, 0x12, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x34, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01}}}, +#endif + .sin6_scope_id = 0, + }; + char buffer[14]; + + init_local_address(R_ADDR); + + memcpy(buffer, "Hello, World!", 14); + memcpy(&my_addr, &in6addr_any, sizeof (my_addr)); + + my_addr.sin6_port = PORT; + + sockfd = socket(AF_INET6, SOCK_DGRAM, 0); + res = bind(sockfd, (struct sockaddr *)&my_addr, sizeof (my_addr)); + if (res < 0) { + perror("Socket could not be bind"); + return 1; + } + +#if R_ADDR == 1 + res = sendto(sockfd, buffer, strlen(buffer), 0, + (struct sockaddr *)&their_addr, + (socklen_t) sizeof (their_addr)); +#else + socklen_t their_len; + res = recvfrom(sockfd, buffer, strlen(buffer), 0, + (struct sockaddr *)&their_addr, + &their_len); + if (their_addr.sin6_addr.uint8[15] != 1) { + fprintf(stderr, "Wrong sender address: %d\n", their_addr.sin6_addr.uint8[11]); + return 1; + } + printf("Port: %d\n", their_addr.sin6_port); +#endif + if (res < 0) { + perror("Message error"); + return 1; + } + + close(sockfd); + printf("All tests successful.\n"); + return 0; +}