further implemented socketstream methods

This commit is contained in:
Bob Polis 2020-03-17 17:21:47 +01:00
parent 6d1ebe4af2
commit 107b09c056
2 changed files with 135 additions and 28 deletions

View File

@ -89,7 +89,7 @@ namespace sc {
class socketstream : public fdstream {
public:
socketstream() = default;
socketstream();
socketstream(int domain, int type);
// copying forbidden
@ -104,7 +104,7 @@ namespace sc {
virtual ~socketstream();
// server
void make_server(const socket_address& address) const;
void make_server(const socket_address& sa);
socketstream accept() const;
// client
@ -112,16 +112,17 @@ namespace sc {
// convenience: human-readable addresses
std::string address() const;
std::string peer_address() const;
// address/endpoint conversion methods
struct sockaddr endpoint_from_address(const socket_address& address) const;
socket_address address_from_endpoint(const struct sockaddr& endpoint) const;
void endpoint_from_address(const socket_address& address,
struct sockaddr_storage* endpoint) const;
socket_address address_from_endpoint(const struct sockaddr* endpoint) const;
protected:
int _socket {-1};
int _domain {0};
int _type {0};
struct sockaddr_storage _sa;
};
struct float_80 {

View File

@ -7,26 +7,38 @@
//
#include "libscio.hpp"
#include <libscerror.hpp>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <cstring>
#include <vector>
#include <utility>
using namespace sc::io;
socketstream::socketstream(int domain, int type)
: fdstream(), _domain(domain), _type(type) {
_socket = socket(_domain, _type, 0);
if (_socket == -1) {
throw std::runtime_error("socketstream: could not create socket");
}
throw_if_min1_msg(_socket, "could not create socket");
_inbuf.fd(_socket);
_outbuf.fd(_socket);
std::memset(&_sa, 0, sizeof(struct sockaddr_storage));
}
socketstream::socketstream() : fdstream() {
std::memset(&_sa, 0, sizeof(struct sockaddr_storage));
}
socketstream::socketstream(socketstream&& other) {
_socket = other._socket;
_domain = other._domain;
_type = other._type;
std::memcpy(&_sa, &other._sa, sizeof(struct sockaddr_storage));
other._socket = -1;
std::memset(&other._sa, 0, sizeof(struct sockaddr_storage));
}
socketstream& socketstream::operator=(socketstream&& other) {
@ -34,8 +46,10 @@ socketstream& socketstream::operator=(socketstream&& other) {
_socket = other._socket;
_domain = other._domain;
_type = other._type;
std::memcpy(&_sa, &other._sa, sizeof(struct sockaddr_storage));
other._socket = -1;
std::memset(&other._sa, 0, sizeof(struct sockaddr_storage));
}
return *this;
}
@ -46,41 +60,133 @@ socketstream::~socketstream() {
}
}
void socketstream::make_server(const socket_address& address) const {
// build sockaddr
// bind
// if stream: listen
void socketstream::make_server(const socket_address& sa) {
size_t addr_sz = 0;
switch (_domain) {
case AF_UNIX: {
struct sockaddr_un* sau = reinterpret_cast<struct sockaddr_un*>(&_sa);
sau->sun_family = AF_UNIX;
addr_sz = sa.address.size();
std::strncpy(sau->sun_path, sa.address.c_str(), addr_sz);
break;
}
case AF_INET: {
struct sockaddr_in* sa4 = reinterpret_cast<struct sockaddr_in*>(&_sa);
sa4->sin_family = AF_INET;
sa4->sin_addr.s_addr = INADDR_ANY;
sa4->sin_port = htons(sa.port);
addr_sz = sizeof(struct sockaddr_in);
break;
}
case AF_INET6: {
struct sockaddr_in6* sa6 = reinterpret_cast<struct sockaddr_in6*>(&_sa);
sa6->sin6_family = AF_INET6;
sa6->sin6_addr = in6addr_any;
sa6->sin6_port = htons(sa.port);
addr_sz = sizeof(struct sockaddr_in6);
break;
}
default:
errno = EAFNOSUPPORT;
throw_if_min1_msg(-1, "unsupported socket domain");
}
struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&_sa);
throw_if_min1(::bind(_socket, addr, addr_sz));
if (_type == SOCK_STREAM) {
throw_if_min1(::listen(_socket, SOMAXCONN));
}
}
socketstream socketstream::accept() const {
int passive_socket = ::accept(_socket, nullptr, 0);
if (passive_socket == -1) {
throw std::runtime_error("socketstream: could not accept");
}
socketstream peer;
peer._socket = passive_socket;
socklen_t len = sizeof(struct sockaddr_storage);
int active_socket = ::accept(_socket,
reinterpret_cast<struct sockaddr*>(&peer._sa),
&len);
throw_if_min1(active_socket);
peer._socket = active_socket;
peer._domain = _domain;
peer._type = _type;
return peer;
}
void socketstream::connect(const socket_address& host) {
// build sockaddr
// connect
endpoint_from_address(host, &_sa);
struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&_sa);
throw_if_min1(::connect(_socket, addr, sizeof(_sa)));
}
std::string socketstream::address() const {
return ""; // TODO
const struct sockaddr* addr = reinterpret_cast<const struct sockaddr*>(&_sa);
socket_address sa = address_from_endpoint(addr);
return sa.address;
}
std::string socketstream::peer_address() const {
return ""; // TODO
void socketstream::endpoint_from_address(const socket_address& address,
struct sockaddr_storage* endpoint) const {
throw_if_null(endpoint);
switch (_domain) {
case AF_UNIX: {
struct sockaddr_un* addr = reinterpret_cast<struct sockaddr_un*>(endpoint);
addr->sun_family = AF_UNIX;
std::memcpy(addr->sun_path, address.address.c_str(), address.address.size());
break;
}
case AF_INET: {
struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(endpoint);
addr->sin_family = AF_INET;
addr->sin_port = htons(address.port);
::inet_pton(_domain, address.address.c_str(), &addr->sin_addr);
break;
}
case AF_INET6: {
struct sockaddr_in6* addr = reinterpret_cast<struct sockaddr_in6*>(endpoint);
addr->sin6_family = AF_INET6;
addr->sin6_port = htons(address.port);
addr->sin6_flowinfo = 0;
::inet_pton(_domain, address.address.c_str(), &addr->sin6_addr);
addr->sin6_scope_id = 0;
break;
}
default:
errno = EAFNOSUPPORT;
throw_if_min1_msg(-1, "unsupported socket domain");
}
}
struct sockaddr socketstream::endpoint_from_address(const socket_address& address) const {
socket_address socketstream::address_from_endpoint(const struct sockaddr* endpoint) const {
throw_if_null(endpoint);
socket_address sa;
switch (_domain) {
case AF_UNIX: {
const struct sockaddr_un* addr = reinterpret_cast<const struct sockaddr_un*>(endpoint);
sa.address = addr->sun_path;
sa.port = 0;
break;
}
socket_address socketstream::address_from_endpoint(const struct sockaddr& endpoint) const {
case AF_INET: {
const struct sockaddr_in* addr = reinterpret_cast<const struct sockaddr_in*>(endpoint);
std::vector<char> buf;
buf.resize(INET_ADDRSTRLEN);
::inet_ntop(_domain, &addr->sin_addr, buf.data(), buf.size());
std::string temp {buf.data(), buf.size()};
sa.address = std::move(temp);
sa.port = ntohs(addr->sin_port);
break;
}
case AF_INET6: {
const struct sockaddr_in6* addr = reinterpret_cast<const struct sockaddr_in6*>(endpoint);
std::vector<char> buf;
buf.resize(INET6_ADDRSTRLEN);
::inet_ntop(_domain, &addr->sin6_addr, buf.data(), buf.size());
std::string temp {buf.data(), buf.size()};
sa.address = std::move(temp);
sa.port = ntohs(addr->sin6_port);
break;
}
default:
errno = EAFNOSUPPORT;
throw_if_min1_msg(-1, "unsupported socket domain");
}
return sa;
}