2013-09-30 15:55:14 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013 Freie Universität Berlin
|
|
|
|
*
|
2014-07-31 19:45:27 +02:00
|
|
|
* 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.
|
2013-09-30 15:55:14 +02:00
|
|
|
*/
|
|
|
|
|
2014-01-31 15:00:21 +01:00
|
|
|
/**
|
|
|
|
* @{
|
|
|
|
* @file sys_socket.c
|
|
|
|
* @brief Providing implementation for POSIX socket wrapper.
|
2015-02-08 18:51:25 +01:00
|
|
|
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
2014-01-31 15:00:21 +01:00
|
|
|
*/
|
2013-09-30 15:55:14 +02:00
|
|
|
#include <errno.h>
|
|
|
|
|
2014-07-31 17:53:46 +02:00
|
|
|
#include "socket_base/socket.h"
|
2013-09-30 15:55:14 +02:00
|
|
|
#include "fd.h"
|
|
|
|
|
|
|
|
#include "sys/socket.h"
|
|
|
|
|
|
|
|
int flagless_send(int fd, const void *buf, size_t len)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
return (int)socket_base_send(fd, buf, (uint32_t)len, 0);
|
2013-09-30 15:55:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int flagless_recv(int fd, void *buf, size_t len)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
return (int)socket_base_recv(fd, buf, (uint32_t)len, 0);
|
2013-09-30 15:55:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int socket(int domain, int type, int protocol)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
int internal_socket = socket_base_socket(domain, type, protocol);
|
2013-09-30 15:55:14 +02:00
|
|
|
|
|
|
|
if (internal_socket < 0) {
|
|
|
|
errno = ENFILE;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fd_new(internal_socket, flagless_recv, flagless_send,
|
2014-07-31 17:53:46 +02:00
|
|
|
socket_base_close);
|
2013-09-30 15:55:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#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)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
int res = sock_func_wrapper(socket_base_accept, socket,
|
2013-09-30 15:55:14 +02:00
|
|
|
(sockaddr6_t *)address,
|
|
|
|
(socklen_t *)address_len);
|
|
|
|
|
|
|
|
if (res < 0) {
|
2014-07-31 17:53:46 +02:00
|
|
|
// transport_layer needs more granular error handling
|
2013-09-30 15:55:14 +02:00
|
|
|
errno = EOPNOTSUPP;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-06-02 18:53:51 +02:00
|
|
|
return fd_new(res, flagless_recv, flagless_send,
|
2014-07-31 17:53:46 +02:00
|
|
|
socket_base_close);
|
2013-09-30 15:55:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int bind(int socket, const struct sockaddr *address, socklen_t address_len)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
int res = sock_func_wrapper(socket_base_bind, socket,
|
2013-09-30 15:55:14 +02:00
|
|
|
(sockaddr6_t *)address, address_len);
|
|
|
|
|
|
|
|
if (res < 0) {
|
2014-07-31 17:53:46 +02:00
|
|
|
// transport_layer needs more granular error handling
|
2013-09-30 15:55:14 +02:00
|
|
|
errno = EOPNOTSUPP;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
int connect(int socket, const struct sockaddr *address, socklen_t address_len)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
int res = sock_func_wrapper(socket_base_connect, socket,
|
2013-09-30 15:55:14 +02:00
|
|
|
(sockaddr6_t *)address, address_len);
|
|
|
|
|
|
|
|
if (res < 0) {
|
2014-07-31 17:53:46 +02:00
|
|
|
// transport_layer needs more granular error handling
|
2013-09-30 15:55:14 +02:00
|
|
|
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
|
2014-06-11 13:33:49 +02:00
|
|
|
(void) socket;
|
|
|
|
(void) level;
|
|
|
|
(void) option_name;
|
|
|
|
(void) option_value;
|
|
|
|
(void) option_len;
|
|
|
|
|
2013-09-30 15:55:14 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int listen(int socket, int backlog)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
int res = sock_func_wrapper(socket_base_listen, socket, backlog);
|
2013-09-30 15:55:14 +02:00
|
|
|
|
|
|
|
if (res < 0) {
|
2014-07-31 17:53:46 +02:00
|
|
|
// transport_layer needs more granular error handling
|
2013-09-30 15:55:14 +02:00
|
|
|
errno = ECONNREFUSED;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t recv(int socket, void *buffer, size_t length, int flags)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
int32_t res = sock_func_wrapper(socket_base_recv, socket, buffer,
|
2013-09-30 15:55:14 +02:00
|
|
|
(uint32_t) length, flags);
|
|
|
|
|
|
|
|
if (res < 0) {
|
2014-07-31 17:53:46 +02:00
|
|
|
// transport_layer needs more granular error handling
|
2013-09-30 15:55:14 +02:00
|
|
|
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)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
int32_t res = sock_func_wrapper(socket_base_recvfrom, socket, buffer,
|
2013-09-30 15:55:14 +02:00
|
|
|
(uint32_t) length, flags,
|
|
|
|
(sockaddr6_t *)address,
|
|
|
|
(socklen_t *)address_len);
|
|
|
|
|
|
|
|
if (res < 0) {
|
2014-07-31 17:53:46 +02:00
|
|
|
// transport_layer needs more granular error handling
|
2013-09-30 15:55:14 +02:00
|
|
|
errno = ENOTCONN;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ssize_t)res;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t send(int socket, const void *buffer, size_t length, int flags)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
int32_t res = sock_func_wrapper(socket_base_send, socket, buffer,
|
2013-09-30 15:55:14 +02:00
|
|
|
(uint32_t) length, flags);
|
|
|
|
|
|
|
|
if (res < 0) {
|
2014-07-31 17:53:46 +02:00
|
|
|
// transport_layer needs more granular error handling
|
2013-09-30 15:55:14 +02:00
|
|
|
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)
|
|
|
|
{
|
2014-07-31 17:53:46 +02:00
|
|
|
int32_t res = sock_func_wrapper(socket_base_sendto, socket, message,
|
2013-09-30 15:55:14 +02:00
|
|
|
(uint32_t) length, flags,
|
|
|
|
(sockaddr6_t *)dest_addr,
|
|
|
|
(socklen_t)dest_len);
|
|
|
|
|
|
|
|
if (res < 0) {
|
2014-07-31 17:53:46 +02:00
|
|
|
// transport_layer needs more granular error handling
|
2013-09-30 15:55:14 +02:00
|
|
|
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
|
2014-06-11 13:33:49 +02:00
|
|
|
(void) socket;
|
|
|
|
(void) level;
|
|
|
|
(void) option_name;
|
|
|
|
(void) option_value;
|
|
|
|
(void) option_len;
|
|
|
|
|
2013-09-30 15:55:14 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2014-01-31 15:00:21 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|