Skip to content
Open
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
54 changes: 54 additions & 0 deletions example/unix_dgram_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "../include/socketwrapper/unixdgram.hpp"
#include <cstring>
#include <iostream>
#include <thread>

int main(int argc, char** argv)
{
if (argc <= 1)
return 0;

if (strcmp(argv[1], "r") == 0)
{
std::cout << "--- Receiver ---\n";

auto sock = net::unix_dgram_socket(net::endpoint_unix("/tmp/sock2"));

auto buffer = std::array<char, 1024>{};
const auto [bytes_read, peer] = sock.read(net::span(buffer));
std::cout << "Peer addr: " << peer.get_addr_string()
<< "; Bytes read: " << bytes_read << '\n';
std::cout << std::string_view(buffer.data(), bytes_read) << '\n';

const auto read_result = sock.read(net::span{buffer}, std::chrono::milliseconds(4000));
if (read_result.has_value())
{
const auto& [bytes_read, peer_opt] = read_result.value();
std::cout << "Peer addr: " << peer_opt.get_addr_string()
<< "; Bytes read: " << bytes_read << '\n';
std::cout << std::string_view{buffer.data(), bytes_read} << '\n';
}
else
{
std::cout << "No message received :(\n";
}
}
else if (strcmp(argv[1], "s") == 0)
{
std::cout << "--- Sender ---\n";

auto sock = net::unix_dgram_socket();

auto buffer = std::string{"Hello world"};
const auto endpoint = net::endpoint_unix("/tmp/sock2");
sock.send(endpoint, net::span(buffer));
std::cout << "All messages sent." << std::endl;

std::this_thread::sleep_for(std::chrono::milliseconds(2000));

auto vec = std::vector<char>{'A', 'B', 'C'};
sock.send(endpoint, net::span(vec));
sock.send(endpoint, net::span("KekWWW"));
std::cout << "All messages sent. Again." << std::endl;
}
}
63 changes: 63 additions & 0 deletions example/unix_stream_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "../include/socketwrapper/unixstream.hpp"

#include <cstring>
#include <iostream>
#include <thread>

int main(int argc, char** argv)
{
if (argc <= 1)
return 0;

if (strcmp(argv[1], "r") == 0)
{
std::cout << "--- Receiver ---\n";

auto buffer = std::array<char, 10000>{};
auto acceptor = net::unix_stream_acceptor(net::endpoint_unix("/tmp/sock1"));

std::cout << "Waiting for accept\n";
auto opt = acceptor.accept(std::chrono::milliseconds(5000));
if (!opt)
{
std::cout << "No acception\n";
return 0;
}
const auto& sock = opt.value();
std::cout << "Accepted\n";

std::cout << "Wait for data ...\n";
size_t bytes_read = sock.read(net::span{buffer});
std::cout << "Received: " << bytes_read << " - " << std::string_view{buffer.data(), bytes_read} << '\n';

const auto read_result = sock.read(net::span{buffer}, std::chrono::milliseconds(4000));
if (read_result.has_value())
{
std::cout << "Received: " << *read_result << " - " << std::string_view{buffer.data(), *read_result} << '\n';
}
}
else if (strcmp(argv[1], "s") == 0)
{
std::cout << "--- Sender ---\n";

auto sock = net::unix_stream_connection();
std::cout << "Socket created\n";

sock.connect(net::endpoint_unix("/tmp/sock1"));
std::cout << "Connected\n";

std::this_thread::sleep_for(std::chrono::milliseconds(3000));

auto vec = std::vector<char>{'H', 'e', 'l', 'l', 'o'};
// sock.send(net::span{vec});
// sock.send(net::span{std::string {"Hello World"}});
sock.send(net::span{vec.begin(), vec.end()});
std::cout << "Sent\n";

std::this_thread::sleep_for(std::chrono::milliseconds(1000));

auto buffer_view = std::string_view{"Hello String_view-World"};
sock.send(net::span{buffer_view.begin(), buffer_view.end()});
std::cout << "Sent again\n";
}
}
3 changes: 2 additions & 1 deletion include/socketwrapper/detail/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ namespace net {
enum class ip_version : uint8_t
{
v4 = AF_INET,
v6 = AF_INET6
v6 = AF_INET6,
unixsock = AF_UNIX
};

enum class socket_type : uint8_t
Expand Down
72 changes: 72 additions & 0 deletions include/socketwrapper/endpoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#include <algorithm>
#include <cstddef>
#include <string>
#include <cstring>
#include <string_view>
#include <sys/un.h>

namespace net {

Expand Down Expand Up @@ -114,6 +116,11 @@ class endpoint<ip_version::v4>
m_up_to_date = false;
return reinterpret_cast<sockaddr&>(m_addr);
}

inline bool is_valid_addr_size(size_t s)
{
return s == addr_size;
}
};

/// Template specialization for ip v6 connections
Expand Down Expand Up @@ -216,11 +223,76 @@ class endpoint<ip_version::v6>
m_up_to_date = false;
return reinterpret_cast<sockaddr&>(m_addr);
}

inline bool is_valid_addr_size(size_t s)
{
return s == addr_size;
}
};


/// Template specialization for unix connections
template <>
class endpoint<ip_version::unixsock>
{
sockaddr_un m_addr;

public:
using addr_type = sockaddr_un;
static constexpr const size_t addr_size = sizeof(sockaddr_un);
static constexpr const size_t addr_str_len = sizeof(sockaddr_un::sun_path);
static constexpr const int addr_family = AF_UNIX;

endpoint() = default;

explicit endpoint(const sockaddr_un& addr)
: m_addr(addr)
{

}

explicit endpoint(const char* path)
{
int n = strlen(path);
if(n >= (int)addr_str_len - 1)
throw std::invalid_argument("path is too long");
m_addr.sun_family = AF_UNIX;
std::memcpy(m_addr.sun_path, path, n);
}

std::string get_addr_string() const
{
return std::string(m_addr.sun_path);
}

std::array<uint8_t, addr_str_len> get_addr_bytes() const
{
auto bytes = std::array<uint8_t, addr_str_len>{};
std::copy_n(m_addr.sun_path, addr_str_len, bytes.data());
return bytes;
}


const sockaddr& get_addr() const
{
return reinterpret_cast<const sockaddr&>(m_addr);
}

sockaddr& get_addr()
{
return reinterpret_cast<sockaddr&>(m_addr);
}

inline bool is_valid_addr_size(size_t s)
{
return s <= addr_size;
}
};

/// Shorthand using-declarations for endpoint class template specializations
using endpoint_v4 = endpoint<ip_version::v4>;
using endpoint_v6 = endpoint<ip_version::v6>;
using endpoint_unix = endpoint<ip_version::unixsock>;

} // namespace net

Expand Down
4 changes: 2 additions & 2 deletions include/socketwrapper/tcp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ class tcp_acceptor : public detail::base_socket
{
auto client_addr = endpoint<ip_ver_v>();
socklen_t addr_len = client_addr.addr_size;
if (const int sock = ::accept(fd, &(client_addr.get_addr()), &addr_len);
sock > 0 && addr_len == client_addr.addr_size)
const int sock = ::accept(fd, &(client_addr.get_addr()), &addr_len);
if (sock > 0 && client_addr.is_valid_addr_size(addr_len))
{
return std::move(tcp_connection<ip_ver_v>{sock, client_addr});
}
Expand Down
12 changes: 12 additions & 0 deletions include/socketwrapper/unixdgram.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef SOCKETWRAPPER_NET_UNIXDGRAM_HPP
#define SOCKETWRAPPER_NET_UNIXDGRAM_HPP

#include "udp.hpp"

namespace net {

using unix_dgram_socket = udp_socket<ip_version::unixsock>;

} // namespace net

#endif
13 changes: 13 additions & 0 deletions include/socketwrapper/unixstream.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef SOCKETWRAPPER_NET_UNIXSTREAM_HPP
#define SOCKETWRAPPER_NET_UNIXSTREAM_HPP

#include "tcp.hpp"

namespace net {

using unix_stream_connection = tcp_connection<ip_version::unixsock>;
using unix_stream_acceptor = tcp_acceptor<ip_version::unixsock>;

} // namespace net

#endif