From 8345f4effb1aa599f58bb62fda59f3af31f069b6 Mon Sep 17 00:00:00 2001 From: Jon Shallow Date: Sat, 3 Oct 2026 10:30:10 +0100 Subject: [PATCH] MSVC: Fix build errors and update CI for building There are a lot of size mismatch warnings that still need to be reviewed and fixed. The tests have been updated to build with a MSVC environment. Signed-off-by: Jon Shallow --- .github/workflows/main.yml | 62 ++++++++++++++++++++++++++++++------ CMakeLists.txt | 11 ++++++- dtls_debug.c | 6 ++-- dtls_debug.h | 2 +- tests/CMakeLists.txt | 48 ++++++++++++++++++++++------ tests/ccm-test.c | 2 +- tests/dtls-client.c | 49 +++++++++++++++++++++++----- tests/dtls-server.c | 33 +++++++++++++------ tests/getopt.c | 65 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 237 insertions(+), 41 deletions(-) create mode 100644 tests/getopt.c diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7ac04b43..7d3041e6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -85,27 +85,66 @@ jobs: steps: - uses: actions/checkout@v6 + - name: setup + run: | + sudo apt-get update && sudo apt-get install -y libcunit1-dev - name: Build tinydtls run: | cmake -E make_directory build_test cd build_test cmake -DWARNING_TO_ERROR=ON -Dmake_tests=ON .. cmake --build . + - name: Install tinydtls + run: | + cd build_test + mkdir -p test-install + cp cmake_install.cmake test-install + cmake --install ./test-install --prefix ./test-install + build-macos-cmake: name: Build for macOS using CMake runs-on: macos-latest steps: - uses: actions/checkout@v6 + - name: setup + run: | + brew install cunit + brew --prefix cunit - name: Build tinydtls run: | cmake -E make_directory build_test cd build_test cmake -DWARNING_TO_ERROR=ON -Dmake_tests=ON .. cmake --build . + - name: Install tinydtls + run: | + cd build_test + mkdir -p test-install + cp cmake_install.cmake test-install + cmake --install ./test-install --prefix ./test-install + + build-windows-unix: + name: Build for Windows using CMake + Unix Makefiles + runs-on: windows-latest + + steps: + - uses: actions/checkout@v6 + - name: Build tinydtls + run: | + cmake -E make_directory build_test + cd build_test + cmake -G "Unix Makefiles" -DWARNING_TO_ERROR=ON -Dmake_tests=ON .. + cmake --build . + - name: Install tinydtls + run: | + cd build_test + mkdir -p test-install + cp cmake_install.cmake test-install + cmake --install ./test-install --prefix ./test-install - build-windows: - name: Build for Windows using CMake + build-windows-vs: + name: Build for Windows using CMake + Visual Studio runs-on: windows-latest steps: @@ -114,7 +153,7 @@ jobs: run: | cmake -E make_directory build_test cd build_test - cmake -G "Unix Makefiles" -DWARNING_TO_ERROR=ON .. + cmake -Dmake_tests=ON .. cmake --build . mingw-cmake: @@ -143,13 +182,18 @@ jobs: with: msystem: ${{matrix.OS}} update: true - install: git mingw-w64-${{env.MINGW_VARIANT}}-gcc mingw-w64-${{env.MINGW_VARIANT}}-cmake mingw-w64-${{env.MINGW_VARIANT}}-openssl + install: git mingw-w64-${{env.MINGW_VARIANT}}-gcc mingw-w64-${{env.MINGW_VARIANT}}-cmake mingw-w64-${{env.MINGW_VARIANT}}-openssl mingw-w64-${{env.MINGW_VARIANT}}-cunit - name: MinGW ${{matrix.OS}} build run: | echo 'Running in MSYS2 ${{matrix.OS}}!' - cmake -E remove_directory build - cmake -E make_directory build - cd build - cmake .. -DWARNING_TO_ERROR=ON + cmake -E remove_directory build_test + cmake -E make_directory build_test + cd build_test + cmake -DWARNING_TO_ERROR=ON -Dmake_tests=ON .. cmake --build . - cmake --build . -- install + - name: MinGW ${{matrix.OS}} install + run: | + cd build_test + mkdir -p test-install + cp cmake_install.cmake test-install + cmake --install ./test-install --prefix ./test-install diff --git a/CMakeLists.txt b/CMakeLists.txt index 2267a69b..50838acd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,14 @@ endif() option(make_tests "Make test programs and examples" OFF) +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug) +endif() + +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +endif() + if(NOT PLATFORM) # PLATFORM seems to be not used set(PLATFORM "posix" CACHE STRING "Choose platform." FORCE) @@ -101,7 +109,7 @@ target_compile_definitions(tinydtls PUBLIC DTLSv12 WITH_SHA256 SHA2_USE_INTTYPES if(MSVC) option(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS "Export all symbols when compiling to a .dll" ON) - target_compile_options(tinydtls PRIVATE -Wall) + # target_compile_options(tinydtls PRIVATE /Wall /wd4820 /wd4668) if(${WARNING_TO_ERROR}) target_compile_options(tinydtls PRIVATE -WX) endif() @@ -116,6 +124,7 @@ set_target_properties(tinydtls PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION $ if( ${make_tests} ) add_subdirectory(tests) + target_compile_options(tinydtls PRIVATE -DTEST_INCLUDE) endif() if(BUILD_SHARED_LIBS) diff --git a/dtls_debug.c b/dtls_debug.c index f8521eaf..3120e7b8 100644 --- a/dtls_debug.c +++ b/dtls_debug.c @@ -251,7 +251,7 @@ dsrv_print_addr(const session_t *addr, char *buf, size_t len) { #endif /* ! HAVE_INET_NTOP */ } -#if !defined(WITH_CONTIKI) && !defined(_MSC_VER) +#if !defined(WITH_CONTIKI) static void dtls_logging_handler(log_t level, const char *message) { @@ -322,7 +322,7 @@ dsrv_log(log_t level, const char *format, ...) { #elif defined (HAVE_VPRINTF) /* WITH_CONTIKI */ void -dsrv_log(log_t level, char *format, ...) { +dsrv_log(log_t level, const char *format, ...) { static char timebuf[32]; va_list ap; @@ -370,7 +370,7 @@ void dump(unsigned char *buf, size_t len) { void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr) { char addrbuf[73]; - int len; + size_t len; len = dsrv_print_addr(addr, addrbuf, sizeof(addrbuf)); if (!len) diff --git a/dtls_debug.h b/dtls_debug.h index a02cab4e..b130176b 100644 --- a/dtls_debug.h +++ b/dtls_debug.h @@ -100,7 +100,7 @@ void dtls_set_log_handler(dtls_log_handler_t app_handler); * Writes the given text to \c stdout. The text is output only when \p * level is below or equal to the log level that set by * set_log_level(). */ -#ifdef HAVE_VPRINTF +#if defined(HAVE_VPRINTF) || defined (_MSC_VER) #if (defined(__GNUC__) && !defined(__MINGW32__)) void dsrv_log(log_t level, const char *format, ...) __attribute__ ((format(printf, 2, 3))); #else /* !__GNUC__ && !__MINGW32__ */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6f431041..b29305b9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -23,24 +23,54 @@ cmake_minimum_required(VERSION 3.10) project(tinydtls-tests LANGUAGES C ) +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + # set(COMPILE_OPTIONS -DTEST_INCLUDE -DDTLSv12 -DWITH_SHA256 /Wall /wd4820 /wd4668) + set(COMPILE_OPTIONS -DTEST_INCLUDE -DDTLSv12 -DWITH_SHA256) + if(${WARNING_TO_ERROR}) + set(COMPILE_OPTIONS -WX ${COMPILE_OPTIONS}) + endif() +else() + set(COMPILE_OPTIONS -Wall -DTEST_INCLUDE -DDTLSv12 -DWITH_SHA256) + if(${WARNING_TO_ERROR}) + set(COMPILE_OPTIONS -Werror ${COMPILE_OPTIONS}) + endif() + if(APPLE) + set(COMPILE_OPTIONS -I/opt/homebrew/opt/cunit/include ${COMPILE_OPTIONS}) + endif() +endif() + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug) +endif() + add_executable(dtls-server dtls-server.c dtls_ciphers_util.c) target_link_libraries(dtls-server LINK_PUBLIC tinydtls) -target_compile_options(dtls-server PUBLIC -Wall -DTEST_INCLUDE -DDTLSv12 -DWITH_SHA256) -if(${WARNING_TO_ERROR}) - target_compile_options(dtls-server PUBLIC -Werror) +if(MINGW OR WIN32) + target_link_libraries(dtls-server LINK_PUBLIC Ws2_32) endif() +target_compile_options(dtls-server PUBLIC ${COMPILE_OPTIONS}) add_executable(ccm-test ccm-test.c) target_link_libraries(ccm-test LINK_PUBLIC tinydtls) -target_compile_options(ccm-test PUBLIC -Wall -DTEST_INCLUDE -DDTLSv12 -DWITH_SHA256) -if(${WARNING_TO_ERROR}) - target_compile_options(ccm-test PUBLIC -Werror) +if(MINGW OR WIN32) + target_link_libraries(ccm-test LINK_PUBLIC Ws2_32) endif() +target_compile_options(ccm-test PUBLIC ${COMPILE_OPTIONS}) add_executable(dtls-client dtls-client.c dtls_ciphers_util.c) target_link_libraries(dtls-client LINK_PUBLIC tinydtls) -target_compile_options(dtls-client PUBLIC -Wall -DTEST_INCLUDE -DDTLSv12 -DWITH_SHA256) -if(${WARNING_TO_ERROR}) - target_compile_options(dtls-client PUBLIC -Werror) +if(MINGW OR WIN32) + target_link_libraries(dtls-client LINK_PUBLIC Ws2_32) endif() +target_compile_options(dtls-client PUBLIC ${COMPILE_OPTIONS}) +if(NOT MSVC AND NOT MINGW) + add_executable(testdriver unit-tests/testdriver.c unit-tests/test_ccm.c unit-tests/test_ecc.c unit-tests/test_prf.c) + target_link_libraries(testdriver LINK_PUBLIC tinydtls) + if(APPLE) + target_link_options(testdriver PUBLIC -L/opt/homebrew/opt/cunit/lib) + endif() + target_link_libraries(testdriver LINK_PUBLIC cunit) + target_compile_options(testdriver PUBLIC ${COMPILE_OPTIONS}) +endif() diff --git a/tests/ccm-test.c b/tests/ccm-test.c index aca94348..c776106a 100644 --- a/tests/ccm-test.c +++ b/tests/ccm-test.c @@ -83,7 +83,7 @@ int main(int argc, char **argv) { printf("Packet Vector #%zu: cannot decrypt message\n", n+1); ret = 1; } else { - printf("\t*** MAC verified (total length = %lu) ***\n", len + data[n].la); + printf("\t*** MAC verified (total length = %zu) ***\n", (size_t)(len + data[n].la)); } } diff --git a/tests/dtls-client.c b/tests/dtls-client.c index 5d856b61..b08bad0d 100644 --- a/tests/dtls-client.c +++ b/tests/dtls-client.c @@ -17,27 +17,55 @@ /* This is needed for apple */ #define __APPLE_USE_RFC_3542 +#include "tinydtls.h" #include #include #include +#ifdef HAVE_UNISTD_H #include +#endif /* HAVE_UNISTD_H */ #include +#ifdef HAVE_NETINET_IN_H #include +#endif /* HAVE_NETINET_IN_H */ #include +#ifdef HAVE_SYS_SOCKET_H #include +#endif /* HAVE_SYS_SOCKET_H */ #ifdef HAVE_SYS_TIME_H #include #endif /* HAVE_SYS_TIME_H */ +#ifdef HAVE_ARPA_INET_H #include +#endif /* HAVE_ARPA_INET_H */ +#ifdef HAVE_NETDB_H #include +#endif /* HAVE_NETDB_H */ #include +#ifdef IS_WINDOWS +#ifdef _MSC_VER +#include "getopt.c" +#define fileno _fileno +#endif /* _MSC_VER */ +#define OPTVAL_T(t) (const char*)(t) +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 /* Standard output. */ +#endif /* STDOUT_FILENO */ +#else /* ! IS_WINDOWS */ +#define OPTVAL_T(t) (t) +#endif /* ! IS_WINDOWS */ + #include "global.h" #include "dtls_debug.h" #include "dtls_ciphers_util.h" #include "dtls.h" +#ifndef MSG_TRUNC +#define MSG_TRUNC 0 +#endif /* MSG_TRUNC */ + #define DEFAULT_PORT 20220 #define PSK_DEFAULT_IDENTITY "Client_identity" @@ -94,10 +122,10 @@ static const unsigned char ecdsa_pub_key_y[] = { #endif /* DTLS_ECC */ #ifdef DTLS_PSK -static ssize_t +static int read_from_file(char *arg, unsigned char *buf, size_t max_buf_len) { FILE *f; - ssize_t result = 0; + int result = 0; f = fopen(arg, "r"); if (f == NULL) @@ -237,8 +265,13 @@ send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { int fd = *(int *)dtls_get_app_data(ctx); +#ifdef IS_WINDOWS + return sendto(fd, (char *)data, len, 0, + &session->addr.sa, session->size); +#else /* ! IS_WINDOWS */ return sendto(fd, data, len, MSG_DONTWAIT, &session->addr.sa, session->size); +#endif /* ! IS_WINDOWS */ } static void @@ -278,7 +311,7 @@ dtls_handle_read(struct dtls_context_t *ctx) { memset(&session, 0, sizeof(session_t)); session.size = sizeof(session.addr); - len = recvfrom(fd, buf, MAX_READ_BUF, MSG_TRUNC, + len = recvfrom(fd, (char *)buf, MAX_READ_BUF, MSG_TRUNC, &session.addr.sa, &session.size); if (len < 0) { @@ -420,7 +453,7 @@ main(int argc, char **argv) { unsigned short local_port = 0; log_t log_level = DTLS_LOG_WARN; int fd; - ssize_t result; + int result; int on = 1; int opt = 0; int res; @@ -540,7 +573,7 @@ main(int argc, char **argv) { return 0; } - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) { + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on) ) < 0) { dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno)); } #if 0 @@ -553,15 +586,15 @@ main(int argc, char **argv) { on = 1; if (dst.addr.sa.sa_family == AF_INET6) { #ifdef IPV6_RECVPKTINFO - if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on) ) < 0) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) { #else /* IPV6_RECVPKTINFO */ - if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on) ) < 0) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) { #endif /* IPV6_RECVPKTINFO */ dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno)); } } else { - if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on) ) < 0) { + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) { dtls_alert("setsockopt IP_PKTINFO: %s\n", strerror(errno)); } } diff --git a/tests/dtls-server.c b/tests/dtls-server.c index 1db0203d..1c2a1a90 100644 --- a/tests/dtls-server.c +++ b/tests/dtls-server.c @@ -15,11 +15,14 @@ /* This is needed for apple */ #define __APPLE_USE_RFC_3542 +#include "tinydtls.h" #include #include #include #include +#ifdef HAVE_UNISTD_H #include +#endif /* HAVE_UNISTD_H */ #include #ifdef HAVE_SYS_TIME_H #include @@ -33,13 +36,23 @@ #ifdef IS_WINDOWS #include -#pragma comment(lib, "Ws2_32.lib") +#ifdef _MSC_VER +#include "getopt.c" +#define fileno _fileno +#endif /* _MSC_VER */ #define MSG_DONTWAIT 0 +#ifndef MSG_TRUNC #define MSG_TRUNC 0 +#endif /* MSG_TRUNC */ +#define OPTVAL_T(t) (const char*)(t) +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 /* Standard output. */ +#endif /* STDOUT_FILENO */ #else /* ! IS_WINDOWS */ #include #include #include +#define OPTVAL_T(t) (t) #endif /* ! IS_WINDOWS */ #define DEFAULT_PORT 20220 @@ -192,7 +205,7 @@ send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { int fd = *(int *)dtls_get_app_data(ctx); - return sendto(fd, data, len, MSG_DONTWAIT, + return sendto(fd, (char *)data, len, MSG_DONTWAIT, &session->addr.sa, session->size); } @@ -231,7 +244,7 @@ dtls_handle_read(struct dtls_context_t *ctx) { memset(&session, 0, sizeof(session_t)); session.size = sizeof(session.addr); - len = recvfrom(*fd, buf, sizeof(buf), MSG_TRUNC, + len = recvfrom(*fd, (char *)buf, sizeof(buf), MSG_TRUNC, &session.addr.sa, &session.size); if (len < 0) { @@ -404,7 +417,7 @@ main(int argc, char **argv) { return 0; } - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) { + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on) ) < 0) { dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno)); } #if 0 @@ -416,18 +429,18 @@ main(int argc, char **argv) { #endif on = 1; if (listen_addr.sin6_family == AF_INET6) { - if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) < 0) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) < 0) { dtls_alert("setsockopt IPV6_V6ONLY: %s\n", strerror(errno)); } #ifdef IPV6_RECVPKTINFO - if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on) ) < 0) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) { #else /* IPV6_RECVPKTINFO */ - if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on) ) < 0) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) { #endif /* IPV6_RECVPKTINFO */ dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno)); } } - if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) < 0) { + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, OPTVAL_T(&on), sizeof(on)) < 0) { dtls_alert("setsockopt IP_PKTINFO: %s\n", strerror(errno)); } @@ -440,7 +453,9 @@ main(int argc, char **argv) { dtls_init(); -#ifndef IS_WINDOWS +#ifdef IS_WINDOWS + signal(SIGINT, dtls_handle_signal); +#else /* ! IS_WINDOWS */ memset (&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_handler = dtls_handle_signal; diff --git a/tests/getopt.c b/tests/getopt.c new file mode 100644 index 00000000..696cc30c --- /dev/null +++ b/tests/getopt.c @@ -0,0 +1,65 @@ +/* + * This file was copied from the following newsgroup posting: + * + * Newsgroups: mod.std.unix + * Subject: public domain AT&T getopt source + * Date: 3 Nov 85 19:34:15 GMT + * + * Here's something you've all been waiting for: the AT&T public domain + * source for getopt(3). It is the code which was given out at the 1985 + * UNIFORUM conference in Dallas. I obtained it by electronic mail + * directly from AT&T. The people there assure me that it is indeed + * in the public domain. + */ + +#include +#include + +int optind = 1; +int optopt; +char *optarg; + +static int +getopt(int argc, char *argv[], const char *opts) { + static int sp = 1; + int c; + char *cp; + + if (sp == 1) { + if (optind >= argc || + argv[optind][0] != '-' || argv[optind][1] == '\0') + return EOF; + else if (!strcmp(argv[optind], "--")) { + optind++; + return EOF; + } + } + optopt = c = argv[optind][sp]; + if (c == ':' || !(cp = strchr(opts, c))) { + fprintf(stderr, ": illegal option -- %c\n", c); + if (argv[optind][++sp] == '\0') { + optind++; + sp = 1; + } + return '?'; + } + if (*++cp == ':') { + if (argv[optind][sp+1] != '\0') + optarg = &argv[optind++][sp+1]; + else if (++optind >= argc) { + fprintf(stderr, ": option requires an argument -- %c\n", c); + sp = 1; + return '?'; + } else + optarg = argv[optind++]; + sp = 1; + } else { + if (argv[optind][++sp] == '\0') { + sp = 1; + optind++; + } + optarg = NULL; + } + + return c; +}