Browse Source

Merge pull request #95 from paullouisageneau/msvc

Add workflow for MSVC
Paul-Louis Ageneau 5 years ago
parent
commit
3d7764c1e9

+ 2 - 2
.github/workflows/build-gnutls.yml

@@ -1,4 +1,4 @@
-name: Build and test with GnuTLS
+name: Build with GnuTLS
 on:
 on:
   push:
   push:
     branches:
     branches:
@@ -7,7 +7,7 @@ on:
     branches:
     branches:
     - master
     - master
 jobs:
 jobs:
-  build-ubuntu:
+  build-linux:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
     - uses: actions/checkout@v2
     - uses: actions/checkout@v2

+ 2 - 2
.github/workflows/build-nice.yml

@@ -1,4 +1,4 @@
-name: Build and test with libnice
+name: Build with libnice
 on:
 on:
   push:
   push:
     branches:
     branches:
@@ -7,7 +7,7 @@ on:
     branches:
     branches:
     - master
     - master
 jobs:
 jobs:
-  build-ubuntu:
+  build-linux:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
     - uses: actions/checkout@v2
     - uses: actions/checkout@v2

+ 18 - 2
.github/workflows/build-openssl.yml

@@ -1,4 +1,4 @@
-name: Build and test with OpenSSL
+name: Build with OpenSSL
 on:
 on:
   push:
   push:
     branches:
     branches:
@@ -7,7 +7,7 @@ on:
     branches:
     branches:
     - master
     - master
 jobs:
 jobs:
-  build-ubuntu:
+  build-linux:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
     - uses: actions/checkout@v2
     - uses: actions/checkout@v2
@@ -38,3 +38,19 @@ jobs:
       run: (cd build; make -j2)
       run: (cd build; make -j2)
     - name: test
     - name: test
       run: ./build/tests
       run: ./build/tests
+  build-windows:
+    runs-on: windows-latest
+    steps:
+    - uses: actions/checkout@v2
+    - uses: ilammy/msvc-dev-cmd@v1
+    - name: submodules
+      run: git submodule update --init --recursive
+    - name: cmake
+      run: cmake -B build -G "NMake Makefiles" -DUSE_JUICE=1 -DUSE_GNUTLS=0
+    - name: nmake
+      run: |
+        cd build
+        nmake
+    - name: test
+      run: build/tests.exe
+

+ 12 - 2
CMakeLists.txt

@@ -21,6 +21,8 @@ if(WIN32)
 	add_definitions(-DWIN32_LEAN_AND_MEAN)
 	add_definitions(-DWIN32_LEAN_AND_MEAN)
 	if (MSVC)
 	if (MSVC)
 		add_definitions(-DNOMINMAX)
 		add_definitions(-DNOMINMAX)
+		add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+		add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
 	endif()
 	endif()
 endif()
 endif()
 
 
@@ -205,7 +207,11 @@ set_target_properties(datachannel-tests PROPERTIES
 	CXX_STANDARD 17)
 	CXX_STANDARD 17)
 set_target_properties(datachannel-tests PROPERTIES OUTPUT_NAME tests)
 set_target_properties(datachannel-tests PROPERTIES OUTPUT_NAME tests)
 target_include_directories(datachannel-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
 target_include_directories(datachannel-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
-target_link_libraries(datachannel-tests datachannel nlohmann_json::nlohmann_json)
+if(WIN32)
+	target_link_libraries(datachannel-tests datachannel-static) # DLL exports only the C API
+else()
+	target_link_libraries(datachannel-tests datachannel)
+endif()
 
 
 # Benchmark
 # Benchmark
 add_executable(datachannel-benchmark test/benchmark.cpp)
 add_executable(datachannel-benchmark test/benchmark.cpp)
@@ -215,7 +221,11 @@ set_target_properties(datachannel-benchmark PROPERTIES
 set_target_properties(datachannel-benchmark PROPERTIES OUTPUT_NAME benchmark)
 set_target_properties(datachannel-benchmark PROPERTIES OUTPUT_NAME benchmark)
 target_compile_definitions(datachannel-benchmark PRIVATE BENCHMARK_MAIN=1)
 target_compile_definitions(datachannel-benchmark PRIVATE BENCHMARK_MAIN=1)
 target_include_directories(datachannel-benchmark PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
 target_include_directories(datachannel-benchmark PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
-target_link_libraries(datachannel-benchmark datachannel)
+if(WIN32)
+	target_link_libraries(datachannel-benchmark datachannel-static) # DLL exports only the C API
+else()
+	target_link_libraries(datachannel-benchmark datachannel)
+endif()
 
 
 # Examples
 # Examples
 set(JSON_BuildTests OFF CACHE INTERNAL "")
 set(JSON_BuildTests OFF CACHE INTERNAL "")

+ 1 - 1
deps/libjuice

@@ -1 +1 @@
-Subproject commit aac444ae5654a26b664191873b83ab4ae966e2df
+Subproject commit 796495852665fb74c0637c069c2abed6392ed4c8

+ 6 - 0
examples/client/CMakeLists.txt

@@ -7,5 +7,11 @@ add_executable(datachannel-client main.cpp)
 set_target_properties(datachannel-client PROPERTIES
 set_target_properties(datachannel-client PROPERTIES
 	CXX_STANDARD 17
 	CXX_STANDARD 17
 	OUTPUT_NAME client)
 	OUTPUT_NAME client)
+
+if(WIN32)
+	target_link_libraries(datachannel-client datachannel-static) # DLL exports only the C API
+else()
+	target_link_libraries(datachannel-client datachannel)
+endif()
 target_link_libraries(datachannel-client datachannel nlohmann_json)
 target_link_libraries(datachannel-client datachannel nlohmann_json)
 
 

+ 1 - 1
examples/client/main.cpp

@@ -212,7 +212,7 @@ string randomId(size_t length) {
 	    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
 	    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
 	string id(length, '0');
 	string id(length, '0');
 	default_random_engine rng(random_device{}());
 	default_random_engine rng(random_device{}());
-	uniform_int_distribution<int> dist(0, characters.size() - 1);
+	uniform_int_distribution<int> dist(0, int(characters.size() - 1));
 	generate(id.begin(), id.end(), [&]() { return characters.at(dist(rng)); });
 	generate(id.begin(), id.end(), [&]() { return characters.at(dist(rng)); });
 	return id;
 	return id;
 }
 }

+ 1 - 1
examples/copy-paste-capi/CMakeLists.txt

@@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 3.5.1)
 project(offerer C)
 project(offerer C)
 
 
 set(CMAKE_C_STANDARD 11)
 set(CMAKE_C_STANDARD 11)
-set(CMAKE_C_FLAGS "-Wall -g -O2")
 
 
 add_executable(datachannel-copy-paste-capi-offerer offerer.c)
 add_executable(datachannel-copy-paste-capi-offerer offerer.c)
 set_target_properties(datachannel-copy-paste-capi-offerer PROPERTIES
 set_target_properties(datachannel-copy-paste-capi-offerer PROPERTIES
@@ -13,3 +12,4 @@ add_executable(datachannel-copy-paste-capi-answerer answerer.c)
 set_target_properties(datachannel-copy-paste-capi-answerer PROPERTIES
 set_target_properties(datachannel-copy-paste-capi-answerer PROPERTIES
 	OUTPUT_NAME answerer)
 	OUTPUT_NAME answerer)
 target_link_libraries(datachannel-copy-paste-capi-answerer datachannel)
 target_link_libraries(datachannel-copy-paste-capi-answerer datachannel)
+

+ 53 - 61
examples/copy-paste-capi/answerer.c

@@ -41,27 +41,19 @@ typedef struct {
         bool connected;
         bool connected;
 } Peer;
 } Peer;
 
 
-Peer *peer = NULL;
-
 static void dataChannelCallback(int dc, void *ptr);
 static void dataChannelCallback(int dc, void *ptr);
-
 static void descriptionCallback(const char *sdp, const char *type, void *ptr);
 static void descriptionCallback(const char *sdp, const char *type, void *ptr);
-
 static void candidateCallback(const char *cand, const char *mid, void *ptr);
 static void candidateCallback(const char *cand, const char *mid, void *ptr);
-
 static void stateChangeCallback(rtcState state, void *ptr);
 static void stateChangeCallback(rtcState state, void *ptr);
-
 static void gatheringStateCallback(rtcGatheringState state, void *ptr);
 static void gatheringStateCallback(rtcGatheringState state, void *ptr);
-
 static void closedCallback(void *ptr);
 static void closedCallback(void *ptr);
-
 static void messageCallback(const char *message, int size, void *ptr);
 static void messageCallback(const char *message, int size, void *ptr);
-
 static void deletePeer(Peer *peer);
 static void deletePeer(Peer *peer);
 
 
-int all_space(const char *str);
 char* state_print(rtcState state);
 char* state_print(rtcState state);
-char* rtcGatheringState_print(rtcState state);
+char *rtcGatheringState_print(rtcGatheringState state);
+
+int all_space(const char *str);
 
 
 int main(int argc, char **argv) {
 int main(int argc, char **argv) {
 	rtcInitLogger(RTC_LOG_DEBUG, NULL);
 	rtcInitLogger(RTC_LOG_DEBUG, NULL);
@@ -259,59 +251,59 @@ static void dataChannelCallback(int dc, void *ptr) {
                 printf("DataChannel %s: Received with label \"%s\"\n", "answerer", buffer);
                 printf("DataChannel %s: Received with label \"%s\"\n", "answerer", buffer);
 }
 }
 
 
-int all_space(const char *str) {
-        while (*str) {
-                if (!isspace(*str++)) {
-                        return 0;
-                }
-        }
-
-	    return 1;
+char *state_print(rtcState state) {
+	char *str = NULL;
+	switch (state) {
+	case RTC_NEW:
+		str = "RTC_NEW";
+		break;
+	case RTC_CONNECTING:
+		str = "RTC_CONNECTING";
+		break;
+	case RTC_CONNECTED:
+		str = "RTC_CONNECTED";
+		break;
+	case RTC_DISCONNECTED:
+		str = "RTC_DISCONNECTED";
+		break;
+	case RTC_FAILED:
+		str = "RTC_FAILED";
+		break;
+	case RTC_CLOSED:
+		str = "RTC_CLOSED";
+		break;
+	default:
+		break;
+	}
+
+	return str;
 }
 }
 
 
-char* state_print(rtcState state) {
-        char *str = NULL;
-        switch (state) {
-        case RTC_NEW:
-                str = "RTC_NEW";
-                break;
-        case RTC_CONNECTING:
-                str = "RTC_CONNECTING";
-                break;
-        case RTC_CONNECTED:
-                str = "RTC_CONNECTED";
-                break;
-        case RTC_DISCONNECTED:
-                str = "RTC_DISCONNECTED";
-                break;
-        case RTC_FAILED:
-                str = "RTC_FAILED";
-                break;
-        case RTC_CLOSED:
-                str = "RTC_CLOSED";
-                break;
-        default:
-                break;
-        }
-
-        return str;
+char *rtcGatheringState_print(rtcGatheringState state) {
+	char *str = NULL;
+	switch (state) {
+	case RTC_GATHERING_NEW:
+		str = "RTC_GATHERING_NEW";
+		break;
+	case RTC_GATHERING_INPROGRESS:
+		str = "RTC_GATHERING_INPROGRESS";
+		break;
+	case RTC_GATHERING_COMPLETE:
+		str = "RTC_GATHERING_COMPLETE";
+		break;
+	default:
+		break;
+	}
+
+	return str;
 }
 }
 
 
-char* rtcGatheringState_print(rtcState state) {
-        char* str = NULL;
-        switch (state) {
-        case RTC_GATHERING_NEW:
-                str = "RTC_GATHERING_NEW";
-                break;
-        case RTC_GATHERING_INPROGRESS:
-                str = "RTC_GATHERING_INPROGRESS";
-                break;
-        case RTC_GATHERING_COMPLETE:
-                str = "RTC_GATHERING_COMPLETE";
-                break;
-        default:
-                break;
-        }
+int all_space(const char *str) {
+	while (*str) {
+		if (!isspace(*str++)) {
+			return 0;
+		}
+	}
 
 
-        return str;
+	return 1;
 }
 }

+ 5 - 5
examples/copy-paste-capi/getline.h

@@ -1,10 +1,11 @@
 // Simple POSIX getline() implementation
 // Simple POSIX getline() implementation
 // This code is public domain
 // This code is public domain
 
 
-#include "malloc.h"
-#include "stdio.h"
+#include <malloc.h>
+#include <stddef.h>
+#include <stdio.h>
 
 
-ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
+int getline(char **lineptr, size_t *n, FILE *stream) {
 	if (!lineptr || !stream || !n)
 	if (!lineptr || !stream || !n)
 		return -1;
 		return -1;
 
 
@@ -20,7 +21,7 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
 		*n = 128;
 		*n = 128;
 	}
 	}
 
 
-	size_t pos = 0;
+	int pos = 0;
 	while(c != EOF) {
 	while(c != EOF) {
         if (pos + 1 >= *n) {
         if (pos + 1 >= *n) {
             size_t new_size = *n + (*n >> 2);
             size_t new_size = *n + (*n >> 2);
@@ -45,4 +46,3 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
     (*lineptr)[pos] = '\0';
     (*lineptr)[pos] = '\0';
     return pos;
     return pos;
 }
 }
-

+ 53 - 63
examples/copy-paste-capi/offerer.c

@@ -33,9 +33,6 @@ static void sleep(unsigned int secs) { Sleep(secs * 1000); }
 #include <unistd.h> // for sleep
 #include <unistd.h> // for sleep
 #endif
 #endif
 
 
-char* state_print(rtcState state);
-char* rtcGatheringState_print(rtcState state);
-
 typedef struct {
 typedef struct {
         rtcState state;
         rtcState state;
         rtcGatheringState gatheringState;
         rtcGatheringState gatheringState;
@@ -44,24 +41,18 @@ typedef struct {
         bool connected;
         bool connected;
 } Peer;
 } Peer;
 
 
-Peer *peer = NULL;
-
 static void descriptionCallback(const char *sdp, const char *type, void *ptr);
 static void descriptionCallback(const char *sdp, const char *type, void *ptr);
-
 static void candidateCallback(const char *cand, const char *mid, void *ptr);
 static void candidateCallback(const char *cand, const char *mid, void *ptr);
-
 static void stateChangeCallback(rtcState state, void *ptr);
 static void stateChangeCallback(rtcState state, void *ptr);
-
 static void gatheringStateCallback(rtcGatheringState state, void *ptr);
 static void gatheringStateCallback(rtcGatheringState state, void *ptr);
-
 static void openCallback(void *ptr);
 static void openCallback(void *ptr);
-
 static void closedCallback(void *ptr);
 static void closedCallback(void *ptr);
-
 static void messageCallback(const char *message, int size, void *ptr);
 static void messageCallback(const char *message, int size, void *ptr);
-
 static void deletePeer(Peer *peer);
 static void deletePeer(Peer *peer);
 
 
+char *state_print(rtcState state);
+char *rtcGatheringState_print(rtcGatheringState state);
+
 int all_space(const char *str);
 int all_space(const char *str);
 
 
 int main(int argc, char **argv){
 int main(int argc, char **argv){
@@ -263,60 +254,59 @@ static void deletePeer(Peer *peer) {
         }
         }
 }
 }
 
 
-int all_space(const char *str) {
-        while (*str) {
-                if (!isspace(*str++)) {
-                        return 0;
-                }
-        }
-
-	    return 1;
+char *state_print(rtcState state) {
+	char *str = NULL;
+	switch (state) {
+	case RTC_NEW:
+		str = "RTC_NEW";
+		break;
+	case RTC_CONNECTING:
+		str = "RTC_CONNECTING";
+		break;
+	case RTC_CONNECTED:
+		str = "RTC_CONNECTED";
+		break;
+	case RTC_DISCONNECTED:
+		str = "RTC_DISCONNECTED";
+		break;
+	case RTC_FAILED:
+		str = "RTC_FAILED";
+		break;
+	case RTC_CLOSED:
+		str = "RTC_CLOSED";
+		break;
+	default:
+		break;
+	}
+
+	return str;
 }
 }
 
 
-char* state_print(rtcState state) {
-        char *str = NULL;
-        switch (state) {
-        case RTC_NEW:
-                str = "RTC_NEW";
-                break;
-        case RTC_CONNECTING:
-                str = "RTC_CONNECTING";
-                break;
-        case RTC_CONNECTED:
-                str = "RTC_CONNECTED";
-                break;
-        case RTC_DISCONNECTED:
-                str = "RTC_DISCONNECTED";
-                break;
-        case RTC_FAILED:
-                str = "RTC_FAILED";
-                break;
-        case RTC_CLOSED:
-                str = "RTC_CLOSED";
-                break;
-        default:
-                break;
-        }
-
-        return str;
-
+char *rtcGatheringState_print(rtcGatheringState state) {
+	char *str = NULL;
+	switch (state) {
+	case RTC_GATHERING_NEW:
+		str = "RTC_GATHERING_NEW";
+		break;
+	case RTC_GATHERING_INPROGRESS:
+		str = "RTC_GATHERING_INPROGRESS";
+		break;
+	case RTC_GATHERING_COMPLETE:
+		str = "RTC_GATHERING_COMPLETE";
+		break;
+	default:
+		break;
+	}
+
+	return str;
 }
 }
 
 
-char* rtcGatheringState_print(rtcState state) {
-        char* str = NULL;
-        switch (state) {
-        case RTC_GATHERING_NEW:
-                str = "RTC_GATHERING_NEW";
-                break;
-        case RTC_GATHERING_INPROGRESS:
-                str = "RTC_GATHERING_INPROGRESS";
-                break;
-        case RTC_GATHERING_COMPLETE:
-                str = "RTC_GATHERING_COMPLETE";
-                break;
-        default:
-                break;
-        }
+int all_space(const char *str) {
+	while (*str) {
+		if (!isspace(*str++)) {
+			return 0;
+		}
+	}
 
 
-        return str;
+	return 1;
 }
 }

+ 10 - 2
examples/copy-paste/CMakeLists.txt

@@ -4,11 +4,19 @@ add_executable(datachannel-copy-paste-offerer offerer.cpp)
 set_target_properties(datachannel-copy-paste-offerer PROPERTIES
 set_target_properties(datachannel-copy-paste-offerer PROPERTIES
 	CXX_STANDARD 17
 	CXX_STANDARD 17
 	OUTPUT_NAME offerer)
 	OUTPUT_NAME offerer)
-target_link_libraries(datachannel-copy-paste-offerer datachannel)
+if(WIN32)
+	target_link_libraries(datachannel-copy-paste-offerer datachannel-static) # DLL exports only the C API
+else()
+	target_link_libraries(datachannel-copy-paste-offerer datachannel)
+endif()
 
 
 add_executable(datachannel-copy-paste-answerer answerer.cpp)
 add_executable(datachannel-copy-paste-answerer answerer.cpp)
 set_target_properties(datachannel-copy-paste-answerer PROPERTIES
 set_target_properties(datachannel-copy-paste-answerer PROPERTIES
 	CXX_STANDARD 17
 	CXX_STANDARD 17
 	OUTPUT_NAME answerer)
 	OUTPUT_NAME answerer)
-target_link_libraries(datachannel-copy-paste-answerer datachannel)
+if(WIN32)
+	target_link_libraries(datachannel-copy-paste-answerer datachannel-static) # DLL exports only the C API
+else()
+	target_link_libraries(datachannel-copy-paste-answerer datachannel)
+endif()
 
 

+ 40 - 34
include/rtc/rtc.h

@@ -23,9 +23,11 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-#include <stdint.h>
-
-// libdatachannel C API
+#ifdef _WIN32
+#define RTC_EXPORT __declspec(dllexport)
+#else
+#define RTC_EXPORT
+#endif
 
 
 #ifndef RTC_ENABLE_MEDIA
 #ifndef RTC_ENABLE_MEDIA
 #define RTC_ENABLE_MEDIA 1
 #define RTC_ENABLE_MEDIA 1
@@ -35,6 +37,10 @@ extern "C" {
 #define RTC_ENABLE_WEBSOCKET 1
 #define RTC_ENABLE_WEBSOCKET 1
 #endif
 #endif
 
 
+#include <stdint.h>
+
+// libdatachannel C API
+
 typedef enum {
 typedef enum {
 	RTC_NEW = 0,
 	RTC_NEW = 0,
 	RTC_CONNECTING = 1,
 	RTC_CONNECTING = 1,
@@ -85,58 +91,58 @@ typedef void (*rtcBufferedAmountLowCallbackFunc)(void *ptr);
 typedef void (*rtcAvailableCallbackFunc)(void *ptr);
 typedef void (*rtcAvailableCallbackFunc)(void *ptr);
 
 
 // Log
 // Log
-void rtcInitLogger(rtcLogLevel level, rtcLogCallbackFunc cb); // NULL cb to log to stdout
+RTC_EXPORT void rtcInitLogger(rtcLogLevel level, rtcLogCallbackFunc cb); // NULL cb to log to stdout
 
 
 // User pointer
 // User pointer
-void rtcSetUserPointer(int id, void *ptr);
+RTC_EXPORT void rtcSetUserPointer(int id, void *ptr);
 
 
 // PeerConnection
 // PeerConnection
-int rtcCreatePeerConnection(const rtcConfiguration *config); // returns pc id
-int rtcDeletePeerConnection(int pc);
+RTC_EXPORT int rtcCreatePeerConnection(const rtcConfiguration *config); // returns pc id
+RTC_EXPORT int rtcDeletePeerConnection(int pc);
 
 
-int rtcSetDataChannelCallback(int pc, rtcDataChannelCallbackFunc cb);
-int rtcSetLocalDescriptionCallback(int pc, rtcDescriptionCallbackFunc cb);
-int rtcSetLocalCandidateCallback(int pc, rtcCandidateCallbackFunc cb);
-int rtcSetStateChangeCallback(int pc, rtcStateChangeCallbackFunc cb);
-int rtcSetGatheringStateChangeCallback(int pc, rtcGatheringStateCallbackFunc cb);
+RTC_EXPORT int rtcSetDataChannelCallback(int pc, rtcDataChannelCallbackFunc cb);
+RTC_EXPORT int rtcSetLocalDescriptionCallback(int pc, rtcDescriptionCallbackFunc cb);
+RTC_EXPORT int rtcSetLocalCandidateCallback(int pc, rtcCandidateCallbackFunc cb);
+RTC_EXPORT int rtcSetStateChangeCallback(int pc, rtcStateChangeCallbackFunc cb);
+RTC_EXPORT int rtcSetGatheringStateChangeCallback(int pc, rtcGatheringStateCallbackFunc cb);
 
 
-int rtcSetRemoteDescription(int pc, const char *sdp, const char *type);
-int rtcAddRemoteCandidate(int pc, const char *cand, const char *mid);
+RTC_EXPORT int rtcSetRemoteDescription(int pc, const char *sdp, const char *type);
+RTC_EXPORT int rtcAddRemoteCandidate(int pc, const char *cand, const char *mid);
 
 
-int rtcGetLocalAddress(int pc, char *buffer, int size);
-int rtcGetRemoteAddress(int pc, char *buffer, int size);
+RTC_EXPORT int rtcGetLocalAddress(int pc, char *buffer, int size);
+RTC_EXPORT int rtcGetRemoteAddress(int pc, char *buffer, int size);
 
 
 // DataChannel
 // DataChannel
-int rtcCreateDataChannel(int pc, const char *label); // returns dc id
-int rtcDeleteDataChannel(int dc);
+RTC_EXPORT int rtcCreateDataChannel(int pc, const char *label); // returns dc id
+RTC_EXPORT int rtcDeleteDataChannel(int dc);
 
 
-int rtcGetDataChannelLabel(int dc, char *buffer, int size);
+RTC_EXPORT int rtcGetDataChannelLabel(int dc, char *buffer, int size);
 
 
 // WebSocket
 // WebSocket
 #if RTC_ENABLE_WEBSOCKET
 #if RTC_ENABLE_WEBSOCKET
-int rtcCreateWebSocket(const char *url); // returns ws id
-int rtcDeleteWebsocket(int ws);
+RTC_EXPORT int rtcCreateWebSocket(const char *url); // returns ws id
+RTC_EXPORT int rtcDeleteWebsocket(int ws);
 #endif
 #endif
 
 
 // DataChannel and WebSocket common API
 // DataChannel and WebSocket common API
-int rtcSetOpenCallback(int id, rtcOpenCallbackFunc cb);
-int rtcSetClosedCallback(int id, rtcClosedCallbackFunc cb);
-int rtcSetErrorCallback(int id, rtcErrorCallbackFunc cb);
-int rtcSetMessageCallback(int id, rtcMessageCallbackFunc cb);
-int rtcSendMessage(int id, const char *data, int size);
+RTC_EXPORT int rtcSetOpenCallback(int id, rtcOpenCallbackFunc cb);
+RTC_EXPORT int rtcSetClosedCallback(int id, rtcClosedCallbackFunc cb);
+RTC_EXPORT int rtcSetErrorCallback(int id, rtcErrorCallbackFunc cb);
+RTC_EXPORT int rtcSetMessageCallback(int id, rtcMessageCallbackFunc cb);
+RTC_EXPORT int rtcSendMessage(int id, const char *data, int size);
 
 
-int rtcGetBufferedAmount(int id); // total size buffered to send
-int rtcSetBufferedAmountLowThreshold(int id, int amount);
-int rtcSetBufferedAmountLowCallback(int id, rtcBufferedAmountLowCallbackFunc cb);
+RTC_EXPORT int rtcGetBufferedAmount(int id); // total size buffered to send
+RTC_EXPORT int rtcSetBufferedAmountLowThreshold(int id, int amount);
+RTC_EXPORT int rtcSetBufferedAmountLowCallback(int id, rtcBufferedAmountLowCallbackFunc cb);
 
 
 // DataChannel and WebSocket common extended API
 // DataChannel and WebSocket common extended API
-int rtcGetAvailableAmount(int id); // total size available to receive
-int rtcSetAvailableCallback(int id, rtcAvailableCallbackFunc cb);
-int rtcReceiveMessage(int id, char *buffer, int *size);
+RTC_EXPORT int rtcGetAvailableAmount(int id); // total size available to receive
+RTC_EXPORT int rtcSetAvailableCallback(int id, rtcAvailableCallbackFunc cb);
+RTC_EXPORT int rtcReceiveMessage(int id, char *buffer, int *size);
 
 
 // Optional preload and cleanup
 // Optional preload and cleanup
-void rtcPreload();
-void rtcCleanup();
+RTC_EXPORT void rtcPreload(void);
+RTC_EXPORT void rtcCleanup(void);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 } // extern "C"
 } // extern "C"

+ 1 - 1
src/base64.cpp

@@ -42,7 +42,7 @@ string to_base64(const binary &data) {
 		i += 3;
 		i += 3;
 	}
 	}
 
 
-	int left = data.size() - i;
+	int left = int(data.size() - i);
 	if (left) {
 	if (left) {
 		auto d0 = to_integer<uint8_t>(data[i]);
 		auto d0 = to_integer<uint8_t>(data[i]);
 		out += tab[d0 >> 2];
 		out += tab[d0 >> 2];

+ 2 - 2
src/candidate.cpp

@@ -98,8 +98,8 @@ bool Candidate::resolve(ResolveMode mode) {
 					// Rewrite the candidate
 					// Rewrite the candidate
 					char nodebuffer[MAX_NUMERICNODE_LEN];
 					char nodebuffer[MAX_NUMERICNODE_LEN];
 					char servbuffer[MAX_NUMERICSERV_LEN];
 					char servbuffer[MAX_NUMERICSERV_LEN];
-					if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
-					                servbuffer, MAX_NUMERICSERV_LEN,
+					if (getnameinfo(p->ai_addr, socklen_t(p->ai_addrlen), nodebuffer,
+					                MAX_NUMERICNODE_LEN, servbuffer, MAX_NUMERICSERV_LEN,
 					                NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
 					                NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
 						const char sp{' '};
 						const char sp{' '};
 						std::ostringstream oss;
 						std::ostringstream oss;

+ 4 - 4
src/certificate.cpp

@@ -132,14 +132,14 @@ namespace rtc {
 
 
 Certificate::Certificate(string crt_pem, string key_pem) {
 Certificate::Certificate(string crt_pem, string key_pem) {
 	BIO *bio = BIO_new(BIO_s_mem());
 	BIO *bio = BIO_new(BIO_s_mem());
-	BIO_write(bio, crt_pem.data(), crt_pem.size());
+	BIO_write(bio, crt_pem.data(), int(crt_pem.size()));
 	mX509 = shared_ptr<X509>(PEM_read_bio_X509(bio, nullptr, 0, 0), X509_free);
 	mX509 = shared_ptr<X509>(PEM_read_bio_X509(bio, nullptr, 0, 0), X509_free);
 	BIO_free(bio);
 	BIO_free(bio);
 	if (!mX509)
 	if (!mX509)
 		throw std::invalid_argument("Unable to import certificate PEM");
 		throw std::invalid_argument("Unable to import certificate PEM");
 
 
 	bio = BIO_new(BIO_s_mem());
 	bio = BIO_new(BIO_s_mem());
-	BIO_write(bio, key_pem.data(), key_pem.size());
+	BIO_write(bio, key_pem.data(), int(key_pem.size()));
 	mPKey = shared_ptr<EVP_PKEY>(PEM_read_bio_PrivateKey(bio, nullptr, 0, 0), EVP_PKEY_free);
 	mPKey = shared_ptr<EVP_PKEY>(PEM_read_bio_PrivateKey(bio, nullptr, 0, 0), EVP_PKEY_free);
 	BIO_free(bio);
 	BIO_free(bio);
 	if (!mPKey)
 	if (!mPKey)
@@ -233,8 +233,8 @@ namespace {
 // Helper function roughly equivalent to std::async with policy std::launch::async
 // Helper function roughly equivalent to std::async with policy std::launch::async
 // since std::async might be unreliable on some platforms (e.g. Mingw32 on Windows)
 // since std::async might be unreliable on some platforms (e.g. Mingw32 on Windows)
 template <class F, class... Args>
 template <class F, class... Args>
-std::future<std::result_of_t<std::decay_t<F>(std::decay_t<Args>...)>> thread_call(F &&f,
-                                                                                  Args &&... args) {
+std::future<std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>>
+thread_call(F &&f, Args &&... args) {
 	using R = std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>;
 	using R = std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>;
 	std::packaged_task<R()> task(std::bind(f, std::forward<Args>(args)...));
 	std::packaged_task<R()> task(std::bind(f, std::forward<Args>(args)...));
 	std::future<R> future = task.get_future();
 	std::future<R> future = task.get_future();

+ 2 - 2
src/datachannel.cpp

@@ -186,8 +186,8 @@ void DataChannel::open(shared_ptr<SctpTransport> transport) {
 	open.channelType = mReliability->type;
 	open.channelType = mReliability->type;
 	open.priority = htons(0);
 	open.priority = htons(0);
 	open.reliabilityParameter = htonl(reliabilityParameter);
 	open.reliabilityParameter = htonl(reliabilityParameter);
-	open.labelLength = htons(mLabel.size());
-	open.protocolLength = htons(mProtocol.size());
+	open.labelLength = htons(uint16_t(mLabel.size()));
+	open.protocolLength = htons(uint16_t(mProtocol.size()));
 
 
 	auto end = reinterpret_cast<char *>(buffer.data() + sizeof(OpenMessage));
 	auto end = reinterpret_cast<char *>(buffer.data() + sizeof(OpenMessage));
 	std::copy(mLabel.begin(), mLabel.end(), end);
 	std::copy(mLabel.begin(), mLabel.end(), end);

+ 2 - 1
src/description.cpp

@@ -26,6 +26,7 @@
 
 
 using std::size_t;
 using std::size_t;
 using std::string;
 using std::string;
+using std::chrono::system_clock;
 
 
 namespace {
 namespace {
 
 
@@ -54,7 +55,7 @@ Description::Description(const string &sdp, Type type, Role role)
 	mData.mid = "data";
 	mData.mid = "data";
 	hintType(type);
 	hintType(type);
 
 
-	auto seed = std::chrono::system_clock::now().time_since_epoch().count();
+	auto seed = static_cast<unsigned int>(system_clock::now().time_since_epoch().count());
 	std::default_random_engine generator(seed);
 	std::default_random_engine generator(seed);
 	std::uniform_int_distribution<uint32_t> uniform;
 	std::uniform_int_distribution<uint32_t> uniform;
 	mSessionId = std::to_string(uniform(generator));
 	mSessionId = std::to_string(uniform(generator));

+ 10 - 2
src/dtlstransport.cpp

@@ -24,6 +24,14 @@
 #include <exception>
 #include <exception>
 #include <iostream>
 #include <iostream>
 
 
+#if !USE_GNUTLS
+#ifdef _WIN32
+#include <winsock2.h> // for timeval
+#else
+#include <sys/time.h> // for timeval
+#endif
+#endif
+
 using namespace std::chrono;
 using namespace std::chrono;
 
 
 using std::shared_ptr;
 using std::shared_ptr;
@@ -382,7 +390,7 @@ bool DtlsTransport::send(message_ptr message) {
 
 
 	PLOG_VERBOSE << "Send size=" << message->size();
 	PLOG_VERBOSE << "Send size=" << message->size();
 
 
-	int ret = SSL_write(mSsl, message->data(), message->size());
+	int ret = SSL_write(mSsl, message->data(), int(message->size()));
 	return openssl::check(mSsl, ret);
 	return openssl::check(mSsl, ret);
 }
 }
 
 
@@ -416,7 +424,7 @@ void DtlsTransport::runRecvLoop() {
 			// Process pending messages
 			// Process pending messages
 			while (!mIncomingQueue.empty()) {
 			while (!mIncomingQueue.empty()) {
 				auto message = *mIncomingQueue.pop();
 				auto message = *mIncomingQueue.pop();
-				BIO_write(mInBio, message->data(), message->size());
+				BIO_write(mInBio, message->data(), int(message->size()));
 
 
 				if (state() == State::Connecting) {
 				if (state() == State::Connecting) {
 					// Continue the handshake
 					// Continue the handshake

+ 4 - 3
src/icetransport.cpp

@@ -40,6 +40,7 @@ using namespace std::chrono_literals;
 
 
 using std::shared_ptr;
 using std::shared_ptr;
 using std::weak_ptr;
 using std::weak_ptr;
+using std::chrono::system_clock;
 
 
 #if USE_JUICE
 #if USE_JUICE
 
 
@@ -69,7 +70,7 @@ IceTransport::IceTransport(const Configuration &config, Description::Role role,
 
 
 	// Randomize servers order
 	// Randomize servers order
 	std::vector<IceServer> servers = config.iceServers;
 	std::vector<IceServer> servers = config.iceServers;
-	unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
+	auto seed = static_cast<unsigned int>(system_clock::now().time_since_epoch().count());
 	std::shuffle(servers.begin(), servers.end(), std::default_random_engine(seed));
 	std::shuffle(servers.begin(), servers.end(), std::default_random_engine(seed));
 
 
 	// Pick a STUN server (TURN support is not implemented in libjuice yet)
 	// Pick a STUN server (TURN support is not implemented in libjuice yet)
@@ -82,7 +83,7 @@ IceTransport::IceTransport(const Configuration &config, Description::Role role,
 			mStunHostname = server.hostname;
 			mStunHostname = server.hostname;
 			mStunService = server.service;
 			mStunService = server.service;
 			jconfig.stun_server_host = mStunHostname.c_str();
 			jconfig.stun_server_host = mStunHostname.c_str();
-			jconfig.stun_server_port = std::stoul(mStunService);
+			jconfig.stun_server_port = uint16_t(std::stoul(mStunService));
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -337,7 +338,7 @@ IceTransport::IceTransport(const Configuration &config, Description::Role role,
 
 
 	// Randomize order
 	// Randomize order
 	std::vector<IceServer> servers = config.iceServers;
 	std::vector<IceServer> servers = config.iceServers;
-	unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
+	auto seed = static_cast<unsigned int>(system_clock::now().time_since_epoch().count());
 	std::shuffle(servers.begin(), servers.end(), std::default_random_engine(seed));
 	std::shuffle(servers.begin(), servers.end(), std::default_random_engine(seed));
 
 
 	// Add one STUN server
 	// Add one STUN server

+ 4 - 4
src/peerconnection.cpp

@@ -659,12 +659,12 @@ void PeerConnection::resetCallbacks() {
 }
 }
 
 
 bool PeerConnection::getSelectedCandidatePair(CandidateInfo *local, CandidateInfo *remote) {
 bool PeerConnection::getSelectedCandidatePair(CandidateInfo *local, CandidateInfo *remote) {
-#if not USE_JUICE
+#if USE_JUICE
+	PLOG_WARNING << "getSelectedCandidatePair() is not implemented for libjuice";
+	return false;
+#else
 	auto iceTransport = std::atomic_load(&mIceTransport);
 	auto iceTransport = std::atomic_load(&mIceTransport);
 	return iceTransport->getSelectedCandidatePair(local, remote);
 	return iceTransport->getSelectedCandidatePair(local, remote);
-#else
-	PLOG_WARNING << "getSelectedCandidatePair is not implemented for libjuice";
-	return false;
 #endif
 #endif
 }
 }
 
 

+ 23 - 12
src/rtc.cpp

@@ -35,6 +35,11 @@
 #include <unordered_map>
 #include <unordered_map>
 #include <utility>
 #include <utility>
 
 
+#ifdef _WIN32
+#include <codecvt>
+#include <locale>
+#endif
+
 using namespace rtc;
 using namespace rtc;
 using std::shared_ptr;
 using std::shared_ptr;
 using std::string;
 using std::string;
@@ -145,7 +150,7 @@ shared_ptr<Channel> getChannel(int id) {
 
 
 template <typename F> int wrap(F func) {
 template <typename F> int wrap(F func) {
 	try {
 	try {
-		return func();
+		return int(func());
 
 
 	} catch (const std::invalid_argument &e) {
 	} catch (const std::invalid_argument &e) {
 		PLOG_ERROR << e.what();
 		PLOG_ERROR << e.what();
@@ -173,14 +178,20 @@ public:
 
 
 	void write(const plog::Record &record) override {
 	void write(const plog::Record &record) override {
 		plog::Severity severity = record.getSeverity();
 		plog::Severity severity = record.getSeverity();
-		std::string formatted = plog::FuncMessageFormatter::format(record);
+		auto formatted = plog::FuncMessageFormatter::format(record);
 		formatted.pop_back(); // remove newline
 		formatted.pop_back(); // remove newline
-
+#ifdef _WIN32
+		using convert_type = std::codecvt_utf8<wchar_t>;
+		std::wstring_convert<convert_type, wchar_t> converter;
+		std::string str = converter.to_bytes(formatted);
+#else
+		std::string str = formatted;
+#endif
 		std::lock_guard lock(mutex);
 		std::lock_guard lock(mutex);
 		if (callback)
 		if (callback)
-			callback(static_cast<rtcLogLevel>(record.getSeverity()), formatted.c_str());
+			callback(static_cast<rtcLogLevel>(record.getSeverity()), str.c_str());
 		else
 		else
-			std::cout << plog::severityToString(severity) << " " << formatted << std::endl;
+			std::cout << plog::severityToString(severity) << " " << str << std::endl;
 	}
 	}
 
 
 private:
 private:
@@ -373,7 +384,7 @@ int rtcGetLocalAddress(int pc, char *buffer, int size) {
 
 
 		if (auto addr = peerConnection->localAddress()) {
 		if (auto addr = peerConnection->localAddress()) {
 			const char *data = addr->data();
 			const char *data = addr->data();
-			size = std::min(size_t(size - 1), addr->size());
+			size = std::min(size - 1, int(addr->size()));
 			std::copy(data, data + size, buffer);
 			std::copy(data, data + size, buffer);
 			buffer[size] = '\0';
 			buffer[size] = '\0';
 			return size + 1;
 			return size + 1;
@@ -393,10 +404,10 @@ int rtcGetRemoteAddress(int pc, char *buffer, int size) {
 
 
 		if (auto addr = peerConnection->remoteAddress()) {
 		if (auto addr = peerConnection->remoteAddress()) {
 			const char *data = addr->data();
 			const char *data = addr->data();
-			size = std::min(size_t(size - 1), addr->size());
+			size = std::min(size - 1, int(addr->size()));
 			std::copy(data, data + size, buffer);
 			std::copy(data, data + size, buffer);
 			buffer[size] = '\0';
 			buffer[size] = '\0';
-			return size + 1;
+			return int(size + 1);
 		}
 		}
 	});
 	});
 }
 }
@@ -413,10 +424,10 @@ int rtcGetDataChannelLabel(int dc, char *buffer, int size) {
 
 
 		string label = dataChannel->label();
 		string label = dataChannel->label();
 		const char *data = label.data();
 		const char *data = label.data();
-		size = std::min(size_t(size - 1), label.size());
+		size = std::min(size - 1, int(label.size()));
 		std::copy(data, data + size, buffer);
 		std::copy(data, data + size, buffer);
 		buffer[size] = '\0';
 		buffer[size] = '\0';
-		return size + 1;
+		return int(size + 1);
 	});
 	});
 }
 }
 
 
@@ -457,7 +468,7 @@ int rtcSetMessageCallback(int id, rtcMessageCallbackFunc cb) {
 		if (cb)
 		if (cb)
 			channel->onMessage(
 			channel->onMessage(
 			    [id, cb](const binary &b) {
 			    [id, cb](const binary &b) {
-				    cb(reinterpret_cast<const char *>(b.data()), b.size(), getUserPointer(id));
+				    cb(reinterpret_cast<const char *>(b.data()), int(b.size()), getUserPointer(id));
 			    },
 			    },
 			    [id, cb](const string &s) { cb(s.c_str(), -1, getUserPointer(id)); });
 			    [id, cb](const string &s) { cb(s.c_str(), -1, getUserPointer(id)); });
 		else
 		else
@@ -478,7 +489,7 @@ int rtcSendMessage(int id, const char *data, int size) {
 			return size;
 			return size;
 		} else {
 		} else {
 			string str(data);
 			string str(data);
-			int len = str.size();
+			int len = int(str.size());
 			channel->send(std::move(str));
 			channel->send(std::move(str));
 			return len;
 			return len;
 		}
 		}

+ 2 - 2
src/sctptransport.cpp

@@ -262,7 +262,7 @@ bool SctpTransport::send(message_ptr message) {
 		return true;
 		return true;
 
 
 	mSendQueue.push(message);
 	mSendQueue.push(message);
-	updateBufferedAmount(message->stream, message_size_func(message));
+	updateBufferedAmount(message->stream, long(message_size_func(message)));
 	return false;
 	return false;
 }
 }
 
 
@@ -302,7 +302,7 @@ bool SctpTransport::trySendQueue() {
 		if (!trySendMessage(message))
 		if (!trySendMessage(message))
 			return false;
 			return false;
 		mSendQueue.pop();
 		mSendQueue.pop();
-		updateBufferedAmount(message->stream, -message_size_func(message));
+		updateBufferedAmount(message->stream, -long(message_size_func(message)));
 	}
 	}
 	return true;
 	return true;
 }
 }

+ 7 - 6
src/tcptransport.cpp

@@ -21,6 +21,7 @@
 #if RTC_ENABLE_WEBSOCKET
 #if RTC_ENABLE_WEBSOCKET
 
 
 #include <exception>
 #include <exception>
+
 #ifndef _WIN32
 #ifndef _WIN32
 #include <fcntl.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <unistd.h>
@@ -150,7 +151,7 @@ void TcpTransport::connect(const string &hostname, const string &service) {
 
 
 	for (auto p = result; p; p = p->ai_next) {
 	for (auto p = result; p; p = p->ai_next) {
 		try {
 		try {
-			connect(p->ai_addr, p->ai_addrlen);
+			connect(p->ai_addr, socklen_t(p->ai_addrlen));
 
 
 			PLOG_INFO << "Connected to " << hostname << ":" << service;
 			PLOG_INFO << "Connected to " << hostname << ":" << service;
 			freeaddrinfo(result);
 			freeaddrinfo(result);
@@ -201,7 +202,7 @@ void TcpTransport::connect(const sockaddr *addr, socklen_t addrlen) {
 
 
 		// Initiate connection
 		// Initiate connection
 		int ret = ::connect(mSock, addr, addrlen);
 		int ret = ::connect(mSock, addr, addrlen);
-		if (ret < 0 && errno != EINPROGRESS) {
+		if (ret < 0 && sockerrno != SEINPROGRESS && sockerrno != SEWOULDBLOCK) {
 			std::ostringstream msg;
 			std::ostringstream msg;
 			msg << "TCP connection to " << node << ":" << serv << " failed, errno=" << sockerrno;
 			msg << "TCP connection to " << node << ":" << serv << " failed, errno=" << sockerrno;
 			throw std::runtime_error(msg.str());
 			throw std::runtime_error(msg.str());
@@ -271,14 +272,14 @@ bool TcpTransport::trySendMessage(message_ptr &message) {
 	auto data = reinterpret_cast<const char *>(message->data());
 	auto data = reinterpret_cast<const char *>(message->data());
 	auto size = message->size();
 	auto size = message->size();
 	while (size) {
 	while (size) {
-#if defined(__APPLE__) or defined(_WIN32)
+#if defined(__APPLE__) || defined(_WIN32)
 		int flags = 0;
 		int flags = 0;
 #else
 #else
 		int flags = MSG_NOSIGNAL;
 		int flags = MSG_NOSIGNAL;
 #endif
 #endif
-		int len = ::send(mSock, data, size, flags);
+		int len = ::send(mSock, data, int(size), flags);
 		if (len < 0) {
 		if (len < 0) {
-			if (errno == EAGAIN || errno == EWOULDBLOCK) {
+			if (sockerrno == SEAGAIN || sockerrno == SEWOULDBLOCK) {
 				message = make_message(message->end() - size, message->end());
 				message = make_message(message->end() - size, message->end());
 				return false;
 				return false;
 			} else {
 			} else {
@@ -335,7 +336,7 @@ void TcpTransport::runLoop() {
 				char buffer[bufferSize];
 				char buffer[bufferSize];
 				int len = ::recv(mSock, buffer, bufferSize, 0);
 				int len = ::recv(mSock, buffer, bufferSize, 0);
 				if (len < 0) {
 				if (len < 0) {
-					if (errno == EAGAIN || errno == EWOULDBLOCK) {
+					if (sockerrno == SEAGAIN || sockerrno == SEWOULDBLOCK) {
 						continue;
 						continue;
 					} else {
 					} else {
 						throw std::runtime_error("Connection lost");
 						throw std::runtime_error("Connection lost");

+ 15 - 5
src/tlstransport.cpp

@@ -269,9 +269,19 @@ TlsTransport::TlsTransport(shared_ptr<TcpTransport> lower, string host, state_ca
 		SSL_CTX_set_quiet_shutdown(mCtx, 1);
 		SSL_CTX_set_quiet_shutdown(mCtx, 1);
 		SSL_CTX_set_info_callback(mCtx, InfoCallback);
 		SSL_CTX_set_info_callback(mCtx, InfoCallback);
 
 
-		SSL_CTX_set_default_verify_paths(mCtx);
-		SSL_CTX_set_verify(mCtx, SSL_VERIFY_PEER, NULL);
-		SSL_CTX_set_verify_depth(mCtx, 4);
+		// SSL_CTX_set_default_verify_paths() does nothing on Windows
+#ifndef _WIN32
+		if (SSL_CTX_set_default_verify_paths(mCtx)) {
+#else
+		if (false) {
+#endif
+			PLOG_INFO << "SSL root CA certificates available, server verification enabled";
+			SSL_CTX_set_verify(mCtx, SSL_VERIFY_PEER, NULL);
+			SSL_CTX_set_verify_depth(mCtx, 4);
+		} else {
+			PLOG_WARNING << "SSL root CA certificates unavailable, server verification disabled";
+			SSL_CTX_set_verify(mCtx, SSL_VERIFY_NONE, NULL);
+		}
 
 
 		if (!(mSsl = SSL_new(mCtx)))
 		if (!(mSsl = SSL_new(mCtx)))
 			throw std::runtime_error("Failed to create SSL instance");
 			throw std::runtime_error("Failed to create SSL instance");
@@ -337,7 +347,7 @@ bool TlsTransport::send(message_ptr message) {
 	if (message->size() == 0)
 	if (message->size() == 0)
 		return true;
 		return true;
 
 
-	int ret = SSL_write(mSsl, message->data(), message->size());
+	int ret = SSL_write(mSsl, message->data(), int(message->size()));
 	if (!openssl::check(mSsl, ret))
 	if (!openssl::check(mSsl, ret))
 		return false;
 		return false;
 
 
@@ -393,7 +403,7 @@ void TlsTransport::runRecvLoop() {
 
 
 			message_ptr message = *next;
 			message_ptr message = *next;
 			if (message->size() > 0)
 			if (message->size() > 0)
-				BIO_write(mInBio, message->data(), message->size()); // Input
+				BIO_write(mInBio, message->data(), int(message->size())); // Input
 			else
 			else
 				recv(message); // Pass zero-sized messages through
 				recv(message); // Pass zero-sized messages through
 		}
 		}

+ 7 - 7
src/wstransport.cpp

@@ -50,7 +50,7 @@ using std::to_integer;
 using std::to_string;
 using std::to_string;
 
 
 using random_bytes_engine =
 using random_bytes_engine =
-    std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned char>;
+    std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned short>;
 
 
 WsTransport::WsTransport(std::shared_ptr<Transport> lower, string host, string path,
 WsTransport::WsTransport(std::shared_ptr<Transport> lower, string host, string path,
                          message_callback recvCallback, state_callback stateCallback)
                          message_callback recvCallback, state_callback stateCallback)
@@ -145,12 +145,12 @@ void WsTransport::close() {
 bool WsTransport::sendHttpRequest() {
 bool WsTransport::sendHttpRequest() {
 	changeState(State::Connecting);
 	changeState(State::Connecting);
 
 
-	auto seed = system_clock::now().time_since_epoch().count();
+	auto seed = static_cast<unsigned int>(system_clock::now().time_since_epoch().count());
 	random_bytes_engine generator(seed);
 	random_bytes_engine generator(seed);
 
 
 	binary key(16);
 	binary key(16);
 	auto k = reinterpret_cast<uint8_t *>(key.data());
 	auto k = reinterpret_cast<uint8_t *>(key.data());
-	std::generate(k, k + key.size(), generator);
+	std::generate(k, k + key.size(), [&]() { return uint8_t(generator()); });
 
 
 	const string request = "GET " + mPath +
 	const string request = "GET " + mPath +
 	                       " HTTP/1.1\r\n"
 	                       " HTTP/1.1\r\n"
@@ -283,7 +283,7 @@ size_t WsTransport::readFrame(byte *buffer, size_t size, Frame &frame) {
 		cur += 4;
 		cur += 4;
 	}
 	}
 
 
-	if (end - cur < frame.length)
+	if (size_t(end - cur) < frame.length)
 		return 0;
 		return 0;
 
 
 	frame.payload = cur;
 	frame.payload = cur;
@@ -292,7 +292,7 @@ size_t WsTransport::readFrame(byte *buffer, size_t size, Frame &frame) {
 			frame.payload[i] ^= maskingKey[i % 4];
 			frame.payload[i] ^= maskingKey[i % 4];
 	cur += frame.length;
 	cur += frame.length;
 
 
-	return cur - buffer;
+	return size_t(cur - buffer);
 }
 }
 
 
 void WsTransport::recvFrame(const Frame &frame) {
 void WsTransport::recvFrame(const Frame &frame) {
@@ -378,13 +378,13 @@ bool WsTransport::sendFrame(const Frame &frame) {
 	}
 	}
 
 
 	if (frame.mask) {
 	if (frame.mask) {
-		auto seed = system_clock::now().time_since_epoch().count();
+		auto seed = static_cast<unsigned int>(system_clock::now().time_since_epoch().count());
 		random_bytes_engine generator(seed);
 		random_bytes_engine generator(seed);
 
 
 		byte *maskingKey = reinterpret_cast<byte *>(cur);
 		byte *maskingKey = reinterpret_cast<byte *>(cur);
 
 
 		auto u = reinterpret_cast<uint8_t *>(maskingKey);
 		auto u = reinterpret_cast<uint8_t *>(maskingKey);
-		std::generate(u, u + 4, generator);
+		std::generate(u, u + 4, [&]() { return uint8_t(generator()); });
 		cur += 4;
 		cur += 4;
 
 
 		for (size_t i = 0; i < frame.length; ++i)
 		for (size_t i = 0; i < frame.length; ++i)

+ 5 - 12
test/benchmark.cpp

@@ -95,13 +95,12 @@ size_t benchmark(milliseconds duration) {
 	fill(messageData.begin(), messageData.end(), byte(0xFF));
 	fill(messageData.begin(), messageData.end(), byte(0xFF));
 
 
 	atomic<size_t> receivedSize = 0;
 	atomic<size_t> receivedSize = 0;
-	atomic<bool> finished = false;
 
 
 	steady_clock::time_point startTime, openTime, receivedTime, endTime;
 	steady_clock::time_point startTime, openTime, receivedTime, endTime;
 
 
 	shared_ptr<DataChannel> dc2;
 	shared_ptr<DataChannel> dc2;
 	pc2->onDataChannel(
 	pc2->onDataChannel(
-	    [&dc2, &finished, &receivedSize, &receivedTime, &endTime](shared_ptr<DataChannel> dc) {
+	    [&dc2, &receivedSize, &receivedTime](shared_ptr<DataChannel> dc) {
 		    dc->onMessage([&receivedTime, &receivedSize](const variant<binary, string> &message) {
 		    dc->onMessage([&receivedTime, &receivedSize](const variant<binary, string> &message) {
 			    if (holds_alternative<binary>(message)) {
 			    if (holds_alternative<binary>(message)) {
 				    const auto &bin = get<binary>(message);
 				    const auto &bin = get<binary>(message);
@@ -111,11 +110,7 @@ size_t benchmark(milliseconds duration) {
 			    }
 			    }
 		    });
 		    });
 
 
-		    dc->onClosed([&finished, &endTime]() {
-			    cout << "DataChannel closed." << endl;
-			    endTime = steady_clock::now();
-			    finished = true;
-		    });
+		    dc->onClosed([]() { cout << "DataChannel closed." << endl; });
 
 
 		    std::atomic_store(&dc2, dc);
 		    std::atomic_store(&dc2, dc);
 	    });
 	    });
@@ -157,11 +152,9 @@ size_t benchmark(milliseconds duration) {
 		cout << "Received: " << receivedSize.load() / 1000 << " KB" << endl;
 		cout << "Received: " << receivedSize.load() / 1000 << " KB" << endl;
 	}
 	}
 
 
-	if (auto adc2 = std::atomic_load(&dc2)) {
-		dc1->close();
-		while (!finished && adc2->isOpen())
-			this_thread::sleep_for(100ms);
-	}
+	dc1->close();
+
+	endTime = steady_clock::now();
 
 
 	auto connectDuration = duration_cast<milliseconds>(openTime - startTime);
 	auto connectDuration = duration_cast<milliseconds>(openTime - startTime);
 	auto transferDuration = duration_cast<milliseconds>(endTime - receivedTime);
 	auto transferDuration = duration_cast<milliseconds>(endTime - receivedTime);

+ 0 - 1
test/capi.cpp

@@ -18,7 +18,6 @@
 
 
 #include <rtc/rtc.h>
 #include <rtc/rtc.h>
 
 
-#include <cstdbool>
 #include <cstdio>
 #include <cstdio>
 #include <cstdlib>
 #include <cstdlib>
 #include <cstring>
 #include <cstring>