Skip to content
This repository was archived by the owner on Apr 16, 2018. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions include/socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,22 @@ class Socket {

void bind(const char[], const int = 0) const;
void start(const char[], const int = 0, const int = SOMAXCONN) const;
void connect(const char[], const int = 0) const;
Socket accept() const;
void connect(const char[], const int = 0, bool * = nullptr) const;
Socket accept(bool * = nullptr) const;


void write(const std::string &) const;
std::string read(const int = 1024) const;

void send(const std::string &, SF::send = SF::send::NONE) const;
std::string recv(const int = 1024, SF::recv = SF::recv::NONE) const;
void write(const std::string &, bool * = nullptr) const;
std::string read(const int = 1024, bool * = nullptr) const;

void send(
const std::string &, sockaddr_storage &, SF::send = SF::send::NONE) const;
const std::string &, SF::send = SF::send::NONE, bool * = nullptr) const;
void send(const std::string &, sockaddr_storage &,
SF::send = SF::send::NONE, bool * = nullptr) const;

std::string recv(
sockaddr_storage &, const int = 1024, SF::recv = SF::recv::NONE) const;
const int = 1024, SF::recv = SF::recv::NONE, bool * = nullptr) const;
std::string recv(sockaddr_storage &, const int = 1024,
SF::recv = SF::recv::NONE, bool * = nullptr) const;


void set(/* options */) const {}
Expand Down
52 changes: 19 additions & 33 deletions include/socket_family.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#include <mutex>
#include <cstring>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <mutex>
#include <cstring>
#include <errno.h>

namespace net {
Expand All @@ -29,13 +29,13 @@ namespace SF {


enum class type {
TCP = SOCK_STREAM,
UDP = SOCK_DGRAM,
SCTP = SOCK_SEQPACKET,
RAW = SOCK_RAW,
RDM = SOCK_RDM,
NONBLOCK = SOCK_NONBLOCK,
CLOEXEC = SOCK_CLOEXEC
TCP = SOCK_STREAM,
UDP = SOCK_DGRAM,
SEQPACKET = SOCK_SEQPACKET,
RAW = SOCK_RAW,
RDM = SOCK_RDM,
NONBLOCK = SOCK_NONBLOCK,
CLOEXEC = SOCK_CLOEXEC
};

enum class shut { READ = SHUT_RD, WRITE = SHUT_WR, READWRITE = SHUT_RDWR };
Expand Down Expand Up @@ -67,15 +67,16 @@ namespace SF {

namespace method {

inline std::string getErrorMsg()
inline std::string getErrorMsg(const int errorNumber)
{
static std::mutex lockToErrorString;
std::lock_guard<std::mutex> lockGuard(lockToErrorString);
char *errMsg = strerror(errno);
static std::mutex m;
std::lock_guard<std::mutex> lock(m);
const char *errMsg = strerror(errorNumber);
std::string returnString(errMsg);
return returnString;
}


inline int construct(
sockaddr_in &addrStruct, const char _addr[], const int _port) noexcept
{
Expand All @@ -90,6 +91,7 @@ namespace method {
inline int construct(
sockaddr_in6 &addrStruct, const char _addr[], const int _port) noexcept
{
// TODO: replace code with call to getaddrinfo()
std::memset(&addrStruct, 0, sizeof(addrStruct));
addrStruct.sin6_family = AF_INET6;
addrStruct.sin6_port = htons(_port);
Expand All @@ -98,28 +100,12 @@ namespace method {
}


inline int construct(sockaddr_storage &addrStruct, SF::domain _d,
const char _addr[], const int _port)
inline int construct(sockaddr_un &addrStruct, const char _addr[]) noexcept
{
std::memset(&addrStruct, 0, sizeof(addrStruct));

switch (_d) {
case SF::domain::IPv4: {
sockaddr_in *p = reinterpret_cast<sockaddr_in *>(&addrStruct);
p->sin_family = AF_INET;
p->sin_port = htons(_port);
return inet_pton(AF_INET, _addr, &p->sin_addr);
}

case SF::domain::IPv6: {
sockaddr_in6 *p = reinterpret_cast<sockaddr_in6 *>(&addrStruct);
p->sin6_family = AF_INET6;
p->sin6_port = htons(_port);
return inet_pton(AF_INET6, _addr, &p->sin6_addr);
}

default: return -1;
}
addrStruct.sun_family = AF_UNIX;
std::strncpy(addrStruct.sun_path, _addr, 108);
return 1;
}
}
}
151 changes: 113 additions & 38 deletions src/socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,20 @@ void Socket::bind(const char _addr[], const int _port) const
}
} break;

case SF::domain::UNIX: {
sockaddr_un servaddr;
res = net::method::construct(servaddr, _addr);
unlink(servaddr.sun_path);
res = ::bind(sockfd, (sockaddr *) &servaddr, sizeof(servaddr));
res = (res == 0) ? 1 : res;
} break;

default: throw std::logic_error("Protocol yet not implemented");
}

const auto currErrno = errno;
if (res == -1) {
throw std::runtime_error(net::method::getErrorMsg());
throw std::runtime_error(net::method::getErrorMsg(currErrno));
} else if (res == 0) {
throw std::invalid_argument("Address argument invalid");
}
Expand All @@ -41,9 +50,10 @@ void Socket::start(const char _addr[], const int _port, const int _q) const
try {
bind(_addr, _port);

if (type == SF::type::TCP || type == SF::type::SCTP) {
if (type == SF::type::TCP || type == SF::type::SEQPACKET) {
if (listen(sockfd, _q) < 0) {
throw std::runtime_error(net::method::getErrorMsg());
const auto currErrno = errno;
throw std::runtime_error(net::method::getErrorMsg(currErrno));
}
}
} catch (...) {
Expand All @@ -52,7 +62,7 @@ void Socket::start(const char _addr[], const int _port, const int _q) const
}


void Socket::connect(const char _addr[], const int _port) const
void Socket::connect(const char _addr[], const int _port, bool *_errorNB) const
{
auto res = -1;
switch (domain) {
Expand All @@ -74,21 +84,34 @@ void Socket::connect(const char _addr[], const int _port) const
}
} break;

case SF::domain::UNIX: {
sockaddr_un addr;
res = net::method::construct(addr, _addr);
res = ::connect(sockfd, (sockaddr *) &addr, sizeof(addr));
res = (res == 0) ? 1 : res;
} break;

default: throw std::logic_error("Protocol yet not implemented");
}

// TODO: Check for error == EINPROGRESS and don't throw exception in that
// case.

const auto currErrno = errno;
if (res == -1) {
throw std::runtime_error(net::method::getErrorMsg());
if (currErrno == EINPROGRESS) {
if (_errorNB != nullptr) {
*_errorNB = true;
} else {
throw std::invalid_argument("errorNB argument missing");
}
} else {
throw std::runtime_error(net::method::getErrorMsg(currErrno));
}
} else if (res == 0) {
throw std::invalid_argument("Address argument invalid");
}
}


Socket Socket::accept() const
Socket Socket::accept(bool *_errorNB) const
{
auto peerAddr = std::make_unique<sockaddr_storage>();

Expand All @@ -97,92 +120,137 @@ Socket Socket::accept() const

auto client = ::accept(sockfd, (sockaddr *) peerAddr.get(), &peerAddrSize);

const auto currErrno = errno;
if (client == -1) {
// TODO: Check for client == EAGAIN or EWOULDBLOCK and
// don't throw exception in that case.
throw std::runtime_error(net::method::getErrorMsg());
if (currErrno == EAGAIN || currErrno == EWOULDBLOCK) {
if (_errorNB != nullptr) {
*_errorNB = true;
} else {
throw std::invalid_argument("errorNB argument missing");
}
} else {
throw std::runtime_error(net::method::getErrorMsg(currErrno));
}
}

return Socket(client, peerAddr);
}


void Socket::write(const std::string &_msg) const
void Socket::write(const std::string &_msg, bool *_errorNB) const
{
const auto written = low_write(::write, sockfd, _msg);

const auto currErrno = errno;
if (written == -1) {
// TODO: Check for written == EAGAIN or EWOULDBLOCK and
// don't throw exception in that case.
throw std::runtime_error(net::method::getErrorMsg());
if (currErrno == EAGAIN || currErrno == EWOULDBLOCK) {
if (_errorNB != nullptr) {
*_errorNB = true;
} else {
throw std::invalid_argument("errorNB argument missing");
}
} else {
throw std::runtime_error(net::method::getErrorMsg(currErrno));
}
}
}


void Socket::send(const std::string &_msg, SF::send _flags) const
void Socket::send(
const std::string &_msg, SF::send _flags, bool *_errorNB) const
{
const auto flags = static_cast<int>(_flags);
const auto sent = low_write(::send, sockfd, _msg, flags);

const auto currErrno = errno;
if (sent == -1) {
// TODO: Check for sent == EAGAIN or EWOULDBLOCK and
// don't throw exception in that case.
throw std::runtime_error(net::method::getErrorMsg());
if (currErrno == EAGAIN || currErrno == EWOULDBLOCK) {
if (_errorNB != nullptr) {
*_errorNB = true;
} else {
throw std::invalid_argument("errorNB argument missing");
}
} else {
throw std::runtime_error(net::method::getErrorMsg(currErrno));
}
}
}


void Socket::send(
const std::string &_msg, sockaddr_storage &_addr, SF::send _flags) const
void Socket::send(const std::string &_msg, sockaddr_storage &_addr,
SF::send _flags, bool *_errorNB) const
{
const auto flags = static_cast<int>(_flags);
const auto sent = low_write(
::sendto, sockfd, _msg, flags, (sockaddr *) &_addr, sizeof(_addr));

const auto currErrno = errno;
if (sent == -1) {
// TODO: Check for sent == EAGAIN or EWOULDBLOCK and
// don't throw exception in that case.
throw std::runtime_error(net::method::getErrorMsg());
if (currErrno == EAGAIN || currErrno == EWOULDBLOCK) {
if (_errorNB != nullptr) {
*_errorNB = true;
} else {
throw std::invalid_argument("errorNB argument missing");
}
} else {
throw std::runtime_error(net::method::getErrorMsg(currErrno));
}
}
}


std::string Socket::read(const int _bufSize) const
std::string Socket::read(const int _bufSize, bool *_errorNB) const
{
std::string str;
str.reserve(_bufSize);

const auto recvd = low_read(::read, sockfd, str);

const auto currErrno = errno;
if (recvd == -1) {
// TODO: Check for bytes == EAGAIN or EWOULDBLOCK and
// don't throw exception in that case.
throw std::runtime_error(net::method::getErrorMsg());
if (currErrno == EAGAIN || currErrno == EWOULDBLOCK) {
if (_errorNB != nullptr) {
*_errorNB = true;
} else {
throw std::invalid_argument("errorNB argument missing");
}
} else {
throw std::runtime_error(net::method::getErrorMsg(currErrno));
}
}

return str;
}


std::string Socket::recv(const int _bufSize, SF::recv _flags) const
std::string Socket::recv(
const int _bufSize, SF::recv _flags, bool *_errorNB) const
{
std::string str;
str.reserve(_bufSize);

const auto flags = static_cast<int>(_flags);
const auto recvd = low_read(::recv, sockfd, str, flags);

const auto currErrno = errno;
if (recvd == -1) {
// TODO: Check for recvd == EAGAIN or EWOULDBLOCK and
// don't throw exception in that case.
throw std::runtime_error(net::method::getErrorMsg());
if (currErrno == EAGAIN || currErrno == EWOULDBLOCK) {
if (_errorNB != nullptr) {
*_errorNB = true;
} else {
throw std::invalid_argument("errorNB argument missing");
}
} else {
throw std::runtime_error(net::method::getErrorMsg(currErrno));
}
}

return str;
}


std::string Socket::recv(
sockaddr_storage &_addr, const int _bufSize, SF::recv _flags) const
std::string Socket::recv(sockaddr_storage &_addr, const int _bufSize,
SF::recv _flags, bool *_errorNB) const
{
std::string str;
str.reserve(_bufSize);
Expand All @@ -192,10 +260,17 @@ std::string Socket::recv(
const auto recvd
= low_read(::recvfrom, sockfd, str, flags, (sockaddr *) &_addr, &length);

const auto currErrno = errno;
if (recvd == -1) {
// TODO: Check for recvd == EAGAIN or EWOULDBLOCK and
// don't throw exception in that case.
throw std::runtime_error(net::method::getErrorMsg());
if (currErrno == EAGAIN || currErrno == EWOULDBLOCK) {
if (_errorNB != nullptr) {
*_errorNB = true;
} else {
throw std::invalid_argument("errorNB argument missing");
}
} else {
throw std::runtime_error(net::method::getErrorMsg(currErrno));
}
}

return str;
Expand Down