diff --git a/Makefile.dep b/Makefile.dep index 9037185244a42030926fee4ed64a7b99495b7313..0abfc56c5807008b2bb71edefbf0ce0a13151e40 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -367,8 +367,8 @@ endif ifneq (,$(filter posix_sockets,$(USEMODULE))) USEMODULE += bitfield - USEMODULE += posix USEMODULE += random + USEMODULE += vfs endif ifneq (,$(filter rtt_stdio,$(USEMODULE))) diff --git a/sys/posix/sockets/posix_sockets.c b/sys/posix/sockets/posix_sockets.c index 2295522ba9e37c364ed9abd0ed5bd9b443b2d829..c4df6db5309aa25fed8e5416f504d409a6734f02 100644 --- a/sys/posix/sockets/posix_sockets.c +++ b/sys/posix/sockets/posix_sockets.c @@ -23,11 +23,11 @@ #include <string.h> #include "bitfield.h" -#include "fd.h" #include "mutex.h" #include "net/ipv4/addr.h" #include "net/ipv6/addr.h" #include "random.h" +#include "vfs.h" #include "sys/socket.h" #include "netinet/in.h" @@ -39,6 +39,7 @@ /* enough to create sockets both with socket() and accept() */ #define _ACTUAL_SOCKET_POOL_SIZE (SOCKET_POOL_SIZE + \ (SOCKET_POOL_SIZE * SOCKET_TCP_QUEUE_SIZE)) +#define SOCKET_BLKSIZE (512) /** * @brief Unitfied connection type. @@ -90,6 +91,14 @@ static mutex_t _socket_pool_mutex = MUTEX_INIT; const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; +static ssize_t socket_recvfrom(socket_t *s, void *restrict buffer, + size_t length, int flags, + struct sockaddr *restrict address, + socklen_t *restrict address_len); +static ssize_t socket_sendto(socket_t *s, const void *buffer, size_t length, + int flags, const struct sockaddr *address, + socklen_t address_len); + static socket_t *_get_free_socket(void) { for (int i = 0; i < _ACTUAL_SOCKET_POOL_SIZE; i++) { @@ -232,13 +241,11 @@ static int _sockaddr_to_ep(const struct sockaddr *address, socklen_t address_len return 0; } -static int socket_close(int socket) +static int socket_close(vfs_file_t *filp) { - socket_t *s; + socket_t *s = filp->private_data.ptr; int res = 0; - assert(((unsigned)socket) < _ACTUAL_SOCKET_POOL_SIZE); - s = &_socket_pool[socket]; assert((s->domain == AF_INET) || (s->domain == AF_INET6)); mutex_lock(&_socket_pool_mutex); if (s->sock != NULL) { @@ -279,16 +286,42 @@ static int socket_close(int socket) return res; } -static ssize_t socket_read(int socket, void *buf, size_t n) +static inline int socket_fstat(vfs_file_t *filp, struct stat *buf) +{ + (void)filp; + memset(buf, 0, sizeof(struct stat)); + buf->st_mode |= (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO); + buf->st_blksize = SOCKET_BLKSIZE; + return 0; +} + +static inline off_t socket_lseek(vfs_file_t *filp, off_t off, int whence) { - return recv(socket, buf, n, 0); + (void)filp; + (void)off; + (void)whence; + return -ESPIPE; /* see http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html */ } -static ssize_t socket_write(int socket, const void *buf, size_t n) +static inline ssize_t socket_read(vfs_file_t *filp, void *buf, size_t n) { - return send(socket, buf, n, 0); + return socket_recvfrom(filp->private_data.ptr, buf, n, 0, NULL, NULL); } +static inline ssize_t socket_write(vfs_file_t *filp, const void *buf, size_t n) +{ + return socket_sendto(filp->private_data.ptr, buf, n, 0, NULL, 0); +} + +static const vfs_file_ops_t socket_ops = { + .close = socket_close, + .fcntl = NULL, /* TODO: provide when needed */ + .fstat = socket_fstat, + .lseek = socket_lseek, + .read = socket_read, + .write = socket_write, +}; + int socket(int domain, int type, int protocol) { int res = 0; @@ -307,8 +340,7 @@ int socket(int domain, int type, int protocol) case AF_INET6: #endif { - int fd = fd_new(s - _socket_pool, socket_read, socket_write, - socket_close); + int fd = vfs_bind(VFS_ANY_FD, 0, &socket_ops, s); if (fd < 0) { errno = ENFILE; @@ -593,8 +625,7 @@ static int _getpeername(socket_t *s, struct sockaddr *__restrict address, int res = 0; if (s->sock == NULL) { - errno = ENOTCONN; - return -1; + return -ENOTCONN; } switch (s->type) { #ifdef MODULE_SOCK_IP @@ -621,11 +652,7 @@ static int _getpeername(socket_t *s, struct sockaddr *__restrict address, res = -EOPNOTSUPP; break; } - if (res < 0) { - errno = -res; - res = -1; - } - else { + if (res >= 0) { struct sockaddr_storage sa; socklen_t sa_len = _ep_to_sockaddr(&ep, &sa); *address_len = _addr_truncate(address, *address_len, &sa, @@ -638,6 +665,7 @@ int getpeername(int socket, struct sockaddr *__restrict address, socklen_t *__restrict address_len) { socket_t *s; + int res; mutex_lock(&_socket_pool_mutex); s = _get_socket(socket); @@ -646,7 +674,11 @@ int getpeername(int socket, struct sockaddr *__restrict address, errno = ENOTSOCK; return -1; } - return _getpeername(s, address, address_len); + if ((res = _getpeername(s, address, address_len)) < 0) { + errno = -res; + return -1; + } + return res; } int getsockname(int socket, struct sockaddr *__restrict address, @@ -773,27 +805,22 @@ int listen(int socket, int backlog) #endif } -ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, - struct sockaddr *restrict address, - socklen_t *restrict address_len) +static ssize_t socket_recvfrom(socket_t *s, void *restrict buffer, + size_t length, int flags, + struct sockaddr *restrict address, + socklen_t *restrict address_len) { - socket_t *s; int res = 0; struct _sock_tl_ep ep = { .port = 0 }; (void)flags; - mutex_lock(&_socket_pool_mutex); - s = _get_socket(socket); - mutex_unlock(&_socket_pool_mutex); if (s == NULL) { - errno = ENOTSOCK; - return -1; + return -ENOTSOCK; } if (s->sock == NULL) { /* socket is not connected */ #ifdef MODULE_SOCK_TCP if (s->type == SOCK_STREAM) { - errno = ENOTCONN; - return -1; + return -ENOTCONN; } #endif /* bind implicitly */ @@ -811,34 +838,24 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, switch (s->type) { #ifdef MODULE_SOCK_IP case SOCK_RAW: - if ((res = sock_ip_recv(&s->sock->raw, buffer, length, recv_timeout - (sock_ip_ep_t *)&ep)) < 0) { - errno = -res; - res = -1; - } + res = sock_ip_recv(&s->sock->raw, buffer, length, recv_timeout, + (sock_ip_ep_t *)&ep); break; #endif #ifdef MODULE_SOCK_TCP case SOCK_STREAM: - if ((res = sock_tcp_read(&s->sock->tcp.sock, buffer, length, - recv_timeout)) < 0) { - errno = -res; - res = -1; - } + res = sock_tcp_read(&s->sock->tcp.sock, buffer, length, + recv_timeout); break; #endif #ifdef MODULE_SOCK_UDP case SOCK_DGRAM: - if ((res = sock_udp_recv(&s->sock->udp, buffer, length, recv_timeout, - &ep)) < 0) { - errno = -res; - res = -1; - } + res = sock_udp_recv(&s->sock->udp, buffer, length, recv_timeout, + &ep); break; #endif default: - errno = EOPNOTSUPP; - res = -1; + res = -EOPNOTSUPP; break; } if ((res >= 0) && (address != NULL) && (address_len != 0)) { @@ -862,19 +879,34 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, return res; } -ssize_t sendto(int socket, const void *buffer, size_t length, int flags, - const struct sockaddr *address, socklen_t address_len) +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; + + mutex_lock(&_socket_pool_mutex); + s = _get_socket(socket); + mutex_unlock(&_socket_pool_mutex); + res = socket_recvfrom(s, buffer, length, flags, address, address_len); + if (res < 0) { + errno = -res; + return -1; + } + return res; +} + +static ssize_t socket_sendto(socket_t *s, const void *buffer, size_t length, + int flags, const struct sockaddr *address, + socklen_t address_len) +{ int res = 0; #if defined(MODULE_SOCK_IP) || defined(MODULE_SOCK_UDP) struct _sock_tl_ep ep = { .port = 0 }; #endif (void)flags; - mutex_lock(&_socket_pool_mutex); - s = _get_socket(socket); - mutex_unlock(&_socket_pool_mutex); if (s == NULL) { errno = ENOTSOCK; return -1; @@ -936,6 +968,23 @@ ssize_t sendto(int socket, const void *buffer, size_t length, int flags, return res; } +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; + + mutex_lock(&_socket_pool_mutex); + s = _get_socket(socket); + mutex_unlock(&_socket_pool_mutex); + res = socket_sendto(s, buffer, length, flags, address, address_len); + if (res < 0) { + errno = -res; + return -1; + } + return res; +} + /* * This is a partial implementation of setsockopt for changing the receive * timeout value of a socket.