Giter Club home page Giter Club logo

sockpp's People

Contributors

anrddh avatar arsdever avatar bmahlbrand avatar borrrden avatar desertkun avatar fpagliughi avatar jaandev avatar mcopik avatar polarisjunior avatar ramonnr avatar sheinb avatar snej avatar tsilia 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sockpp's Issues

Linking on Windows with minGW-x64

I was able to create a static library in both Windows and Linux (using ArchLinux) following the README. Two files were generated:

  • libsockpp.a for Linux
  • sockpp-static.lib for Windows

Then I need to use the static library in another program, which is built using a Makefile.
In Linux no issue occurs, while in Windows with minGW-x64 I received multiple errors like

C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccvvpJbH.o:tcp6echo.cpp:(.text+0x176): undefined reference to `sockpp::operator<<(std::ostream&, sockpp::inet6_address const&)'

To reproduce the issue with the example tcp6echo (assuming headers in ./include and static library in ./lib):

  • In Linux all works ok using g++ -I./include -o tcp6echo tcp6echo.cpp -L./lib -lsockpp
  • In Windows with minGW-x64 issue occurs using g++ -I./include -o tcp6echo tcp6echo.cpp -L./lib -l:sockpp-static.lib

Lots and Lots of Unresolved External Symbols

I've been trying to integrate your code with MS Visual Studio 2019 for quite awhile now and I've come up with many errors. Currently the one I can not figure out is all these unresolved external symbols that I'm getting. I'm new to integrating libraries with Visual Studio, or anything for that matter. I'll walk you through what I've done.

I used CMake to build the binaries for a static library then in the .sln file it produced I built the solution.

After building it I placed the sockpp-static.lib and sockpp-obj.lib in a dependencies folder in the repo of the project I was testing it with. I pointed the linker at both of these files and then added the include and library directories.

It threw some weird runtime errors that I had to fix and some weird iterator debug errors that I fixed and now I'm at this point where it throws all these unresolved external symbol errors based off the sockpp-static.lib file.

It looks like this:
https://i.imgur.com/NImylP6.png

It does this after I use anything to do with sockpp.
For example:

        in_port_t port = 5050;

	socket_initializer sockInit;

	return 0;

will throw a bunch of errors. However if it's only in_port_t port; then it won't throw the errors.

I've tried messing with the runtime library it uses and some preprocessor settings as well. I even tried adding each of the .obj files that are generated by CMake to the Additional Directories but all that does is make it so the file that is causing the issue is no longer "sockpp-static.lib(socket.obj)" but it's "socket.obj" that's causing the problem.

Forgive me, I'm new to this. I have no clue what could be causing all these errors.

Scatter/gather I/O (like readv/writev)

For performance reasons it's good to be able to read or write multiple discontiguous byte ranges in one system call. The generic system calls for this are writev and readv; the socket-specific ones are sendmsg and recvmsg.

The C++ methods for these would probably take a const std::vector<iovec>& parameter.

Regression: Failure in connect() no longer sets last_error

A failure in connector::connect() or acceptor::open now leaves the last_error property at 0 instead of an actual error code.

This is a side effect of the fix of #23. socket::close now overwrites last_error with the status of the ::close call, which is almost always 0.

How to build documentation using CMake

I installed Doxygen and Graphiz (because it first said "doxygen missing components: dot") and I'm trying this on Windows:

mkdir build
cd build
cmake ..
cmake -D SOCKPP_BUILD_DOCUMENTATION=ON --build .

But no HTML files are appearing anywhere in the build directory. How does this work?

My output is:

-- Building for: Visual Studio 16 2019
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.17763.
-- The C compiler identification is MSVC 19.24.28314.0
-- The CXX compiler identification is MSVC 19.24.28314.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Creating static library: sockpp-static
-- Configuring done
-- Generating done
-- Build files have been written to: C:/software/sockpp/build
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.17763.
-- Creating static library: sockpp-static
-- Found Doxygen: C:/Program Files/doxygen/bin/doxygen.exe (found version "1.8.17 (b5fa3cd1c6e6240e20d3b80a70e3f04040b32021*)") found components:  doxygen dot
-- Configuring done
-- Generating done
-- Build files have been written to: C:/software/sockpp/build

I discovered that I could simply run doxygen to generate the documentation, but that should be in the README file. (or putting the documentation online, that would be better)

Datagram/UDP support

Get the datagram/UDP sockets working for all the address families and make sure it works on Windows as well.

Win32 build issue with Unicode

Per the UTF-8 Everywhere Manifesto, it's best to not rely on the legacy ANSI .vs UNICODE macros for Win32 functions that take strings. Since you explicitly use an ANSI string for the call to LoadLibrary you should explicitly use the LoadLibraryA method.

This causes problems when trying to build your library using vcpkg manager when the setup adds the recommended UNICODE _UNICODE defines.

In exception.cpp use FormatMessageA instead of FormatMessage.

select

Great library! Any interest in integrating select?

If so, I'm interested in working on that, but I'm curious what your thoughts are on how it would best fit into the library / future plans you might have.

Questions and Answers

Hi there. I found useful to have such a place to get answers to some questions related to the library. So, hopefully, this does the job.

At least I have a little list of questions that I want to ask you before continuing to work on my project.

  1. Does the sockpp::tcp_socket ensure that the packets will be transferred for 100% (I mean if there is not a full connection lost, but some packets were dropped) and in the correct order?
  2. Is there a way to get the local IP address through the library (could be it's not related to this library)
  3. Is there a way to resolve a domain name to an IP address?

Thanks in advance.

Does Windows support socket timeouts?

In the stream_socket class, the calls to read_timeout() and write_timeout() are empty for Windows. I can't remember if Windows doesn't support this, or if I was just too lazy to look up how.

@borrrden Do you know?

bool stream_socket::read_timeout(const microseconds& to)
{
	#if !defined(_WIN32)
		timeval tv = to_timeval(to);
		return set_option(SOL_SOCKET, SO_RCVTIMEO, tv);
	#else
		return false;
	#endif
}

Can I clone a udp_socket

Since I can use clone() to copy a tcp_socket or tcp_connect, I want to do the same for udp_socket
For example, I want to have one thread to read from a udp_socket and another thread to write to this udp_socket
Here is a demo:

const int BUF_SIZE = 512;
const string host = "";//the target
const in_port_t port = 12345;
void listener(sockpp::udp_socket sock) {
	string s;
	s.resize(BUF_SIZE);
	while (true) {
		int n = sock.recv(&s[0], BUF_SIZE);
		cout << s.substr(0, n) << endl;
	}
}
void sender(sockpp::udp_socket sock) {
	string s;
	while (true) {
		cin >> s;
		sock.send_to(s, {host, port});
	}
}
int main() {
	sockpp::initialize();
	sockpp::udp_socket sock;
	sock.connect({host, port});
	std::thread thr(listener, sock.clone());
	sender(std::move(sock));
}

But this example fails to compile. In order to make it work, I consult stream_socket.h and modified datagram_socket.h.
Specifically, I tried adding a function like below in class datagram_socket:

datagram_socket clone() const {
	auto h = base::clone().release();
	return datagram_socket(h);
}

And a function below in class datagram_socket_tmpl:

datagram_socket_tmpl(datagram_socket&& sock)
	: base(std::move(sock)) {}

It seems to work fine under Windows, but I didn't do a rigorous test. Is there a bug in this method, and is there a better way to deal with the problem?

Doc-comment issues (Clang warnings with -Wdocumentation)

There are a number of glitches in the doc-comments, especially @param directives, like name mismatches and empty descriptions. They're flagged as warnings by Doxygen, and by Clang if -Wdocumentation is on.

Not a big deal, except that the project I work on builds with -Wdocumentation -Werror (because it's a library with its own API and doc-comments), so when I include sockpp headers they break the build.

I can work around this by wrapping all the includes with #pragma clang diagnostic push / ignored / pop, but it's a pain and it'd be nice if these were cleaned up along with the other header-file work that's acknowledged in the README :)

I cannot get examples to compile on linux

Using: g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Examples: tcp echo client /server and unix echo client/server.
I consistently get errors with non- static reference made to run_echo().
when I comment out the call to run_echo(); I get undefined references
`sockpp::inet_address::inet_address(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&, unsigned short)':|

Windows broken build

Windows is now reporting:

...\sockpp\src\socket.cpp(192): error C3861: 'strerror_r': identifier not found [...\sockpp\build\src\sockpp-objs.vcxproj]

sys_error improperly declared; not caught as std::exception

One of my tests keeps crashing with uncaught exception of type sockpp::sys_error. The exception is expected (the test tries to connect to a nonexistent hostname) but my catch(const std::exception &x) { ... } is being ignored.

I finally realized the problem: sys_error is not compatible with type std::exception because it doesn't publicly inherit from it. Its declaration needs to be changed to

class sys_error : public std::runtime_error

i.e. adding public after the colon.

With this fix, my test works as expected.

Reasons for implementing `sock_address_ref`

First off, thanks for writing sockcpp! It's almost exactly what I was looking for in a modernized C++ sockets library.

I've been digging through the code, and I'm confused about why you've preferred to implement and use sock_address_refover using C++ references to sock_address.

Non-blocking I/O

It would be useful to support non-blocking I/O on sockets, and non-blocking connect and accept. This allows a lot more flexibility with threading, instead of having to devote one or two threads to every socket. It also seems like the only way to control the timeout of connect.

I've implemented this and will try to put a PR together today.

Setting read timeout fails (Bad file descriptor)

I tried to set the read timeout using read_timeout function in stream_socket.h but it failed. I got "Bad file descriptor" error message.
Is there a way to set the timeout or changing the default timout if that's possible ?

Compile with MinGW-64 (G++)

Hi fpagliughi,

Would you happen to know how to compile a sockpp included CPP file properly with G++? I've tried many including:
g++ main.cpp -o main -I "sockpp/include/" -L "sockpp/build/Debug/sockpp-static.lib"

Including both the path and the linker file location. The program compiles properly when I have the actual include statement (example: #include <sockpp/tcp_connector.h>) only - but when trying to add a TCP connector (example: sockpp::tcp_connector conn({"localhost", 12345});) - it fails to compile.

Get unit tests working on all platforms.

I was able to make it compile and run. The hardest part, actually, was fighting with CMake since Catch2 is not something I normally "install" since it's just one (or two) headers. Some CMake patching took care of that though, and the only thing left is the following issues (on Windows) in the unit tests causing 7 test and 8 assertion failures:

  • Incorrect assumption: Address information is available before socket connection (family type will remain unspecified, as opposed to the various checks for AF_INET)
  • Incorrect assumption: Windows uses POSIX error codes (e.g. sock.last_error() == EAFNOSUPPORT needs to be sock.last_error() == WSAEAFNOSUPPORT). Also, often these codes are WSAEINVAL or WSAENOTSOCK instead.
  • socket::pair not implemented for Windows, so its corresponding test fails
  • to_timeval is not implemented on Windows, causing compilation failures

All of the above are pretty easily fixable though.

EDIT OH I forgot, initialize() is never called during the tests so a lot of tests initially failed with the "not initialized" error. I fixed that by not auto generating the catch main function (GOTCHA: Include socket platform.h before catch.hpp to avoid odd errors from including headers in the wrong order)

Originally posted by @borrrden in #25 (comment)

The cmake doesn't generate config file to be included as a 3th party project

I am developing a library, which uses come 3rd party libraries including this one. For the other libraries, I was able to include them using the following CMakeLists.txt code:

find_package(package_name REQUIRED)
target_link_libraries(my_target_name PRIVATE package_name::package_name)

but for this one, it says the following:

Could not find a package configuration file provided by "sockpp-static" with any of the following names:
sockpp-staticConfig.cmake
sockpp-static-config.cmake

error LNK2001

  1. git clone https://github.com/fpagliughi/sockpp
  2. run Visual Studio 2019 Developer Command Prompt v16.5.4
  3. cd sockpp && mkdir build && cd build
  4. run cmake

cmake .. -G"NMake Makefiles" -DSOCKPP_BUILD_STATIC=SOCKPP_BUILD_STATIC -DCMAKE_CXX_FLAGS_RELEASE=/MT -DCMAKE_BUILD_TYPE=Release

  1. build examples/tcp/tcpecho.cpp
1>main.obj : error LNK2001: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __stdcall sockpp::operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class sockpp::inet_address const &)" (??6sockpp@@YGAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV12@ABVinet_address@0@@Z)
1>main.obj : error LNK2001: unresolved external symbol "public: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __stdcall sockpp::socket::error_str(int)" (?error_str@socket@sockpp@@SG?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z)
1>main.obj : error LNK2001: unresolved external symbol "public: static void __stdcall sockpp::socket::destroy(void)" (?destroy@socket@sockpp@@SGXXZ)
1>main.obj : error LNK2001: unresolved external symbol "public: static void __stdcall sockpp::socket::initialize(void)" (?initialize@socket@sockpp@@SGXXZ)

EINTR and interrupted system calls

A characteristic of earlier UNIX systems was that if a process caught a singal while the process was blocked in a "slow" system call, the system call was interrupted. The system call returned an error and errno was set to EINTR. ... The problem with interrupted system calls is that we now have to handle the error return explicitly.

โ€”Stevens & Rago, Advanced Programming In The UNIX Environment, 3rd ed., sec. 10.5

This is annoying because you have to wrap some calls in a do...while loop, and confusing because the behavior has changed over time, is different on different platforms, and there are workarounds to make it less annoying that don't (to me) seem to help.

It appears that the calls used by sockpp that are affected are connect, accept, send, recv. The man pages for these all list EINTR among the possible errors. All these need to be wrapped like:

int result;
do {
    result = SYSTEMCALL();
} while (result < 0 && last_error_code() == EINTR);

I have no idea whether any of this applies to Windows. I don't think Windows even has the notion of "signals" in the same sense as Unix. (@borrrden ?)

Receiving Big Data

Hi, I'm just wondering but is there any mechanism in this repository that can simply be able to receive data from another endpoint without knowing the length of it and be able to receive it all properly? For example, if I send an image on the server side to the client, is there any way I can receive the full image which one simple line to store it all in an array without sending the length of the data first then the actual data?

CMake option for no install

Hi,
I am developing a project and I want to use your library. I manage my dependencies as git submodules and add them with add_subdirectory. I want it to be built with the rest of my code using my configuration etc.
Would it be possible to add such an option to CMake?
Or add check:
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
add decide to install based on that.

socket.is_connected not working

Hi,
I've been trying to check if my socket that I have connected to a server is active in which it obviously is because I am able to send data back and forth, but is there any way I can check because I've been trying to use "socket.is_connected()" but it seems to be returning the same value no matter if it is connected or not. Currently using TCP sockets.

Error LNK2019

Hi guys,

I created a C++ project with VS 2019 and related head files and a library are added to the project. Unfortunately, it is unable to build successfully. Are there some critical steps I've overlooked?

1667915884206

building with mingw32 g++ on Windows 10

C:\For_CMake\source\sockpp-0.7.1\src\inet_address.cpp: In member function 'std::__cxx11::string sockpp::inet_address::to_string() const':
C:\For_CMake\source\sockpp-0.7.1\src\inet_address.cpp:107:13: error: 'inet_ntop' was not declared in this scope
  auto str = inet_ntop(AF_INET, (void*) &(addr_.sin_addr), buf, INET_ADDRSTRLEN);
             ^~~~~~~~~
C:\For_CMake\source\sockpp-0.7.1\src\inet_address.cpp:107:13: note: suggested alternative: 'inet_ntoa'
  auto str = inet_ntop(AF_INET, (void*) &(addr_.sin_addr), buf, INET_ADDRSTRLEN);
             ^~~~~~~~~
             inet_ntoa
C:\For_CMake\source\sockpp-0.7.1\src\inet_address.cpp: In function 'std::ostream& sockpp::operator<<(std::ostream&, const sockpp::inet_address&)':
C:\For_CMake\source\sockpp-0.7.1\src\inet_address.cpp:117:13: error: 'inet_ntop' was not declared in this scope
  auto str = inet_ntop(AF_INET, (void*) &(addr.sockaddr_in_ptr()->sin_addr),
             ^~~~~~~~~
C:\For_CMake\source\sockpp-0.7.1\src\inet_address.cpp:117:13: note: suggested alternative: 'inet_ntoa'
  auto str = inet_ntop(AF_INET, (void*) &(addr.sockaddr_in_ptr()->sin_addr),
             ^~~~~~~~~
             inet_ntoa
mingw32-make[2]: *** [src\CMakeFiles\sockpp-objs.dir\build.make:138: src/CMakeFiles/sockpp-objs.dir/inet_address.cpp.obj] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:141: src/CMakeFiles/sockpp-objs.dir/all] Error 2
mingw32-make: *** [Makefile:148: all] Error 2

Error in cross-compiling for SH4 Linux

When I try to cross-compile for use on an SH4 Linux system, I get a compile error.

After configuring with cmake as follows :

$ cmake -Bbuild -DSOCKPP_BUILD_SHARED=OFF -DSOCKPP_BUILD_STATIC=ON -DCMAKE_CXX_COMPILER="sh4-linux-g++" -DCMAKE_CXX_FLAGS="-Os -Wno-missing-field-intializers -DSO_REUSEPORT=2"
-- The C compiler identification is GNU 10.3.0
-- The CXX compiler identification is GNU 10.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /work/buildroot/output/host/usr/bin/sh4-linux-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /work/buildroot/output/host/usr/bin/sh4-linux-g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Creating static library: sockpp-static
-- Configuring done
-- Generating done
-- Build files have been written to: /home/habu/sockpp/build

The following error message appears when performing a build.

[ 10%] Building CXX object src/CMakeFiles/sockpp-objs.dir/acceptor.cpp.o
In file included from /home/habu/sockpp/include/sockpp/stream_socket.h:50,
                 from /home/habu/sockpp/include/sockpp/acceptor.h:49,
                 from /home/habu/sockpp/src/acceptor.cpp:38:
/home/habu/sockpp/include/sockpp/socket.h:70:1: error: 'timeval' does not name a type
   70 | timeval to_timeval(const std::chrono::microseconds& dur);
      | ^~~~~~~
/home/habu/sockpp/include/sockpp/socket.h:78:1: error: 'timeval' does not name a type
   78 | timeval to_timeval(const std::chrono::duration<Rep,Period>& dur) {
      | ^~~~~~~
/home/habu/sockpp/include/sockpp/socket.h:87:52: error: 'timeval' does not name a type
   87 | inline std::chrono::microseconds to_duration(const timeval& tv)
      |                                                    ^~~~~~~
/home/habu/sockpp/include/sockpp/socket.h: In function 'std::chrono::microseconds sockpp::to_duration(const int&)':
/home/habu/sockpp/include/sockpp/socket.h:89:40: error: request for member 'tv_sec' in 'tv', which is of non-class type 'const int'
   89 |     auto dur = std::chrono::seconds{tv.tv_sec}
      |                                        ^~~~~~
/home/habu/sockpp/include/sockpp/socket.h:89:46: error: no matching function for call to 'std::chrono::duration<long long int>::duration(<brace-enclosed initializer list>)'
   89 |     auto dur = std::chrono::seconds{tv.tv_sec}
      |                                              ^
In file included from /home/habu/sockpp/include/sockpp/socket.h:51,
                 from /home/habu/sockpp/include/sockpp/stream_socket.h:50,
                 from /home/habu/sockpp/include/sockpp/acceptor.h:49,
                 from /home/habu/sockpp/src/acceptor.cpp:38:
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:478:14: note: candidate: 'template<class _Rep2, class _Period2, class> constexpr std::chrono::duration<_Rep, _Period>::duration(const std::chrono::duration<_Rep, _Period>&) [with _Rep2 = _Rep2; _Period2 = _Period2; <template-parameter-2-3> = <template-parameter-1-3>; _Rep = long long int; _Period = std::ratio<1>]'
  478 |    constexpr duration(const duration<_Rep2, _Period2>& __d)
      |              ^~~~~~~~
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:478:14: note:   template argument deduction/substitution failed:
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:470:23: note: candidate: 'template<class _Rep2, class> constexpr std::chrono::duration<_Rep, _Period>::duration(const _Rep2&) [with _Rep2 = _Rep2; <template-parameter-2-2> = <template-parameter-1-2>; _Rep = long long int; _Period = std::ratio<1>]'
  470 |    constexpr explicit duration(const _Rep2& __rep)
      |                       ^~~~~~~~
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:470:23: note:   template argument deduction/substitution failed:
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:463:2: note: candidate: 'constexpr std::chrono::duration<_Rep, _Period>::duration(const std::chrono::duration<_Rep, _Period>&) [with _Rep = long long int; _Period = std::ratio<1>]'
  463 |  duration(const duration&) = default;
      |  ^~~~~~~~
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:463:2: note:   conversion of argument 1 would be ill-formed:
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:461:12: note: candidate: 'std::chrono::duration<_Rep, _Period>::duration() [with _Rep = long long int; _Period = std::ratio<1>]'
  461 |  constexpr duration() = default;
      |            ^~~~~~~~
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:461:12: note:   candidate expects 0 arguments, 1 provided
In file included from /home/habu/sockpp/include/sockpp/stream_socket.h:50,
                 from /home/habu/sockpp/include/sockpp/acceptor.h:49,
                 from /home/habu/sockpp/src/acceptor.cpp:38:
/home/habu/sockpp/include/sockpp/socket.h:90:36: error: request for member 'tv_usec' in 'tv', which is of non-class type 'const int'
   90 |     + std::chrono::microseconds{tv.tv_usec};
      |                                    ^~~~~~~
/home/habu/sockpp/include/sockpp/socket.h:90:43: error: no matching function for call to 'std::chrono::duration<long long int, std::ratio<1, 1000000> >::duration(<brace-enclosed initializer list>)'
   90 |     + std::chrono::microseconds{tv.tv_usec};
      |                                           ^
In file included from /home/habu/sockpp/include/sockpp/socket.h:51,
                 from /home/habu/sockpp/include/sockpp/stream_socket.h:50,
                 from /home/habu/sockpp/include/sockpp/acceptor.h:49,
                 from /home/habu/sockpp/src/acceptor.cpp:38:
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:478:14: note: candidate: 'template<class _Rep2, class _Period2, class> constexpr std::chrono::duration<_Rep, _Period>::duration(const std::chrono::duration<_Rep, _Period>&) [with _Rep2 = _Rep2; _Period2 = _Period2; <template-parameter-2-3> = <template-parameter-1-3>; _Rep = long long int; _Period = std::ratio<1, 1000000>]'
  478 |    constexpr duration(const duration<_Rep2, _Period2>& __d)
      |              ^~~~~~~~
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:478:14: note:   template argument deduction/substitution failed:
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:470:23: note: candidate: 'template<class _Rep2, class> constexpr std::chrono::duration<_Rep, _Period>::duration(const _Rep2&) [with _Rep2 = _Rep2; <template-parameter-2-2> = <template-parameter-1-2>; _Rep = long long int; _Period = std::ratio<1, 1000000>]'
  470 |    constexpr explicit duration(const _Rep2& __rep)
      |                       ^~~~~~~~
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:470:23: note:   template argument deduction/substitution failed:
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:463:2: note: candidate: 'constexpr std::chrono::duration<_Rep, _Period>::duration(const std::chrono::duration<_Rep, _Period>&) [with _Rep = long long int; _Period = std::ratio<1, 1000000>]'
  463 |  duration(const duration&) = default;
      |  ^~~~~~~~
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:463:2: note:   conversion of argument 1 would be ill-formed:
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:461:12: note: candidate: 'std::chrono::duration<_Rep, _Period>::duration() [with _Rep = long long int; _Period = std::ratio<1, 1000000>]'
  461 |  constexpr duration() = default;
      |            ^~~~~~~~
/mnt/wsl/work/buildroot/output/host/opt/ext-toolchain/sh4-buildroot-linux-musl/include/c++/10.3.0/chrono:461:12: note:   candidate expects 0 arguments, 1 provided
In file included from /home/habu/sockpp/include/sockpp/stream_socket.h:50,
                 from /home/habu/sockpp/include/sockpp/acceptor.h:49,
                 from /home/habu/sockpp/src/acceptor.cpp:38:
/home/habu/sockpp/include/sockpp/socket.h: At global scope:
/home/habu/sockpp/include/sockpp/socket.h:99:65: error: 'timeval' does not name a type
   99 | inline std::chrono::system_clock::time_point to_timepoint(const timeval& tv)
      |                                                                 ^~~~~~~
cc1plus: note: unrecognized command-line option '-Wno-missing-field-intializers' may have been intended to silence earlier diagnostics
gmake[2]: *** [src/CMakeFiles/sockpp-objs.dir/build.make:76: src/CMakeFiles/sockpp-objs.dir/acceptor.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:126: src/CMakeFiles/sockpp-objs.dir/all] Error 2
gmake: *** [Makefile:136: all] Error 2

According to the error, the definition of the timeval type seems to be missing, so adding the following sys/time.h include near the beginning of include/sockpp/socket.h will enable compilation.

#include "sockpp/sock_address.h"
#include <sys/time.h> // <-- add
#include <chrono>
#include <string>
#include <tuple>

This should solve the problem on Linux-based systems, but I am not sure if this is a reasonable solution on non-Linux systems.

GNU Make deprecated

The GNU Makefiles are broken and will be removed in favor of the CMake build.

Issue while building

I have getting below error while building your library
build/Debug/GNU-Linux/NativeTCP.o:(.data.rel.ro._ZTVN6sockpp13tcp_connectorE[_ZTVN6sockpp13tcp_connectorE]+0x20): undefined reference to `sockpp::stream_socket::read(void*, unsigned long)'

Can this library be compiled for IOS?

I want to use CMake to compile this library for IOS, but I tried and got errors. Can I implement that?
`
Creating symlinks
/Applications/CMake.app/Contents/bin/cmake -E cmake_symlink_library /Users/wujiahang/Project/EdgeTileIOS/deps/build/sockpp/Release-iphoneos/libsockpp.0.7.0.dylib /Users/wujiahang/Project/EdgeTileIOS/deps/build/sockpp/Release-iphoneos/libsockpp.0.dylib /Users/wujiahang/Project/EdgeTileIOS/deps/build/sockpp/Release-iphoneos/libsockpp.dylib
CMake Error: failed to create symbolic link '/Users/wujiahang/Project/EdgeTileIOS/deps/build/sockpp/Release-iphoneos/libsockpp.0.dylib': no such file or directory
CMake Error: cmake_symlink_library: System Error: No such file or directory
CMake Error: failed to create symbolic link '/Users/wujiahang/Project/EdgeTileIOS/deps/build/sockpp/Release-iphoneos/libsockpp.dylib': no such file or directory
CMake Error: cmake_symlink_library: System Error: No such file or directory
make: *** [sockpp_buildpart_0] Error 1

** BUILD FAILED **
`

Simultaneous TCP connections automatically closes

@fpagliughi

Thank you for building this awesome library. I'm seeing this weird issue where if we start Simultaneous 2 TCP connections to the server, the sever issue RSTs and close the TCP connections, but this doesn't happen if we open like more than 2 simultaneous TCP connections at same time.

I'm using Ubuntu OS. I observe the same issue on the evpp library, but I don't think this is library specific.

I did compile with these flags too

-Wpedantic -Wthread-safety -Wall -Wextra -g -fsanitize=undefined -fsanitize=address -fsanitize=leak

But they detected nothing, and so is Valgrind

The following NodeJS script is used to send Simultaneous TCP connections. You don't need to write a HTTP server stack to test this, just the usual TCP code with do nothing while loop to keep socket from destructuring. I'm using 5 threads in the C++ server.

const request = require('request-promise');

async function main() {
    try {
        // 2 requests at same time fails
        const urls = [
            "https://YOUR_IP:PORT",
            "https://YOUR_IP:PORT",
        ]

        const requests = [];

        for(const url of urls) {
            requests.push(request.get(url));
        }

        let res = await Promise.race(requests);

    } catch (e) {
        console.log(e);
    }
}

main();

Please do let me know if you need the threaded wrapper that I wrote around your low level lib.

Question about `close(2)` in destructor

Hello!

I was attempting to roll my own socket library before I discovered sockpp (which is excellent, btw). One thing that stumped me in my own design was how to handle the case where close(2) is called from within a destructor, but returns an error.

I see below that you opted not to handle a bad response from close:

close(h);

Do you think such a response is unlikely, or not applicable with this kind of file descriptor? Or do you expect that users would have a way to know within their application that close failed? The situation described in the (macOS) man page is that close could return an error if there were unreported problems with the previous write(2), but I have not been able to trigger that in practice.

Thank you for clarifying, I was super stumped by this one.

Invalid handling of unix paths with maximum length

The definition of the struct

struct sockaddr_un
  {
    __SOCKADDR_COMMON (sun_);
    char sun_path[108];		/* Path name.  */
  };

Allows a path with up to 108 characters. If all chars are used, there is no null termination. So all accessors of this path should check for the size:

--- a/sockpp/include/sockpp/unix_address.h
+++ b/sockpp/include/sockpp/unix_address.h
@@ -125,7 +125,7 @@ public:
 	 * Gets the path to which this address refers.
 	 * @return The path to which this address refers.
 	 */
-	std::string path() const { return std::string(addr_.sun_path); }
+	std::string path() const { return std::string(addr_.sun_path, strnlen(addr_.sun_path, MAX_PATH_NAME)); }
 	/**
 	 * Gets the size of the address structure.
 	 * Note: In this implementation, this should return sizeof(this) but
@@ -170,7 +170,7 @@ public:
 	 *  	   "unix:<path>"
 	 */
 	std::string to_string() const {
-		return std::string("unix:") + std::string(addr_.sun_path);
+		return std::string("unix:") + path();
 	}
 };
 
--- a/sockpp/tests/unit/test_unix_address.cpp
+++ b/sockpp/tests/unit/test_unix_address.cpp
@@ -65,8 +65,8 @@ TEST_CASE("unix_address path constructor", "[address]") {
 
     // Check the low-level struct
     REQUIRE(AF_UNIX == addr.sockaddr_un_ptr()->sun_family);
-    REQUIRE(0 == strcmp(PATH.c_str(),
-                        (const char*) &addr.sockaddr_un_ptr()->sun_path));
+    REQUIRE(0 == strncmp(PATH.c_str(),
+                        (const char*) &addr.sockaddr_un_ptr()->sun_path, MAX_PATH_NAME));
 
     SECTION("copy constructor") {
         unix_address addr2(addr);
@@ -77,8 +77,8 @@ TEST_CASE("unix_address path constructor", "[address]") {
 
         // Check the low-level struct
         REQUIRE(AF_UNIX == addr2.sockaddr_un_ptr()->sun_family);
-        REQUIRE(0 == strcmp(PATH.c_str(),
-                            (const char*) &addr2.sockaddr_un_ptr()->sun_path));
+        REQUIRE(0 == strncmp(PATH.c_str(),
+                            (const char*) &addr2.sockaddr_un_ptr()->sun_path, MAX_PATH_NAME));
     }
 
     SECTION("sockaddr conversions") {
@@ -91,15 +91,15 @@ TEST_CASE("unix_address path constructor", "[address]") {
 
         // Check the low-level struct
         REQUIRE(AF_UNIX == addr2.sockaddr_un_ptr()->sun_family);
-        REQUIRE(0 == strcmp(PATH.c_str(),
-                            (const char*) &(addr2.sockaddr_un_ptr()->sun_path)));
+        REQUIRE(0 == strncmp(PATH.c_str(),
+                            (const char*) &(addr2.sockaddr_un_ptr()->sun_path, MAX_PATH_NAME)));
     }
 }
 
 TEST_CASE("unix_address sockaddr_un constructor", "[address]") {
     sockaddr_un unaddr;
     unaddr.sun_family = AF_UNIX;
-    strcpy(unaddr.sun_path, PATH.c_str());
+    strncpy(unaddr.sun_path, PATH.c_str(), MAX_PATH_NAME);
 
     unix_address addr(unaddr);
 
@@ -109,8 +109,8 @@ TEST_CASE("unix_address sockaddr_un constructor", "[address]") {
 
     // Check the low-level struct
     REQUIRE(AF_UNIX == addr.sockaddr_un_ptr()->sun_family);
-    REQUIRE(0 == strcmp(PATH.c_str(),
-                        (const char*) &addr.sockaddr_un_ptr()->sun_path));
+    REQUIRE(0 == strncmp(PATH.c_str(),
+                        (const char*) &addr.sockaddr_un_ptr()->sun_path, MAX_PATH_NAME));
 
 	// TODO: Restore this when all address checks in place
 	/*

Windows build warnings

These warnings are generated on the Windows build...

inet_address.cpp(72): warning C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
inet_address.cpp(101): warning C4996: 'inet_ntoa': Use inet_ntop() or InetNtop() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
inet_address.h(224): warning C4996: 'inet_ntoa': Use inet_ntop() or InetNtop() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings

exception.cpp(53): warning C4996: 'strerror': This function or variable may be unsafe. Consider using strerror_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

socket.cpp(114): warning C4996: 'WSADuplicateSocketA': Use WSADuplicateSocketW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
socket.cpp(115): warning C4996: 'WSASocketA': Use WSASocketW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings

datagram_socket.obj : warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library

last_error property is not thread-safe

The implementation of the socket class's last_error property is not thread-safe. The error code is copied from errno into a member variable after a system call. However, the error really needs to be tracked per thread, as errno itself is.

This is significant because it's not uncommon to have one thread writing to a socket and another thread reading from it โ€” this is a typical way to implement WebSockets, for example. What can happen in this case is:

  1. Thread A calls write.
  2. The underlying send system call fails, and the error is copied from errno into the socket's lastErr_.
  3. Thread B calls read.
  4. The underlying recv system call succeeds, so lastErr_ is set to 0.
  5. Thread A sees that the write call returned -1, and calls get_last_error.
  6. get_last_error returns 0, not the actual error from the write.

Error code from getaddrinfo is lost

In inet_address.cpp:

    if (::getaddrinfo(saddr.c_str(), NULL, &hints, &res) != 0)
        throw sys_error();

getaddrinfo doesn't set errno; it returns an error code instead. So this results in throwing a sys_err with a code of zero, which isn't useful.

Worse, these error codes aren't errno values, they're a different numbering system declared in netdb.h, like EAI_NONAME (8), so putting the error code in the sys_error would be a mistake.

Best solution is probably to create a getaddrinfo_error exception class and throw that...

Some examples won't compile on Windows (VS2015 with update3)

Hello.
I ran into a couple of issues trying to build examples with MSVS2015 update3 on Windows:

  1. Error in the tcpechotest.cpp:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\random(2387): error C2338: invalid template argument for uniform_int_distribution
F:\dump\sockpp\examples\tcp\tcpechotest.cpp(92): note: see reference to class template instantiation 'std::uniform_int_distribution<char>' being compiled

This is because the template parameter of std::uniform_int_distribution must be either: int, short, long, long long or their unsigned counterpart. Please see Template parameters section here: std::uniform_int_distribution

  1. Error in the udpechosvr.cpp:
F:\dump\sockpp\examples\udp\udpechosvr.cpp(75): error C2666: 'sockpp::datagram_socket_tmpl<sockpp::inet_address>::send_to': 2 overloads have similar conversions
F:\dump\sockpp\include\sockpp/datagram_socket.h(355): note: could be 'ssize_t sockpp::datagram_socket_tmpl<sockpp::inet_address>::send_to(const void *,std::size_t,const ADDR &)'
<...>
F:\dump\sockpp\include\sockpp/datagram_socket.h(345): note: or       'ssize_t sockpp::datagram_socket_tmpl<sockpp::inet_address>::send_to(const std::string &,int,const ADDR &)'

You can see the full error text for the 2nd issue here: https://gist.github.com/tsilia/6c9959ad0393a211970160c598a7cd41

Unix-Domain sockets on Windows 10

I recently stumbled on a Microsoft blog claiming that some version of Windows 10 now supports Unix-domain sockets:
https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/

I have no experience with it, nor do I have access to a PC with a recent version of Windows 10. But if anyone has tried this and/or sees a desire for it, I don't think it would be too difficult to implement. Maybe we could create a CMake option for SOCKPP_BUILD_AF_UNIX, or something like that, and have it default true on Linux and false on Windows.

android build error: sockpp exception - no matching conversion for functional-style cast

When building for Android targets, I've encountered the following error:

/workspace/myproject/third-party/sockpp/src/exception.cpp:70:15: error: no matching conversion for functional-style cast from 'int' to 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')
                        return s ? std::string(s) : std::string();

I'll look into an actual resolution and submit a PR if the fix isn't immediately obvious, but was able to get around it by commenting it out, and the rest of the library built fine.

Definition of ssize_t is wrong

sockpp has its own declaration of ssize_t in platform.h, but on non-Windows systems it defines it as int. This is wrong on 64-bit OSs that use 32-bit ints, which includes all Apple platforms. (Dunno about Linux or BSD.) This leads to compile errors if a source file ends up including both platform.h and the OS's declaration. That aside, there are potentially actual integer overflow bugs if dealing with sizes > 4GB.

#ifndef _SSIZE_T_DEFINED
#define _SSIZE_T_DEFINED
#undef ssize_t
#ifdef _WIN64
using ssize_t = int64_t;
#else
using ssize_t = int;
#endif // _WIN64
#endif // _SSIZE_T_DEFINED

You shouldn't need to declare this at all. Instead:

  • On a POSIX-compliant OS, #include <sys/types.h>.
  • On Windows, #include <BaseTsd.h> and then using ssize_t = SSIZE_T;.

(Also, it's kind of icky that the types declared in platform.h are all in the global namespace. Could they be put in the sockpp namespace like the rest of the API?)

Make exceptions optional

It would be great if this library could be used without exceptions. There are many environments where exceptions are not allowed.

Receiving Data

Hi, I'm just wondering but is there any mechanism in this repository that can simply be able to receive data from another endpoint without knowing the length of it and be able to receive it all properly? For example, if I send an image on the server side to the client, is there any way I can receive the full image which one simple line to store it all in an array without sending the length of the data first then the actual data?

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.