- extend existing Linux workflow with CMake support.
Including running pytest the first time with CMake.
- cmake: generate `tests/config` and `tests/http/config.ini`.
Required for pytest tests.
Uses basic detection logic. Feel free to take it from here.
Also dump config files in a CI step for debugging purposes.
- cmake: build `tests/http/clients` programs.
- fix portability issues with `tests/http/clients` programs.
Some of them use `getopt()`, which is not supported by MSVC.
Fix the rest to compile in CI (old-mingw-w64, MSVC, Windows).
- GHA/linux: add CMake job matching an existing autotools one.
- GHA/linux: test `-DCURL_LIBCURL_VERSIONED_SYMBOLS=ON`
in the new CMake job.
- reorder testdeps to build server, client tests first and then
libtests and units, to catch errors in the more complex/unique
sources earlier.
- sort list in `tests/http/clients/Makefile.inc`.
Closes #14382
rustls-version: 0.13.0
jobs:
- autotools:
- name: ${{ matrix.build.name }}
+ linux:
+ name: ${{ matrix.build.generate && 'CM' || 'AM' }} ${{ matrix.build.name }}
runs-on: 'ubuntu-latest'
container: ${{ matrix.build.container }}
timeout-minutes: 90
configure: LDFLAGS="-Wl,-rpath,$HOME/libressl/lib" --with-openssl=$HOME/libressl --enable-debug
singleuse: --unit
+ - name: libressl
+ install_packages: zlib1g-dev valgrind
+ install_steps: libressl pytest
+ generate: -DOPENSSL_ROOT_DIR=$HOME/libressl -DENABLE_DEBUG=ON -DCURL_LIBCURL_VERSIONED_SYMBOLS=ON
+ singleuse: --unit
+
- name: libressl-clang
install_packages: zlib1g-dev clang
install_steps: libressl
sudo make install
- run: autoreconf -fi
+ if: ${{ matrix.build.configure }}
name: 'autoreconf'
- run: ./configure --disable-dependency-tracking --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
+ if: ${{ matrix.build.configure }}
+ name: 'configure (autotools)'
- - run: make V=1
+ - run: |
+ cmake . \
+ -DCMAKE_C_COMPILER_TARGET=$(uname -m)-pc-linux-gnu -DBUILD_STATIC_LIBS=ON \
+ -DCMAKE_UNITY_BUILD=ON -DCURL_WERROR=ON \
+ -DBUILD_EXAMPLES=ON \
+ -DCURL_BROTLI=ON -DCURL_ZSTD=ON \
+ ${{ matrix.build.generate }}
+ if: ${{ matrix.build.generate }}
+ name: 'configure (cmake)'
+
+ - name: 'test configs'
+ run: |
+ cat tests/config || true
+ cat tests/http/config.ini || true
+
+ - run: make V=1 VERBOSE=1
name: 'make'
- run: |
git config --global --add safe.directory "*"
- ./scripts/singleuse.pl ${{ matrix.build.singleuse }} lib/.libs/libcurl.a
+ if [ -n '${{ matrix.build.generate }}' ]; then
+ libcurla=lib/libcurl.a
+ else
+ libcurla=lib/.libs/libcurl.a
+ fi
+ ./scripts/singleuse.pl ${{ matrix.build.singleuse }} ${libcurla}
name: single-use function check
- run: ./src/curl -V
name: 'check curl -V output'
- run: make V=1 examples
+ if: ${{ matrix.build.configure }}
name: 'make examples'
- run: make V=1 -C tests
- name: 'make tests'
+ if: ${{ matrix.build.configure }}
+ name: 'make tests (autotools)'
+
+ - run: make VERBOSE=1 testdeps
+ if: ${{ matrix.build.generate }}
+ name: 'make tests (cmake)'
- - run: make V=1 test-ci
+ - run: make V=1 VERBOSE=1 test-ci
name: 'run tests'
env:
TFLAGS: "${{ matrix.build.tflags }}"
###########################################################################
set(CMAKE_UNITY_BUILD OFF)
+find_program(TEST_NGHTTPX "nghttpx")
+if(NOT TEST_NGHTTPX)
+ set(TEST_NGHTTPX "nghttpx")
+endif()
+# TEST_NGHTTPX
+configure_file("config.in" "${CMAKE_CURRENT_BINARY_DIR}/config" @ONLY)
+
add_custom_target(testdeps)
-add_subdirectory(libtest)
+add_subdirectory(http)
+add_subdirectory(http/clients)
add_subdirectory(server)
+add_subdirectory(libtest)
add_subdirectory(unit)
function(add_runtests targetname test_flags)
--- /dev/null
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+find_program(CADDY "caddy") # /usr/bin/caddy
+if(NOT CADDY)
+ set(CADDY "")
+endif()
+find_program(VSFTPD "vsftpd") # /usr/sbin/vsftpd
+if(NOT VSFTPD)
+ set(VSFTPD "")
+endif()
+find_program(HTTPD "apache2") # /usr/sbin/apache2
+if(NOT HTTPD)
+ set(HTTPD "")
+endif()
+find_program(APACHECTL "apache2ctl") # /usr/sbin/apache2ctl
+if(NOT APACHECTL)
+ set(APACHECTL "")
+endif()
+find_program(APXS "apxs")
+if(NOT APXS)
+ set(APXS "")
+endif()
+find_program(HTTPD_NGHTTPX "nghttpx" PATHS "/usr/bin" "/usr/local/bin")
+if(NOT HTTPD_NGHTTPX)
+ set(HTTPD_NGHTTPX "")
+endif()
+
+# APXS, HTTPD, APACHECTL, HTTPD_NGHTTPX, CADDY, VSFTPD
+configure_file("config.ini.in" "${CMAKE_CURRENT_BINARY_DIR}/config.ini" @ONLY)
testenv/ws_echo_server.py
EXTRA_DIST = \
+CMakeLists.txt \
config.ini.in \
conftest.py \
requirements.txt \
--- /dev/null
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+# Get 'check_PROGRAMS' variable
+transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
+include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
+
+foreach(_client IN LISTS check_PROGRAMS)
+ set(_client_target "curl-test-client-${_client}")
+ add_executable(${_client_target} "${_client}.c")
+ add_dependencies(testdeps ${_client_target})
+ target_include_directories(${_client_target} PRIVATE
+ "${CURL_SOURCE_DIR}/lib" # for "curl_setup_once.h"
+ "${CURL_BINARY_DIR}/lib" # for "curl_config.h"
+ "${CURL_BINARY_DIR}/include" # for "curl/curl.h"
+ )
+ target_link_libraries(${_client_target} ${LIB_SELECTED} ${CURL_LIBS})
+ target_compile_definitions(${_client_target} PRIVATE "CURL_NO_OLDIES")
+ if(LIB_SELECTED STREQUAL LIB_STATIC AND WIN32)
+ set_property(TARGET ${_client_target} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_STATICLIB")
+ endif()
+ set_target_properties(${_client_target} PROPERTIES OUTPUT_NAME "${_client}" UNITY_BUILD OFF)
+endforeach()
AUTOMAKE_OPTIONS = foreign nostdinc
+EXTRA_DIST = CMakeLists.txt
# Specify our include paths here, and do it relative to $(top_srcdir) and
# $(top_builddir), to ensure that these paths which belong to the library
# This might hold -Werror
CFLAGS += @CURL_CFLAG_EXTRAS@
-# Makefile.inc provides the check_PROGRAMS and COMPLICATED_EXAMPLES defines
+# Makefile.inc provides the check_PROGRAMS define
include Makefile.inc
all: $(check_PROGRAMS)
# These are all libcurl example programs to be test compiled
check_PROGRAMS = \
- h2-serverpush \
h2-download \
- ws-data \
- ws-pingpong \
+ h2-pausing \
+ h2-serverpush \
h2-upgrade-extreme \
tls-session-reuse \
- h2-pausing \
- upload-pausing
+ upload-pausing \
+ ws-data \
+ ws-pingpong
* HTTP/2 server push
* </DESC>
*/
-
/* curl stuff */
#include <curl/curl.h>
-#include <curl/mprintf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifndef _MSC_VER
/* somewhat Unix-specific */
-#include <sys/time.h>
-#include <unistd.h>
+#include <unistd.h> /* getopt() */
+#endif
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
#ifndef CURLPIPE_MULTIPLEX
#error "too old libcurl, cannot do HTTP/2 server push!"
#endif
+#ifndef _MSC_VER
static int verbose = 1;
static void log_line_start(FILE *log, const char *idsbuf, curl_infotype type)
if(!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {
if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&
conn_id >= 0) {
- curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2,
- xfer_id, conn_id);
+ snprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id, conn_id);
}
else {
- curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
+ snprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
}
}
else
fprintf(stderr, "[t-%d] RECV %ld bytes, total=%ld, pause_at=%ld\n",
t->idx, (long)blen, (long)t->recv_size, (long)t->pause_at);
if(!t->out) {
- curl_msnprintf(t->filename, sizeof(t->filename)-1, "download_%u.data",
- t->idx);
+ snprintf(t->filename, sizeof(t->filename)-1, "download_%u.data", t->idx);
t->out = fopen(t->filename, "wb");
if(!t->out)
return 0;
" -V http_version (http/1.1, h2, h3) http version to use\n"
);
}
+#endif /* !_MSC_VER */
/*
* Download a file over HTTP/2, take care of server push.
*/
int main(int argc, char *argv[])
{
+#ifndef _MSC_VER
CURLM *multi_handle;
struct CURLMsg *m;
const char *url;
curl_multi_cleanup(multi_handle);
return 0;
+#else
+ (void)argc;
+ (void)argv;
+ fprintf(stderr, "Not supported with this compiler.\n");
+ return 1;
+#endif /* !_MSC_VER */
}
* HTTP/2 download pausing
* </DESC>
*/
-/* This is based on the poc client of issue #11982
+/* This is based on the PoC client of issue #11982
*/
+#include <curl/curl.h>
+
#include <assert.h>
#include <stdio.h>
#include <string.h>
-#include <sys/time.h>
-#include <unistd.h>
#include <stdlib.h>
-#include <curl/curl.h>
-#include <curl/mprintf.h>
+#ifndef _MSC_VER
+/* somewhat Unix-specific */
+#include <unistd.h> /* getopt() */
+#endif
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+#ifndef _MSC_VER
#define HANDLECOUNT 2
static void log_line_start(FILE *log, const char *idsbuf, curl_infotype type)
if(!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {
if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&
conn_id >= 0) {
- curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2,
- xfer_id, conn_id);
+ snprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id, conn_id);
}
else {
- curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
+ snprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
}
}
else
handle->idx, (long)realsize);
return realsize;
}
+#endif /* !_MSC_VER */
int main(int argc, char *argv[])
{
+#ifndef _MSC_VER
struct handle handles[HANDLECOUNT];
CURLM *multi_handle;
int i, still_running = 1, msgs_left, numfds;
exit(1);
}
memset(&resolve, 0, sizeof(resolve));
- curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1,
- "%s:%s:127.0.0.1", host, port);
+ snprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1", host, port);
resolve = curl_slist_append(resolve, resolve_buf);
for(i = 0; i<HANDLECOUNT; i++) {
if(curl_multi_poll(multi_handle, NULL, 0, 100, &numfds) != CURLM_OK)
err();
- while((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
+ /* !checksrc! disable EQUALSNULL 1 */
+ while((msg = curl_multi_info_read(multi_handle, &msgs_left)) != NULL) {
if(msg->msg == CURLMSG_DONE) {
for(i = 0; i<HANDLECOUNT; i++) {
if(msg->easy_handle == handles[i].h) {
curl_global_cleanup();
return rc;
+#else
+ (void)argc;
+ (void)argv;
+ fprintf(stderr, "Not supported with this compiler.\n");
+ return 1;
+#endif /* !_MSC_VER */
}
* HTTP/2 server push
* </DESC>
*/
-
/* curl stuff */
#include <curl/curl.h>
-#include <curl/mprintf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-/* somewhat Unix-specific */
-#include <sys/time.h>
-#include <unistd.h>
-
#ifndef CURLPIPE_MULTIPLEX
#error "too old libcurl, cannot do HTTP/2 server push!"
#endif
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
static
void dump(const char *text, unsigned char *ptr, size_t size,
char nohex)
int rv;
(void)parent; /* we have no use for this */
- curl_msnprintf(filename, sizeof(filename)-1, "push%u", count++);
+ snprintf(filename, sizeof(filename)-1, "push%u", count++);
/* here's a new stream, save it in a new file for each new push */
out = fopen(filename, "wb");
* HTTP/2 Upgrade test
* </DESC>
*/
+#include <curl/curl.h>
+
#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
/* #include <error.h> */
#include <errno.h>
-#include <curl/curl.h>
-#include <curl/mprintf.h>
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
static void log_line_start(FILE *log, const char *idsbuf, curl_infotype type)
{
if(!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {
if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&
conn_id >= 0) {
- curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2,
- xfer_id, conn_id);
+ snprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id, conn_id);
}
else {
- curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
+ snprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
}
}
else
curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(easy, CURLOPT_WRITEDATA, NULL);
curl_easy_setopt(easy, CURLOPT_HTTPGET, 1L);
- curl_msnprintf(range, sizeof(range), "%" PRIu64 "-%" PRIu64,
- UINT64_C(0), UINT64_C(16384));
+ snprintf(range, sizeof(range), "%d-%d", 0, 16384);
curl_easy_setopt(easy, CURLOPT_RANGE, range);
mc = curl_multi_add_handle(multi, easy);
}
/* Check for finished handles and remove. */
- while((msg = curl_multi_info_read(multi, &msgs_in_queue))) {
+ /* !checksrc! disable EQUALSNULL 1 */
+ while((msg = curl_multi_info_read(multi, &msgs_in_queue)) != NULL) {
if(msg->msg == CURLMSG_DONE) {
long status = 0;
curl_off_t xfer_id;
* TLS session reuse
* </DESC>
*/
+#include <curl/curl.h>
+
#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
#include <string.h>
-#include <inttypes.h>
/* #include <error.h> */
#include <errno.h>
-#include <curl/curl.h>
-#include <curl/mprintf.h>
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
static void log_line_start(FILE *log, const char *idsbuf, curl_infotype type)
{
if(!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {
if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&
conn_id >= 0) {
- curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2,
- xfer_id, conn_id);
+ snprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id, conn_id);
}
else {
- curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
+ snprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
}
}
else
exit(1);
}
- memset(&resolve, 0, sizeof(resolve));
- curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1,
- "%s:%s:127.0.0.1", host, port);
+ memset(&resolve, 0, sizeof(resolve));
+ snprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1", host, port);
curl_slist_append(&resolve, resolve_buf);
multi = curl_multi_init();
}
/* Check for finished handles and remove. */
- while((msg = curl_multi_info_read(multi, &msgs_in_queue))) {
+ /* !checksrc! disable EQUALSNULL 1 */
+ while((msg = curl_multi_info_read(multi, &msgs_in_queue)) != NULL) {
if(msg->msg == CURLMSG_DONE) {
long status = 0;
curl_off_t xfer_id;
* upload pausing
* </DESC>
*/
-/* This is based on the poc client of issue #11769
+/* This is based on the PoC client of issue #11769
*/
+#include <curl/curl.h>
+
#include <stdio.h>
#include <string.h>
-#include <sys/time.h>
-#include <unistd.h>
#include <stdlib.h>
-#include <curl/curl.h>
-#include <curl/mprintf.h>
+#ifndef _MSC_VER
+/* somewhat Unix-specific */
+#include <unistd.h> /* getopt() */
+#endif
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+#ifndef _MSC_VER
static void log_line_start(FILE *log, const char *idsbuf, curl_infotype type)
{
/*
if(!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {
if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&
conn_id >= 0) {
- curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2,
- xfer_id, conn_id);
+ snprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id, conn_id);
}
else {
- curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
+ snprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
}
}
else
" -V http_version (http/1.1, h2, h3) http version to use\n"
);
}
+#endif /* !_MSC_VER */
int main(int argc, char *argv[])
{
+#ifndef _MSC_VER
CURL *curl;
CURLcode rc = CURLE_OK;
CURLU *cu;
exit(1);
}
memset(&resolve, 0, sizeof(resolve));
- curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1,
- "%s:%s:127.0.0.1", host, port);
+ snprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1", host, port);
resolve = curl_slist_append(resolve, resolve_buf);
curl = curl_easy_init();
curl_global_cleanup();
return (int)rc;
+#else
+ (void)argc;
+ (void)argv;
+ fprintf(stderr, "Not supported with this compiler.\n");
+ return 1;
+#endif /* !_MSC_VER */
}
* Websockets data echos
* </DESC>
*/
-
/* curl stuff */
#include "curl_setup.h"
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
-/* somewhat Unix-specific */
-#include <sys/time.h>
-#include <unistd.h>
-
#ifdef USE_WEBSOCKETS
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#else
+#include <sys/time.h>
+#endif
+
static
void dump(const char *text, unsigned char *ptr, size_t size,
char nohex)
result = curl_ws_recv(curl, recvbuf, sizeof(recvbuf), &nread, &frame);
if(result == CURLE_AGAIN) {
fprintf(stderr, "EAGAIN, sleep, try again\n");
+#ifdef _WIN32
+ Sleep(100);
+#else
usleep(100*1000);
+#endif
continue;
}
fprintf(stderr, "ws: curl_ws_recv(offset=%ld, len=%ld) -> %d, %ld\n",
* Websockets pingpong
* </DESC>
*/
-
/* curl stuff */
#include "curl_setup.h"
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
-/* somewhat Unix-specific */
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#else
#include <sys/time.h>
-#include <unistd.h>
+#endif
#ifdef USE_WEBSOCKETS
fprintf(stderr, "Receive pong\n");
res = recv_pong(curl, payload);
if(res == CURLE_AGAIN) {
+#ifdef _WIN32
+ Sleep(100);
+#else
usleep(100*1000);
+#endif
continue;
}
websocket_close(curl);