diff --git a/libscio.hpp b/libscio.hpp index d221aad..6aab244 100644 --- a/libscio.hpp +++ b/libscio.hpp @@ -9,11 +9,13 @@ #ifndef _libscio_H_ #define _libscio_H_ +#include #include #include #include #include #include +#include namespace sc { @@ -21,7 +23,11 @@ namespace sc { class fdoutbuf : public std::streambuf { public: - fdoutbuf(int fd): _fd(fd) {} + fdoutbuf(int fd) : _fd(fd) {} + fdoutbuf() : _fd(-1) {} + + int fd() const { return _fd; } + void fd(int fd) { _fd = fd; } protected: int _fd; @@ -33,6 +39,10 @@ namespace sc { class fdostream : public std::ostream { public: fdostream(int fd) : std::ostream(&_outbuf), _outbuf(fd) {} + fdostream() : std::ostream(&_outbuf), _outbuf(-1) {} + + int fd() const { return _outbuf.fd(); } + void fd(int fd) { _outbuf.fd(fd); } protected: fdoutbuf _outbuf; @@ -41,6 +51,10 @@ namespace sc { class fdinbuf : public std::streambuf { public: fdinbuf(int fd) : _fd(fd) {} + fdinbuf() : _fd(-1) {} + + int fd() const { return _fd; } + void fd(int fd) { _fd = fd; } protected: int _fd; @@ -53,6 +67,10 @@ namespace sc { class fdistream : public std::istream { public: fdistream(int fd) : std::istream(&_inbuf), _inbuf(fd) {} + fdistream() : std::istream(&_inbuf), _inbuf(-1) {} + + int fd() const { return _inbuf.fd(); } + void fd(int fd) { _inbuf.fd(fd); } protected: fdinbuf _inbuf; @@ -61,14 +79,49 @@ namespace sc { class fdstream : public fdostream, public fdistream { public: fdstream(int fd) : fdostream(fd), fdistream(fd) {} + fdstream() : fdostream(-1), fdistream(-1) {} + }; + + struct socket_address { + std::string address; + int port; }; class socketstream : public fdstream { public: - socketstream(int fd) : fdstream(fd) {} + socketstream() = default; + socketstream(int domain, int type); - //void make_server(const std::string& address, int port); - //void connect(const std::string& address, int port); + // copying forbidden + socketstream(const socketstream&) = delete; + socketstream& operator=(const socketstream&) = delete; + + // moving allowed + socketstream(socketstream&& other); + socketstream& operator=(socketstream&& other); + + // cleanup: socketstream is RAII class for open socket + virtual ~socketstream(); + + // server + void make_server(const socket_address& address) const; + socketstream accept() const; + + // client + void connect(const socket_address& host); + + // 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; + + protected: + int _socket {-1}; + int _domain {0}; + int _type {0}; }; struct float_80 { diff --git a/socketstream.cpp b/socketstream.cpp new file mode 100644 index 0000000..849d6e4 --- /dev/null +++ b/socketstream.cpp @@ -0,0 +1,86 @@ +// +// socketstream.cpp +// libscio +// +// Created by Bob Polis at 2020-03-02 +// Copyright (c) 2020 SwiftCoder. All rights reserved. +// + +#include "libscio.hpp" +#include + +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"); + } + _inbuf.fd(_socket); + _outbuf.fd(_socket); +} + +socketstream::socketstream(socketstream&& other) { + _socket = other._socket; + _domain = other._domain; + _type = other._type; + + other._socket = -1; +} + +socketstream& socketstream::operator=(socketstream&& other) { + if (this != &other) { + _socket = other._socket; + _domain = other._domain; + _type = other._type; + + other._socket = -1; + } + return *this; +} + +socketstream::~socketstream() { + if (_socket != -1) { + close(_socket); + } +} + +void socketstream::make_server(const socket_address& address) const { + // build sockaddr + // bind + // if stream: listen +} + + 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; + peer._domain = _domain; + peer._type = _type; + return peer; +} + +void socketstream::connect(const socket_address& host) { + // build sockaddr + // connect +} + +std::string socketstream::address() const { + return ""; // TODO +} + +std::string socketstream::peer_address() const { + return ""; // TODO +} + +struct sockaddr socketstream::endpoint_from_address(const socket_address& address) const { + +} + +socket_address socketstream::address_from_endpoint(const struct sockaddr& endpoint) const { + +}