Skip to content

Commit 57b37ab

Browse files
authored
Merge pull request #2 from lpcvoid/windows_support
add windows support and new CI target
2 parents b43547c + 61d8843 commit 57b37ab

File tree

9 files changed

+67
-49
lines changed

9 files changed

+67
-49
lines changed

.github/workflows/test_matrix.yml

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ jobs:
1313
fail-fast: false
1414
matrix:
1515
config:
16-
# - {
17-
# name: "Windows MSVC",
18-
# os: windows-latest,
19-
# build_type: "Release", cc: "cl", cxx: "cl",
20-
# environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat"
21-
# }
16+
- {
17+
name: "Windows MSVC",
18+
os: windows-latest,
19+
build_type: "Release", cc: "cl", cxx: "cl",
20+
#this path will change at some point when VC2022 is released I guess
21+
environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat"
22+
}
2223
- {
2324
name: "Ubuntu gcc",
2425
os: ubuntu-latest,
@@ -45,6 +46,12 @@ jobs:
4546
- name: Build
4647
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
4748

48-
- name: Test
49+
- name: Test on Windows
50+
if: startsWith(matrix.config.os, 'windows')
51+
working-directory: ${{github.workspace}}/build
52+
run: tests/${{env.BUILD_TYPE}}/test_libnetcpp.exe
53+
54+
- name: Test on Linux/MacOS
55+
if: (!startsWith(matrix.config.os, 'windows'))
4956
working-directory: ${{github.workspace}}/build
50-
run: tests/test_libnetcpp
57+
run: tests/test_libnetcpp

examples/daytime_client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ int main(int argc, char** argv) {
2424
std::cout << "Connecting to " << time_host << " on port " << port << std::endl;
2525
netlib::client client;
2626

27-
std::error_condition client_create_res =
27+
std::error_condition client_create_res =
2828
client.connect(time_host, port, netlib::AddressFamily::IPv4,
2929
netlib::AddressProtocol::TCP, 1000ms);
3030

src/client.hpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace netlib {
2323
fd_set fdset;
2424
FD_ZERO(&fdset);
2525
FD_SET(sock, &fdset);
26-
timeval tv{.tv_sec = timeout.count() / 1000, .tv_usec=static_cast<int32_t>((timeout.count() % 1000) * 1000)};
26+
timeval tv{.tv_sec = static_cast<int32_t>(timeout.count() / 1000), .tv_usec=static_cast<int32_t>((timeout.count() % 1000) * 1000)};
2727
std::cout << "tv.tv_sec = " << tv.tv_sec << ", usec=" << tv.tv_usec << std::endl;
2828
fd_set* fdset_ptr_read = ((op_class == OperationClass::read) || (op_class == OperationClass::both)) ? &fdset : nullptr;
2929
fd_set* fdset_ptr_write = ((op_class == OperationClass::write) || (op_class == OperationClass::both)) ? &fdset : nullptr;
@@ -61,10 +61,13 @@ namespace netlib {
6161
}
6262

6363
public:
64-
client() = default;
64+
client(){
65+
netlib::socket::initialize_system();
66+
}
6567
client(netlib::socket sock, addrinfo* endpoint){
6668
_socket = sock;
6769
_endpoint_addr = endpoint;
70+
netlib::socket::initialize_system();
6871
}
6972
virtual ~client() {
7073
disconnect();
@@ -97,7 +100,9 @@ namespace netlib {
97100
int32_t connect_result = ::connect(sock.get_raw().value(), res_addrinfo->ai_addr, res_addrinfo->ai_addrlen);
98101
if (connect_result == -1) {
99102
std::error_condition error_condition = socket_get_last_error();
100-
if (error_condition != std::errc::operation_in_progress) {
103+
if ((error_condition != std::errc::operation_in_progress) &&
104+
(error_condition != std::errc::operation_would_block))
105+
{
101106
freeaddrinfo(addrinfo_result.first);
102107
return error_condition;
103108
}
@@ -153,10 +158,10 @@ namespace netlib {
153158
if (wait_res.first) {
154159
return {0, wait_res.first};
155160
}
156-
ssize_t send_res = ::send(_socket.value().get_raw().value(), data.data(), data.size(), 0);
161+
ssize_t send_res = ::send(_socket.value().get_raw().value(), reinterpret_cast<const char*>(data.data()), data.size(), 0);
157162
if (send_res >= 0) {
158163
if (send_res == data.size()) {
159-
return {send_res, {}};
164+
return {static_cast<std::size_t>(send_res), {}};
160165
}
161166
return {send_res, std::errc::message_size};
162167
}
@@ -188,7 +193,7 @@ namespace netlib {
188193
std::cout << "client recv after wait" << std::endl;
189194

190195
std::vector<uint8_t> data(byte_count, 0);
191-
ssize_t recv_res = ::recv(_socket.value().get_raw().value(), data.data(), byte_count, 0);
196+
ssize_t recv_res = ::recv(_socket.value().get_raw().value(), reinterpret_cast<char*>(data.data()), byte_count, 0);
192197
if (recv_res > 0) {
193198
std::cout << "client recv " << recv_res << std::endl;
194199
data.resize(recv_res);

src/endpoint_accessor.hpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
#pragma once
2-
#include <arpa/inet.h>
32
#include <array>
43
#include <cstring>
5-
#include <netdb.h>
6-
#include <netinet/in.h>
74
#include <optional>
85
#include <string>
9-
#include <sys/socket.h>
6+
#include "socket.hpp"
7+
108

119
namespace netlib {
1210
class endpoint_accessor {

src/server.hpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <iostream>
1010
#include <map>
1111
#include <mutex>
12+
#include <array>
1213
#include <optional>
1314
#include <thread>
1415
#include <utility>
@@ -69,6 +70,13 @@ namespace netlib {
6970
FD_SET(fd, &fdset);
7071
}
7172
}
73+
74+
//windows returns WSAEINVAL if we have nothing to pass to select, so we
75+
//need to filter this previously and elmulate the sleeping
76+
if (!highest_fd) {
77+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
78+
continue;
79+
}
7280
//we want the timeout to be fairly low, so that we avoid situations where
7381
//we have a new client in _clients, but are not monitoring it yet - that
7482
//would mean we have a "hardcoded" delay in servicing a new clients packets
@@ -119,14 +127,14 @@ namespace netlib {
119127
std::this_thread::sleep_for(std::chrono::milliseconds(10));
120128
new_endpoint.addr_len = sizeof(addrinfo);
121129
socket_t status = ::accept(_listener_sock->get_raw().value(), &new_endpoint.addr, &new_endpoint.addr_len);
122-
if (status > 0) {
130+
if (status != INVALID_SOCKET) {
123131
new_endpoint.socket.set_raw(status);
124132
new_endpoint.socket.set_nonblocking(true);
125133
if (_cb_onconnect) {
126134
netlib::server_response greeting = _cb_onconnect(new_endpoint);
127135
if (!greeting.answer.empty()) {
128136
ssize_t send_result = ::send(new_endpoint.socket.get_raw().value(),
129-
greeting.answer.data(),
137+
reinterpret_cast<const char*>(greeting.answer.data()),
130138
greeting.answer.size(),
131139
0);
132140
if ((send_result != greeting.answer.size()) && (_cb_on_error)) {
@@ -159,7 +167,7 @@ namespace netlib {
159167
ssize_t recv_res = 0;
160168
while (true) {
161169
recv_res = ::recv(endpoint.socket.get_raw().value(),
162-
buffer.data(), buffer.size(), 0);
170+
reinterpret_cast<char*>(buffer.data()), buffer.size(), 0);
163171
if (recv_res > 0) {
164172
total_buffer.insert(total_buffer.end(), buffer.begin(),
165173
buffer.begin() + recv_res);
@@ -180,7 +188,7 @@ namespace netlib {
180188
if (!response.answer.empty()) {
181189
ssize_t send_result = ::send(
182190
endpoint.socket.get_raw().value(),
183-
response.answer.data(), response.answer.size(), 0);
191+
reinterpret_cast<const char*>(response.answer.data()), response.answer.size(), 0);
184192
if (send_result != response.answer.size()) {
185193
return socket_get_last_error();
186194
}
@@ -217,7 +225,9 @@ namespace netlib {
217225
}
218226

219227
public:
220-
server() = default;
228+
server() {
229+
netlib::socket::initialize_system();
230+
}
221231
virtual ~server() { stop();
222232
}
223233
inline std::error_condition create(const std::string& bind_host,

src/service_resolver.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ namespace netlib {
3838
case EAI_ADDRFAMILY:
3939
#endif
4040
case EAI_NODATA:
41-
case EAI_NONAME:
4241
case EAI_FAIL: {
4342
return { nullptr, std::errc::network_unreachable};
4443
}

src/socket.hpp

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
#pragma comment(lib, "Ws2_32.lib")
1010
#pragma comment(lib, "AdvApi32.lib")
1111

12-
//headers
13-
#include <winsock2.h>
14-
#include <iphlpapi.h>
15-
#include <windows.h>
16-
#include <ws2tcpip.h>
17-
#include <stdint.h>
12+
//headers
13+
#include <WinSock2.h>
14+
#include <WS2tcpip.h>
15+
#include <Windows.h>
16+
#include <iphlpapi.h>
17+
#include <ws2tcpip.h>
18+
#include <stdint.h>
1819

1920
//defines
2021
using socket_t = SOCKET;
@@ -39,11 +40,13 @@ using socket_t = int32_t;
3940
namespace netlib {
4041

4142
static std::error_condition socket_get_last_error(){
43+
std::error_code ec;
4244
#ifdef _WIN32
43-
return std::make_error_condition(static_cast<std::errc>(WASGetLastError()));
45+
ec = std::error_code(::GetLastError(), std::system_category());
4446
#else
45-
return std::make_error_condition(static_cast<std::errc>(errno));
47+
ec = std::error_code(errno, std::system_category());
4648
#endif
49+
return ec.default_error_condition();
4750
}
4851

4952
enum class AddressFamily {IPv4 = AF_INET, IPv6 = AF_INET6, unspecified = AF_UNSPEC};
@@ -53,21 +56,20 @@ namespace netlib {
5356
class socket {
5457
private:
5558
std::optional<socket_t> _socket = std::nullopt;
59+
public:
60+
socket() = default;
5661

57-
static bool initialize_system() {
62+
static bool initialize_system() {
5863
#ifdef _WIN32
59-
static bool initialized = false;
60-
if (!initialized) {
61-
WSADATA wsaData;
62-
WSAStartup(MAKEWORD(2,2), &wsaData);
63-
initialized = true;
64-
}
65-
#else
66-
return true;
64+
static bool initialized = false;
65+
if (!initialized) {
66+
WSADATA wsaData;
67+
WSAStartup(MAKEWORD(2, 2), &wsaData);
68+
initialized = true;
69+
}
6770
#endif
68-
}
69-
public:
70-
socket() = default;
71+
return true;
72+
}
7173

7274
bool is_valid() {
7375
return _socket.has_value() && _socket.value() != INVALID_SOCKET;

src/thread_pool.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ namespace netlib {
8686
}
8787
//https://stackoverflow.com/a/31078143
8888
template <typename FUNCTION, typename... FUNCARGS>
89-
std::future<typename std::result_of<FUNCTION(FUNCARGS...)>::type>
90-
add_task(FUNCTION&& function, FUNCARGS&&... args) {
89+
auto add_task(FUNCTION&& function, FUNCARGS&&... args) {
9190
// first, check if we even have a free thread
9291
// if not, we add one up to a max allowed
9392
std::size_t free_threads = (get_thread_count() - get_task_count());

tests/test_client_server.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ TEST_CASE("Test server with callbacks") {
3131
bool client_was_connected = false;
3232
bool client_has_sent = false;
3333

34-
35-
3634
std::cout << "****Starting failing test" << std::endl;
3735

3836
server.register_callback_on_connect(

0 commit comments

Comments
 (0)