22 * @brief JSON-RPC implementation for TCP/IP stack with POSIX calls.
33 * @author Ashot Vardanian
44 */
5+
6+ #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
7+ #define UCALL_IS_WINDOWS
8+
9+ #include < Ws2tcpip.h>
10+ #include < io.h>
11+ #include < winsock2.h>
12+
13+ #define SHUT_WR SD_SEND
14+ #define SHUT_RD SD_RECEIVE
15+ #define SHUT_RDWR SD_BOTH
16+ // SO_REUSEPORT is not supported on Windows.
17+ #define SO_REUSEPORT 0
18+
19+ #pragma comment(lib, "Ws2_32.lib")
20+ #define UNICODE
21+
22+ #else
523#include < arpa/inet.h> // `inet_addr`
6- #include < errno.h> // `strerror`
7- #include < fcntl.h> // `fcntl`
824#include < netinet/in.h> // `sockaddr_in`
9- # include < stdlib.h > // `std::aligned_malloc`
25+
1026#include < sys/ioctl.h>
1127#include < sys/socket.h> // `recv`, `setsockopt`
12- # include < sys/types.h >
28+
1329#include < sys/uio.h>
1430#include < unistd.h>
31+ #endif
32+
33+ #include < errno.h> // `strerror`
34+ #include < fcntl.h> // `fcntl`
35+ #include < stdlib.h> // `std::aligned_malloc`
36+ #include < sys/types.h>
1537
1638#include < charconv> // `std::to_chars`
1739#include < chrono> // `std::chrono`
@@ -244,13 +266,13 @@ void forward_packet(engine_t& engine) noexcept {
244266
245267int ssl_send (void * ctx, const unsigned char * buf, size_t len) {
246268 mbedtls_net_context* conn = reinterpret_cast <mbedtls_net_context*>(ctx);
247- ssize_t ret = send (conn->fd , buf, len, 0 );
269+ ssize_t ret = send (conn->fd , reinterpret_cast < char const *>( buf) , len, 0 );
248270 return ret;
249271}
250272
251273int ssl_recv (void * ctx, unsigned char * buf, size_t len) {
252274 mbedtls_net_context* conn = reinterpret_cast <mbedtls_net_context*>(ctx);
253- ssize_t ret = recv (conn->fd , buf, len, 0 );
275+ ssize_t ret = recv (conn->fd , reinterpret_cast < char *>( buf) , len, 0 );
254276 return ret;
255277}
256278
@@ -329,11 +351,14 @@ void ucall_take_call(ucall_server_t server, uint16_t) {
329351 if (auto error_ptr = std::get_if<default_error_t >(&json_or_error); error_ptr)
330352 return ucall_call_reply_error (&engine, error_ptr->code , error_ptr->note .data (), error_ptr->note .size ());
331353 parsed_request_t request = std::get<parsed_request_t >(json_or_error);
332- auto res = std::from_chars (request.content_length .begin (), request.content_length .end (), bytes_expected);
333- bytes_expected += (request.body .begin () - buffer_ptr);
354+ auto res = std::from_chars (request.content_length .data (),
355+ request.content_length .data () + request.content_length .size (), bytes_expected);
356+ bytes_expected += (request.body .data () - buffer_ptr);
334357
335358 if (res.ec == std::errc::invalid_argument || bytes_expected <= 0 )
359+ #if !defined(UCALL_IS_WINDOWS)
336360 if (ioctl (engine.connection , FIONREAD , &bytes_expected) == -1 || bytes_expected == 0 )
361+ #endif
337362 bytes_expected = bytes_received; // TODO what?
338363
339364 // Either process it in the statically allocated memory,
@@ -352,7 +377,11 @@ void ucall_take_call(ucall_server_t server, uint16_t) {
352377 if (parser.allocate (bytes_expected, bytes_expected / 2 ) != sj::SUCCESS )
353378 return ucall_call_reply_error_out_of_memory (&engine);
354379
380+ #if defined(UCALL_IS_WINDOWS)
381+ buffer_ptr = (char *)_aligned_malloc (round_up_to<align_k>(bytes_expected + sj::SIMDJSON_PADDING ), align_k);
382+ #else
355383 buffer_ptr = (char *)std::aligned_alloc (align_k, round_up_to<align_k>(bytes_expected + sj::SIMDJSON_PADDING ));
384+ #endif
356385 if (!buffer_ptr)
357386 return ucall_call_reply_error_out_of_memory (&engine);
358387
@@ -364,7 +393,11 @@ void ucall_take_call(ucall_server_t server, uint16_t) {
364393 engine.stats .bytes_received += bytes_received;
365394 engine.stats .packets_received ++;
366395 forward_packet (engine);
396+ #if defined(UCALL_IS_WINDOWS)
397+ _aligned_free (buffer_ptr);
398+ #else
367399 std::free (buffer_ptr);
400+ #endif
368401 buffer_ptr = nullptr ;
369402 }
370403
@@ -396,8 +429,8 @@ void ucall_init(ucall_config_t* config_inout, ucall_server_t* server_out) {
396429 config.queue_depth = 128u ;
397430 if (!config.max_callbacks )
398431 config.max_callbacks = 128u ;
399- if (!config.interface )
400- config.interface = " 0.0.0.0" ;
432+ if (!config.hostname )
433+ config.hostname = " 0.0.0.0" ;
401434 if (config.use_ssl &&
402435 !(config.ssl_private_key_path || config.ssl_certificates_paths || config.ssl_certificates_count ))
403436 return ;
@@ -420,7 +453,7 @@ void ucall_init(ucall_config_t* config_inout, ucall_server_t* server_out) {
420453 // By default, let's open TCP port for IPv4.
421454 struct sockaddr_in address;
422455 address.sin_family = AF_INET ;
423- address.sin_addr .s_addr = inet_addr (config.interface );
456+ address.sin_addr .s_addr = inet_addr (config.hostname );
424457 address.sin_port = htons (config.port );
425458
426459 // Try allocating all the necessary memory.
@@ -435,8 +468,8 @@ void ucall_init(ucall_config_t* config_inout, ucall_server_t* server_out) {
435468 if (socket_descriptor < 0 )
436469 goto cleanup;
437470 // Optionally configure the socket, but don't always expect it to succeed.
438- if (setsockopt (socket_descriptor, SOL_SOCKET , SO_REUSEADDR | SO_REUSEPORT , &socket_options,
439- sizeof (socket_options)) == -1 )
471+ if (setsockopt (socket_descriptor, SOL_SOCKET , SO_REUSEADDR | SO_REUSEPORT ,
472+ reinterpret_cast < char const *>(&socket_options), sizeof (socket_options)) == -1 )
440473 errno;
441474 if (bind (socket_descriptor, (struct sockaddr *)&address, sizeof (address)) < 0 )
442475 goto cleanup;
0 commit comments