Merge pull request #226 from authmillenon/posix_sockets

Posix sockets
This commit is contained in:
Oleg Hahm 2014-01-17 07:00:14 -08:00
commit afdc3dee23
16 changed files with 1384 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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();
}

89
sys/include/fd.h Normal file
View File

@ -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 <mlenders@inf.fu-berlin.de>
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
*/
#ifndef FD_H
#define FD_H
#include <stdlib.h>
#include <sys/types.h>
/**
* 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 */

99
sys/posix/fd.c Normal file
View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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));
}

View File

@ -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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html">
* The Open Group Base Specifications Issue 7, <unistd.h>
* </a>
*
* @author Freie Universität Berlin
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
*/
#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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html">
* The Open Group Base Specification Issue 7, close
* </a>
*
* @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 */

5
sys/posix/pnet/Makefile Normal file
View File

@ -0,0 +1,5 @@
MODULE =pnet
CFLAGS += -isystem $(RIOTBASE)/sys/posix/pnet/include
include $(RIOTBASE)/Makefile.base

16
sys/posix/pnet/doc.txt Normal file
View File

@ -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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/">
* The Open Group Specifications Issue 7
* </a>
* @ingroup posix
*/

View File

@ -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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/arpa_inet.h.html">
* The Open Group Base Specifications Issue 7, <arpa/inet.h>
* </a>
*
* @author Freie Universität Berlin
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef ARPA_INET_H
#define ARPA_INET_H
#include <inttypes.h>
#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 <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] 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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/ntohl.html">
* The Open Group Base Specification Issue 7, ntohl
* </a>
*
* @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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/ntohs.html">
* The Open Group Base Specification Issue 7, ntohs
* </a>
*
* @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 */

View File

@ -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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html">
* The Open Group Base Specifications Issue 7, <netinet/in.h>
* </a>
*
* @author Freie Universität Berlin
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef _NETINET_IN_H
#define _NETINET_IN_H
#include <inttypes.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#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 <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>
*/
#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 */

View File

@ -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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html">
* The Open Group Base Specifications Issue 7, <sys/socket.h>
* </a>
*
* @author Freie Universität Berlin
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
*/
#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 <sys/types.h>
#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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html">
* The Open Group Base Specification Issue 7, accept
* </a>
*
* @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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html">
* The Open Group Base Specification Issue 7, bind
* </a>
*
* @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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html">
* The Open Group Base Specification Issue 7, connect
* </a>
*
* @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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html">
* The Open Group Base Specification Issue 7, getsockopt
* </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,
* -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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">
* The Open Group Base Specification Issue 7, listen
* </a>
*
* @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 <sys/socket.h>.
* @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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html">
* The Open Group Base Specification Issue 7, recv
* </a>
*
* @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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html">
* The Open Group Base Specification Issue 7, recvfrom
* </a>
*
* @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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html">
* The Open Group Base Specification Issue 7, send
* </a>
*
* @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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html">
* The Open Group Base Specification Issue 7, sendto
* </a>
*
* @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 <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);
/**
* @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 */

View File

@ -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 <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
};

177
sys/posix/pnet/sys_socket.c Normal file
View File

@ -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 <errno.h>
#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;
}

30
sys/posix/unistd.c Normal file
View File

@ -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 <errno.h>
#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;
}

52
tests/test_pnet/Makefile Normal file
View File

@ -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

90
tests/test_pnet/main.c Normal file
View File

@ -0,0 +1,90 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#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;
}