Code Monkey home page Code Monkey logo

socketwrapper's People

Contributors

tglane avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

socketwrapper's Issues

Buld fails with clang / possible memleak

$ make
clang -o tls_example tls_example.cpp -std=c++17 -fpic -Wall -Werror -Wextra -pedantic -lpthread -lstdc++ -lssl -lcrypto
[...]
/usr/bin/../lib/gcc/i686-linux-gnu/8/../../../../include/c++/8/optional:200:11: error: destructor called on
      non-final 'net::tls_connection<net::ip_version::v4>' that has virtual functions but non-virtual destructor
[...]
1 error generated.
make: *** [Makefile:14: tls] Fehler 1

tells that the base class constructor is not virtual which might cause memleaks.

Easy to fix with

diff --git a/include/socketwrapper/detail/base_socket.hpp b/include/socketwrapper/detail/base_socket.hpp
index 230cde9..f575bd3 100644
--- a/include/socketwrapper/detail/base_socket.hpp
+++ b/include/socketwrapper/detail/base_socket.hpp
@@ -57,7 +57,7 @@ public:
 #endif
     }
 
-    ~base_socket()
+    virtual ~base_socket()
     {
         if(m_sockfd > 0)
         {

To build using clang I used

diff --git a/example/Makefile b/example/Makefile
index cf6996a..56322d5 100644
--- a/example/Makefile
+++ b/example/Makefile
@@ -1,7 +1,7 @@
-cc = g++
+cc = clang
 
 CFLAGS = -std=c++17 -fpic -Wall -Werror -Wextra -pedantic
-LDFLAGS = -lpthread
+LDFLAGS = -lpthread -lstdc++
 
 %.o: %.cpp
        $(cc) -c $< -o $@ $(CFLAGS)

Remove code duplication using a traits class

Hi,

I see frequent blocks of duplicate code within constexpr conditions.

You might consider trimming those using a traits class that distinguishes between the two different cases of IPv4 and IPv6:

diff --git a/include/socketwrapper/detail/utility.hpp b/include/socketwrapper/detail/utility.hpp
index 5de451b..e49da53 100644
--- a/include/socketwrapper/detail/utility.hpp
+++ b/include/socketwrapper/detail/utility.hpp
@@ -38,6 +38,23 @@ struct connection_info
 
 namespace detail {
 
+template<ip_version IP_VER>
+struct traits;
+
+template<>
+struct traits<ip_version::v4>
+{
+    using addr = sockaddr_in;
+    static constexpr size_t addr_str_len = INET_ADDRSTRLEN;
+};
+
+template<>
+struct traits<ip_version::v6>
+{
+    using addr = sockaddr_in6;
+    static constexpr size_t addr_str_len = INET6_ADDRSTRLEN;
+};
+
 template<ip_version IP_VER>
 inline int resolve_hostname(std::string_view host_name, uint16_t port, socket_type type, std::variant<sockaddr_in, sockaddr_in6>& addr_out)
 {

This will e.g. be used to trim this:

template<ip_version IP_VER>
inline connection_info resolve_addrinfo(sockaddr* addr_in)
{
    connection_info peer {};
    if constexpr(IP_VER == ip_version::v4)
    {
        peer.addr.resize(INET_ADDRSTRLEN);
        std::string port_str; // Use string instead of array here because std::stoi creates a string anyway
        port_str.resize(6);

        if(inet_ntop(AF_INET, &(reinterpret_cast<sockaddr_in*>(addr_in)->sin_addr), peer.addr.data(), peer.addr$
            throw std::runtime_error {"Failed to resolve addrinfo."};
        peer.port = ntohs(reinterpret_cast<sockaddr_in*>(addr_in)->sin_port);

        return peer;
    }
    else if constexpr(IP_VER == ip_version::v6)
    {
        peer.addr.resize(INET6_ADDRSTRLEN);
        std::string port_str; // Use string instead of array here because std::stoi creates a string anyway
        port_str.resize(6);

        if(inet_ntop(AF_INET, &(reinterpret_cast<sockaddr_in6*>(addr_in)->sin6_addr), peer.addr.data(), peer.ad$
            throw std::runtime_error {"Failed to resolve addrinfo."};
        peer.port = ntohs(reinterpret_cast<sockaddr_in6*>(addr_in)->sin6_port);

        return peer;
    }
    else
    {
        static_assert(IP_VER == ip_version::v4 || IP_VER == ip_version::v6);
    }
}

Into just that:

template<ip_version IP_VER>
inline connection_info resolve_addrinfo(sockaddr* addr_in)
{
    connection_info peer {};
    peer.addr.resize(traits<IP_VER>::addr_str_len);
    std::string port_str; // Use string instead of array here because std::stoi creates a string anyway
    port_str.resize(6);

    if(inet_ntop(AF_INET, &(reinterpret_cast<typename traits<IP_VER>::addr*>(addr_in)->sin_addr), peer.addr.dat$
        throw std::runtime_error {"Failed to resolve addrinfo."};
    peer.port = ntohs(reinterpret_cast<typename traits<IP_VER>::addr*>(addr_in)->sin_port);

    return peer;
}

Of course this works elegantly only if there are no differences except types and values used in the distinction. Also you exchange the nice compile-time error of the static_assert for a less helpful C++ template error.

Add timeout to all async socket operations

Currently only the sync operations (read, write, accept) offer the option to set a timeout after which the operation returns even if no data was processed. This should also be possible for the async counterparts.

Add non-template base class for all socket types

All of the socket types share some basic data type like the file descriptor or the network family.
This would be nice to store multiple socket types in one container even if they do not share the same signatures for their read/write methods.

Contact

Hey, where could I contact you in private about your project and some related stuff ?

Feat:Add configuration methods to socket classes

Currently the only way to set configuration settings of a socket is to use the sockets base_socket::get() function to receive the file descriptor and use it with POSIXs functions to configure the socket. There should be member functions that allow the user to do this.

Refactor functions that take a span parameter

Currently all functions that use net::span as buffer parameter take it as a r-value reference. This should be changed to a value type parameter because it is a non-owning cheap to copy type --- like with std::string_view as a parameter.

Add coroutine support

With C++20 came the coroutine library to support concurrent operations. This is particularly interesting for IO operations like we have in networking.
The goal should be to have read/write/accept functions for each socket class that return an awaitable. Internally the executor/notifier implementations should be used.

I will start with some research on this topic since the C++ coroutines seem rather complicated.

Socket server example gives runtime error when more than one client connects

Hello changed your code so that one receiver stays live to accept calls and sender periodically sends data. Single sender, single receiver it works fine but when i run second sender the code gives runtime error and exits. Maybe I need to add some more code to example to make it working?

#include "../socketwrapper.hpp"
#include
#include
#include

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

if(strcmp(argv[1], "r") == 0)
{
    std::cout << "--- Receiver ---\n";
 /*   net::tcp_acceptor<net::ip_version::v4> acceptor_two {"0.0.0.0", 4556};
    acceptor_two.async_accept([](net::tcp_connection<net::ip_version::v4>&& sock) {
        std::cout << sock.get() << std::endl;
    });

*/
net::tcp_acceptornet::ip_version::v4 acceptor {"0.0.0.0", 5060};
std::cout << "Waiting for accept\n";
std::vector<net::tcp_connectionnet::ip_version::v4> conns;
acceptor.async_accept([&conns](net::tcp_connectionnet::ip_version::v4&& conn) {
std::array<char, 1024> buffer;
std::cout << "Accepted\n";

        conns.push_back(std::move(conn));
        auto& sock = conns.back();
        sock.async_read(net::span {buffer}, [&buffer](size_t br){
            std::cout << "Received: " << br << " - " << std::string_view {buffer.data(), br} << '\n';
        });
    });

    std::cout << "Wait for data ...\n";
    std::this_thread::sleep_for(std::chrono::milliseconds(100000));
}
else if(strcmp(argv[1], "s") == 0)
{
    {
        std::cout << "--- Sender ---\n";
        net::tcp_connection<net::ip_version::v4> sock {"127.0.0.1", 5060};
        std::cout << "Connected\n";
        std::vector<char> vec {'H', 'e', 'l', 'l', 'o'};

        std::this_thread::sleep_for(std::chrono::milliseconds(2000));
        std::string_view buffer {"Hello String_view-World"};
        sock.send(net::span {buffer.begin(), buffer.end()});

        std::cout << "Sent\n";
    }
    {
        std::cout << "--- Sender ---\n";
        net::tcp_connection<net::ip_version::v4> sock {"127.0.0.1", 5060};
        std::cout << "Connected\n";
        std::vector<char> vec {'H', 'e', 'l', 'l', 'o'};
        // sock.send(net::span {vec});
        // sock.send(net::span {std::string {"Hello World"}});

while(true){
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::string_view buffer {"Hello String_view -World"};
sock.send(net::span {buffer.begin(), buffer.end()});
}
std::cout << "Sent\n";
}
}
}

Feat:Add promised based socket operations

Call read/write/accept on a socket and receive a std::future that is resolved when the async socket operations finished inside the async context. This avoids the clutter that can be caused by a multitude of callbacks.

Fix:Dont overwrite already registered callbacks when adding a new callback

Currently only one callback per socket is registered so you cant register a write and a read callback at the same time.
It should be possible to register one read and one write callback per socket at the same time.

By calling a async read/write function after a read/write callback was already registered should overwrite the previously registered read/write callback.

Create a better abstraction for ip addresses/connection endpoints

Currently the only "abstraction" for ip addresses and ports to represent an endpoint is a std::string_view storing the ip address of the endpoint as a string and a uint16_t that represents the endpoints port.

This should be abstracted away by a address/endpoint class that offers multiple options to create an instance of it.

getting a warning about a it saying something in async is deprecated

Just a little heads up I'm getting this warning in Visual Studio Code on Ubuntu 20.04 compiling with GCC 11
And I'm using Cmake to include the header only library as a INTERFACE

I have tried to clone a brand new up to date version of your repo and it still gives me the warning

Btw I do store all external libraries in the project folder in Libraries/External for easier management and that is why the path is starting with that

[build] Libraries/External/Cpp-socketwrapper/include/socketwrapper/detail/async.hpp: In member function ‘bool net::detail::async_context::add(int, net::detail::async_context::event_type, CALLBACK_TYPE&&)’:
[build] Libraries/External/Cpp-socketwrapper/include/socketwrapper/detail/async.hpp:125:38: warning: bitwise operation between different enumeration types ‘const net::detail::async_context::event_type’ and ‘EPOLL_EVENTS’ is deprecated [-Wdeprecated-enum-enum-conversion]
[build]   125 |             item.event.events = type | EPOLLET;
[build]       |                                      ^

And noticed you had made a issue about a month ago about async so were starting to think it were related wich is why I wanted to inform you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.