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

View File

@ -7,26 +7,38 @@
// //
#include "libscio.hpp" #include "libscio.hpp"
#include <libscerror.hpp>
#include <unistd.h> #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; using namespace sc::io;
socketstream::socketstream(int domain, int type) socketstream::socketstream(int domain, int type)
: fdstream(), _domain(domain), _type(type) { : fdstream(), _domain(domain), _type(type) {
_socket = socket(_domain, _type, 0); _socket = socket(_domain, _type, 0);
if (_socket == -1) { throw_if_min1_msg(_socket, "could not create socket");
throw std::runtime_error("socketstream: could not create socket");
}
_inbuf.fd(_socket); _inbuf.fd(_socket);
_outbuf.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) { socketstream::socketstream(socketstream&& other) {
_socket = other._socket; _socket = other._socket;
_domain = other._domain; _domain = other._domain;
_type = other._type; _type = other._type;
std::memcpy(&_sa, &other._sa, sizeof(struct sockaddr_storage));
other._socket = -1; other._socket = -1;
std::memset(&other._sa, 0, sizeof(struct sockaddr_storage));
} }
socketstream& socketstream::operator=(socketstream&& other) { socketstream& socketstream::operator=(socketstream&& other) {
@ -34,8 +46,10 @@ socketstream& socketstream::operator=(socketstream&& other) {
_socket = other._socket; _socket = other._socket;
_domain = other._domain; _domain = other._domain;
_type = other._type; _type = other._type;
std::memcpy(&_sa, &other._sa, sizeof(struct sockaddr_storage));
other._socket = -1; other._socket = -1;
std::memset(&other._sa, 0, sizeof(struct sockaddr_storage));
} }
return *this; return *this;
} }
@ -46,41 +60,133 @@ socketstream::~socketstream() {
} }
} }
void socketstream::make_server(const socket_address& address) const { void socketstream::make_server(const socket_address& sa) {
// build sockaddr size_t addr_sz = 0;
// bind switch (_domain) {
// if stream: listen 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 { 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; 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._domain = _domain;
peer._type = _type; peer._type = _type;
return peer; return peer;
} }
void socketstream::connect(const socket_address& host) { void socketstream::connect(const socket_address& host) {
// build sockaddr endpoint_from_address(host, &_sa);
// connect struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&_sa);
throw_if_min1(::connect(_socket, addr, sizeof(_sa)));
} }
std::string socketstream::address() const { 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 { void socketstream::endpoint_from_address(const socket_address& address,
return ""; // TODO 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) {
socket_address socketstream::address_from_endpoint(const struct sockaddr& endpoint) const { case AF_UNIX: {
const struct sockaddr_un* addr = reinterpret_cast<const struct sockaddr_un*>(endpoint);
sa.address = addr->sun_path;
sa.port = 0;
break;
}
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;
} }