Skip to content

Commit ddee8ee

Browse files
committed
[mod] Windows build support
Signed-off-by: tsymiar <[email protected]>
1 parent e145744 commit ddee8ee

File tree

8 files changed

+150
-90
lines changed

8 files changed

+150
-90
lines changed

.github/workflows/cmake-multi-platform.yml

+5-3
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,19 @@ jobs:
2121
# 2. <Linux, Release, latest GCC compiler toolchain on the default runner image, default generator>
2222
# 3. <Linux, Release, latest Clang compiler toolchain on the default runner image, default generator>
2323
#
24-
# To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list.
2524
matrix:
26-
os: [ubuntu-latest]
25+
os: [ubuntu-latest, windows-latest]
2726
build_type: [Release]
28-
c_compiler: [gcc, clang]
2927
include:
3028
- os: ubuntu-latest
3129
c_compiler: gcc
3230
cpp_compiler: g++
3331
- os: ubuntu-latest
3432
c_compiler: clang
3533
cpp_compiler: clang++
34+
- os: windows-latest
35+
c_compiler: msvc
36+
cpp_compiler: msvc
3637

3738
steps:
3839
- uses: actions/checkout@v3
@@ -53,6 +54,7 @@ jobs:
5354
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
5455
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
5556
-S ${{ github.workspace }}
57+
${{ matrix.os == 'windows-latest' && '-A x64' || '' }}
5658
5759
- name: Build
5860
# Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).

src/scadup/Broker.cpp

100644100755
+73-48
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include "Scadup.h"
22

3+
#define LOG_TAG "Broker"
4+
#include "../utils/logging.h"
5+
36
#define XMK(x) #x
47
#define GET(x) XMK(x)
58

@@ -16,6 +19,30 @@ void signalCatch(int value)
1619
LOGI("caught signal: %d", value);
1720
}
1821

22+
bool Scadup::makeSocket(SOCKET& socket)
23+
{
24+
#ifdef _WIN32
25+
WSADATA wsaData;
26+
WORD version = MAKEWORD(2, 2);
27+
int wsResult = WSAStartup(version, &wsaData);
28+
if (wsResult != 0) {
29+
LOGE("WSAStartup fail: %s!", strerror(errno));
30+
return false;
31+
}
32+
#endif
33+
bool status = true;
34+
socket = ::socket(AF_INET, SOCK_STREAM, 0);
35+
if (socket <= 0) {
36+
LOGE("Generating socket fail(%s).",
37+
(errno != 0 ? strerror(errno) : std::to_string(socket).c_str()));
38+
#ifdef _WIN32
39+
WSACleanup();
40+
#endif
41+
status = false;
42+
}
43+
return status;
44+
}
45+
1946
ssize_t Scadup::writes(SOCKET socket, const uint8_t* data, size_t len)
2047
{
2148
if (data == nullptr || len == 0)
@@ -24,7 +51,7 @@ ssize_t Scadup::writes(SOCKET socket, const uint8_t* data, size_t len)
2451
return -1;
2552
std::mutex mtxLck = {};
2653
std::lock_guard<std::mutex> lock(mtxLck);
27-
ssize_t left = (ssize_t)len;
54+
auto left = (ssize_t)len;
2855
auto* buff = new(std::nothrow) uint8_t[left];
2956
if (buff == nullptr) {
3057
LOGE("Socket buffer malloc size %zu failed!", left);
@@ -57,31 +84,30 @@ ssize_t Scadup::writes(SOCKET socket, const uint8_t* data, size_t len)
5784

5885
int Scadup::connect(const char* ip, unsigned short port, unsigned int total)
5986
{
60-
SOCKET socket = ::socket(AF_INET, SOCK_STREAM, 0);
61-
if (socket < 0) {
62-
LOGE("Generating socket to connect(%s).",
63-
(errno != 0 ? strerror(errno) : std::to_string(socket).c_str()));
87+
SOCKET sock = -1;
88+
if (!makeSocket(sock)) {
89+
LOGE("Connect to make socket fail!");
6490
return -1;
6591
}
6692
sockaddr_in local{};
6793
local.sin_family = AF_INET;
6894
local.sin_port = htons(port);
6995
local.sin_addr.s_addr = inet_addr(ip);
70-
int flag = 1;
71-
setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(char));
96+
char flag = 1;
97+
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(char));
7298
LOGI("------ connecting to %s:%d ------", ip, port);
7399
unsigned int tries = 0;
74-
while (::connect(socket, reinterpret_cast<struct sockaddr*>(&local), sizeof(local)) == (-1)) {
100+
while (::connect(sock, reinterpret_cast<struct sockaddr*>(&local), sizeof(local)) == (-1)) {
75101
if (tries < total) {
76102
wait(Time100ms * (long)pow(2, tries));
77103
tries++;
78104
} else {
79105
LOGE("Retrying to connect (times=%d, %s).", tries, (errno != 0 ? strerror(errno) : "No error"));
80-
close(socket);
106+
Close(sock);
81107
return -2;
82108
}
83109
}
84-
return socket;
110+
return sock;
85111
}
86112

87113
SOCKET Scadup::socket2Broker(const char* ip, unsigned short port, uint64_t& ssid, uint32_t timeout)
@@ -92,19 +118,19 @@ SOCKET Scadup::socket2Broker(const char* ip, unsigned short port, uint64_t& ssid
92118
return -1;
93119
}
94120
Header head{};
95-
ssize_t size = ::recv(socket, &head, sizeof(head), 0);
121+
ssize_t size = ::recv(socket, reinterpret_cast<char*>(&head), sizeof(head), 0);
96122
if (size > 0) {
97123
if (head.size == sizeof(head) && head.flag == BROKER)
98124
ssid = head.ssid;
99125
else
100126
LOGW("Mismatch flag %s, size %u.", GET_FLAG(head.flag), head.size);
101127
} else {
102128
if (size == 0) {
103-
LOGE("Connection closed by peer, close %d", socket);
129+
LOGE("Connection closed by peer, close %d: %s", socket, strerror(errno));
104130
} else {
105131
LOGE("Recv fail(%ld), close %d: %s", size, socket, strerror(errno));
106132
}
107-
close(socket);
133+
Close(socket);
108134
return -3;
109135
}
110136
return socket;
@@ -120,10 +146,9 @@ int Broker::setup(unsigned short port)
120146
{
121147
signal(SIGPIPE, signalCatch);
122148

123-
SOCKET sock = ::socket(AF_INET, SOCK_STREAM, 0);
124-
if (sock < 0) {
125-
LOGE("Generating socket to setup(%s).",
126-
(errno != 0 ? strerror(errno) : std::to_string(sock).c_str()));
149+
SOCKET sock = -1;
150+
if (!makeSocket(sock)) {
151+
LOGE("Setup to make socket fail!");
127152
return -1;
128153
}
129154

@@ -134,15 +159,15 @@ int Broker::setup(unsigned short port)
134159
if (::bind(sock, reinterpret_cast<struct sockaddr*>(&local), sizeof(local)) < 0) {
135160
LOGE("Binding socket (%s).",
136161
(errno != 0 ? strerror(errno) : std::to_string(sock).c_str()));
137-
close(sock);
162+
Close(sock);
138163
return -2;
139164
}
140165

141166
const int backlog = 50;
142167
if (listen(sock, backlog) < 0) {
143168
LOGE("listening socket (%s).",
144169
(errno != 0 ? strerror(errno) : std::to_string(sock).c_str()));
145-
close(sock);
170+
Close(sock);
146171
return -3;
147172
}
148173

@@ -158,7 +183,7 @@ int Broker::setup(unsigned short port)
158183
check.detach();
159184
}
160185

161-
socklen_t size = static_cast<socklen_t>(sizeof(local));
186+
auto size = static_cast<socklen_t>(sizeof(local));
162187
getsockname(sock, reinterpret_cast<struct sockaddr*>(&local), &size);
163188
LOGI("listens localhost [%s:%d].", inet_ntoa(local.sin_addr), port);
164189

@@ -193,7 +218,7 @@ void Broker::taskAllot(Networks& works, const Network& work)
193218
{
194219
if (work.head.flag == PUBLISHER) {
195220
Header head{};
196-
ssize_t len = recv(work.socket, &head, sizeof(head), MSG_WAITALL);
221+
ssize_t len = recv(work.socket, reinterpret_cast<char*>(&head), sizeof(head), MSG_WAITALL);
197222
if (len == 0 || (len < 0 && errno == EPIPE)) {
198223
setOffline(works, work.socket);
199224
LOGW("Socket lost/closing by itself!");
@@ -212,7 +237,7 @@ void Broker::taskAllot(Networks& works, const Network& work)
212237
LOGI("start heart beat task");
213238
while (m_active) {
214239
Header head{};
215-
ssize_t len = ::recv(socket, &head, HEAD_SIZE, 0);
240+
ssize_t len = ::recv(socket, reinterpret_cast<char*>(&head), HEAD_SIZE, 0);
216241
if (len == 0 || (len < 0 && errno == EPIPE) || (len > 0 && head.cmd == 0xff)) {
217242
setOffline(works, socket);
218243
LOGW("Socket %d lost/closing by itself!", socket);
@@ -239,8 +264,8 @@ int Broker::ProxyTask(Networks& works, const Network& work)
239264
work.IP, work.PORT, work.head.size);
240265
const size_t sz1 = sizeof(Message::Payload::status);
241266
size_t left = work.head.size - HEAD_SIZE;
242-
static Message sval{};
243-
Message* msg = new(sval) Message;
267+
static Message mval{};
268+
auto* msg = new(mval) Message;
244269
msg->payload.content = new char[left - sz1];
245270
memset(msg->payload.content, 0, left - sz1);
246271
size_t len = 0;
@@ -250,7 +275,7 @@ int Broker::ProxyTask(Networks& works, const Network& work)
250275
ssize_t got = ::recv(work.socket, reinterpret_cast<char*>(payload + len), size, 0);
251276
if (got < 0) {
252277
if (errno != EAGAIN && errno != EWOULDBLOCK) {
253-
LOGE("Call recv failed: %s", strerror(errno));
278+
LOGE("Call recv(%d) failed: %s", got, strerror(errno));
254279
delete[] msg->payload.content;
255280
return -1;
256281
}
@@ -272,47 +297,47 @@ int Broker::ProxyTask(Networks& works, const Network& work)
272297
queue_push(&g_msgQue, msg);
273298
setOffline(works, work.socket);
274299
std::vector<Network>& vec = works[SUBSCRIBER];// only SUBSCRIBER should be sent
275-
if (vec.size() <= 0) {
300+
if (vec.empty()) {
276301
LOGW("No subscriber to publish!");
277302
}
278303
void* message = queue_front(&g_msgQue);
279304
if (message != nullptr) {
280-
Message msg = *reinterpret_cast<Message*>(message);
281-
if (msg.head.flag != PUBLISHER) {
282-
LOGW("Message invalid(%d), len=%u!", msg.head.flag, msg.head.size);
305+
Message val = *reinterpret_cast<Message*>(message);
306+
if (val.head.flag != PUBLISHER) {
307+
LOGW("Message invalid(%d), len=%u!", val.head.flag, val.head.size);
283308
return -1;
284309
}
285-
if (msg.head.size > 0) {
310+
if (val.head.size > 0) {
286311
for (auto& sub : vec) {
287312
if (sub.head.topic == work.head.topic) {
288313
if (sub.active && sub.socket > 0) {
289-
size_t left = work.head.size;
290-
size_t size = HEAD_SIZE + sz1;
291-
char* buff = (char*)&msg;
314+
left = work.head.size;
315+
size = HEAD_SIZE + sz1;
316+
char* buff = (char*)&val;
292317
do {
293-
size_t len = ::send(sub.socket, buff, size, MSG_NOSIGNAL);
294-
if (len == 0 || (len < 0 && errno == EPIPE)) {
318+
size_t sz = ::send(sub.socket, buff, size, MSG_NOSIGNAL);
319+
if (sz == 0 || (sz < 0 && errno == EPIPE)) {
295320
setOffline(works, sub.socket);
296-
LOGE("Write to sock[%d], size %u failed!", sub.socket, msg.head.size);
321+
LOGE("Write to sock[%d], size %u failed!", sub.socket, val.head.size);
297322
break;
298323
} else {
299-
if (len == HEAD_SIZE + sz1) {
324+
if (sz == HEAD_SIZE + sz1) {
300325
size = work.head.size - HEAD_SIZE - sz1;
301-
buff = msg.payload.content;
326+
buff = val.payload.content;
302327
}
303-
left -= len;
328+
left -= sz;
304329
}
305330
} while (left > 0);
306-
LOGI("writes message to subscriber[%s:%u], size %u!", sub.IP, sub.PORT, msg.head.size);
331+
LOGI("writes message to subscriber[%s:%u], size %u!", sub.IP, sub.PORT, val.head.size);
307332
} else {
308333
LOGW("No valid subscriber of topic %04x!", sub.head.topic);
309334
}
310335
}
311336
}
312-
Delete(msg.payload.content)
337+
Delete(val.payload.content)
313338
queue_pop(&g_msgQue);
314339
} else {
315-
LOGW("Message size(%u) invalid!", msg.head.size);
340+
LOGW("Message size(%u) invalid!", val.head.size);
316341
}
317342
} else {
318343
LOGW("MsgQue is null!");
@@ -329,7 +354,7 @@ void Broker::setOffline(Networks& works, SOCKET socket)
329354
if (wk.socket == socket) {
330355
wk.active = false;
331356
if (wk.socket > 0) {
332-
close(wk.socket);
357+
Close(wk.socket);
333358
wk.socket = 0;
334359
}
335360
LOGI("client %s:%u will delete later soon.", wk.IP, wk.PORT);
@@ -357,7 +382,7 @@ void Broker::checkAlive(Networks& works, bool* active)
357382
}
358383
}
359384
for (auto it = works.begin(); it != works.end(); ) {
360-
if (it->second.size() == 0) {
385+
if (it->second.empty()) {
361386
auto next = std::next(it);
362387
works.erase(it);
363388
it = next;
@@ -376,7 +401,7 @@ int Broker::broker()
376401
while (m_active) {
377402
FD_SET(m_socket, &fdset);
378403
timeval timeout = { 3, 0 };
379-
if (select((int)(m_socket + 1), &fdset, NULL, NULL, &timeout) > 0) {
404+
if (select((int)(m_socket + 1), &fdset, nullptr, nullptr, &timeout) > 0) {
380405
if (FD_ISSET(m_socket, &fdset)) {
381406
struct sockaddr_in peer { };
382407
auto socklen = static_cast<socklen_t>(sizeof(peer));
@@ -411,7 +436,7 @@ int Broker::broker()
411436
continue;
412437
}
413438
memset(&head, 0, sizeof(head));
414-
ssize_t size = recv(sockNew, &head, sizeof(head), MSG_PEEK);
439+
ssize_t size = recv(sockNew, reinterpret_cast<char*>(&head), sizeof(head), MSG_PEEK);
415440
if (size > 0 && ssid == head.ssid) {
416441
work.socket = sockNew;
417442
work.head = head;
@@ -429,7 +454,7 @@ int Broker::broker()
429454
} else {
430455
if (0 == size || errno == EINVAL || (size < 0 && errno != EAGAIN)) {
431456
LOGE("Recv fail(%ld), ssid=%llu, close %d: %s", size, head.ssid, sockNew, strerror(errno));
432-
close(sockNew);
457+
Close(sockNew);
433458
}
434459
}
435460
}
@@ -444,7 +469,7 @@ void Broker::exit()
444469
{
445470
m_active = false;
446471
if (m_socket > 0) {
447-
close(m_socket);
472+
Close(m_socket);
448473
m_socket = -1;
449474
}
450475
queue_deinit(&g_msgQue);

src/scadup/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ if (NOT WIN32)
66
if (NOT "${ANDROID}" EQUAL "1")
77
set(EXTERN pthread)
88
endif()
9+
else()
10+
set(EXTERN WS2_32)
911
endif()
1012
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall")
1113
#set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

src/scadup/Publisher.cpp

100644100755
+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include "Scadup.h"
22

3+
#define LOG_TAG "Publisher"
4+
#include "../utils/logging.h"
5+
36
using namespace Scadup;
47

58
void Publisher::setup(const char* ip, unsigned short port)
@@ -22,7 +25,7 @@ ssize_t Publisher::broadcast(const uint8_t* data, size_t len)
2225
LOGE("Writes %d: %s", bytes, strerror(errno));
2326
return -3;
2427
}
25-
close(m_socket);
28+
Close(m_socket);
2629
return bytes;
2730
}
2831

0 commit comments

Comments
 (0)