compiles in debug/release. tests pass (in debug config at least)

This commit is contained in:
Amol Deshpande 2018-03-12 15:25:01 -07:00
parent 0e7c6aad9e
commit 461e84d874
97 changed files with 4282 additions and 875 deletions

View file

@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 2.8)
project(lsquic)
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
# We prefer clang
IF(NOT ("${CMAKE_C_COMPILER}" MATCHES "ccc-analyzer" OR
"${CMAKE_C_COMPILER}" MATCHES "gcc" OR
@ -14,6 +15,8 @@ IF(NOT ("${CMAKE_C_COMPILER}" MATCHES "ccc-analyzer" OR
ENDIF()
ENDIF()
ENDIF()
# By default, we compile in development mode. To compile production code,
# pass -DDEVEL_MODE=0 to cmake (before that, `make clean' and remove any
# cmake cache files).
@ -25,6 +28,8 @@ ENDIF()
MESSAGE(STATUS "DEVEL_MODE: ${DEVEL_MODE}")
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Wall -Wextra -Wno-unused-parameter")
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -fno-omit-frame-pointer")
@ -58,6 +63,36 @@ ELSE()
MESSAGE(STATUS "AddressSanitizer is OFF")
ENDIF()
#MSVC
ELSE()
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -W4 -WX -Zi -DWIN32_LEAN_AND_MEAN -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS -I${CMAKE_CURRENT_SOURCE_DIR}/wincompat")
IF(DEVEL_MODE EQUAL 1)
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Od ")
#SET (MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DFIU_ENABLE=1")
#SET (FIULIB "fiu")
ELSE()
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -OX")
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DNDEBUG")
# Comment out the following line to compile out debug messages:
#SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DLSQUIC_LOWEST_LOG_LEVEL=LSQ_LOG_INFO")
ENDIF()
SET (BORINGSSL_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/../boringssl/include)
SET (VCPKG_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/../vcpkg/installed/x64-windows-static/include )
IF(CMAKE_BUILD_TYPE MATCHES "Debug")
SET (BORINGSSL_LIB ${CMAKE_CURRENT_SOURCE_DIR}/../boringssl/build/ssl ${CMAKE_CURRENT_SOURCE_DIR}/../boringssl/build/x64/debug)
SET (VCPKG_LIB ${CMAKE_CURRENT_SOURCE_DIR}/../vcpkg/installed/x64-windows-static/lib)
SET (ZLIB_NAME "zlibd")
ELSE()
SET (BORINGSSL_LIB ${CMAKE_CURRENT_SOURCE_DIR}/../boringssl/build/ssl ${CMAKE_CURRENT_SOURCE_DIR}/../boringssl/build/x64)
SET (VCPKG_LIB ${CMAKE_CURRENT_SOURCE_DIR}/../vcpkg/installed/x64-windows-static/debug/lib)
SET (ZLIB_NAME zlibd)
ENDIF()
ENDIF() #MSVC
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MY_CMAKE_FLAGS} $ENV{EXTRA_CFLAGS}")
MESSAGE(STATUS "Compiler flags: ${CMAKE_C_FLAGS}")
@ -69,8 +104,9 @@ IF(NOT DEFINED BORINGSSL_LIB)
SET(BORINGSSL_LIB /usr/local/lib)
ENDIF()
include_directories( ${BORINGSSL_INCLUDE} )
link_directories( ${BORINGSSL_LIB} )
include_directories(${BORINGSSL_INCLUDE} ${VCPKG_INCLUDE} )
link_directories( ${BORINGSSL_LIB} ${VCPKG_LIB} )
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories( include )
@ -81,13 +117,27 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
link_directories( /usr/local/lib )
ENDIF()
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
add_executable(http_client
test/http_client.c
test/prog.c
test/test_common.c
)
target_link_libraries(http_client lsquic event pthread libssl.a libcrypto.a ${FIULIB} z m)
ELSE()
add_executable(http_client
test/http_client.c
test/prog.c
wincompat/test_common_win.c
wincompat/getopt.c
wincompat/getopt1.c
)
target_link_libraries(http_client lsquic event ssl crypto ${FIULIB} ${ZLIB_NAME} ws2_32)
ENDIF()
add_subdirectory(src)

View file

@ -10,9 +10,13 @@
#include <stdarg.h>
#include <lsquic_types.h>
#ifndef WIN32
#include <sys/uio.h>
#include <sys/types.h>
#include <time.h>
#else
#include <vc_compat.h>
#endif
struct iovec;
struct sockaddr;

View file

@ -10,6 +10,9 @@
#include <assert.h>
#include <stdlib.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -7,6 +7,9 @@
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_buf.h"

View file

@ -7,8 +7,12 @@
#define LSQUIC_CONN_H
#include <sys/queue.h>
#ifndef WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#else
#include <ws2ipdef.h>
#endif
struct lsquic_conn;
struct lsquic_enc_session;

View file

@ -6,6 +6,11 @@
#include <zlib.h>
#include <openssl/ssl.h>
#ifndef WIN32
#else
#include <stdlib.h>
#include <vc_compat.h>
#endif
#include "lsquic_int_types.h"
#include "lsquic_crypto.h"
@ -440,7 +445,7 @@ int decompress_certs(const unsigned char *in, const unsigned char *in_end,
{
int ret;
size_t i;
uint8_t* uncompressed_data, *uncompressed_data_buf;
uint8_t* uncompressed_data = NULL, *uncompressed_data_buf = NULL;
lsquic_str_t *dict;
uint32_t uncompressed_size;
size_t count = *out_certs_count;

View file

@ -11,6 +11,9 @@
#include <openssl/hmac.h>
#include <zlib.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_types.h"
#include "lsquic_crypto.h"
@ -211,7 +214,7 @@ uint128 fnv1a_128(const uint8_t * data, int len)
void fnv1a_128_s(const uint8_t * data, int len, uint8_t *md)
{
return fnv1a_128_2_s(data, len, NULL, 0, md);
fnv1a_128_2_s(data, len, NULL, 0, md);
}
@ -281,6 +284,7 @@ void lshkdf_extract(const unsigned char *ikm, int ikm_len, const unsigned char *
}
#define SHA256LEN 32
int lshkdf_expand(const unsigned char *prk, const unsigned char *info, int info_len,
uint16_t c_key_len, uint8_t *c_key,
uint16_t s_key_len, uint8_t *s_key,
@ -288,7 +292,6 @@ int lshkdf_expand(const unsigned char *prk, const unsigned char *info, int info_
uint16_t s_key_iv_len, uint8_t *s_key_iv,
uint16_t sub_key_len, uint8_t *sub_key)
{
const int SHA256LEN = 32;
int L = c_key_len + s_key_len + c_key_iv_len + s_key_iv_len + sub_key_len;
int N = (L + SHA256LEN - 1) / SHA256LEN;
unsigned char *p_org;

View file

@ -8,6 +8,9 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_int_types.h"
#include "lsquic_types.h"
@ -133,10 +136,10 @@ lsquic_cubic_was_quiet (struct lsquic_cubic *cubic, lsquic_time_t now)
void
lsquic_cubic_ack (struct lsquic_cubic *cubic, lsquic_time_t now,
lsquic_cubic_ack (struct lsquic_cubic *cubic, lsquic_time_t now_time,
lsquic_time_t rtt, int app_limited, unsigned n_bytes)
{
LSQ_DEBUG("%s(cubic, %"PRIu64", %"PRIu64", %d, %u)", __func__, now, rtt,
LSQ_DEBUG("%s(cubic, %"PRIu64", %"PRIu64", %d, %u)", __func__, now_time, rtt,
app_limited, n_bytes);
if (0 == cubic->cu_min_delay || rtt < cubic->cu_min_delay)
{
@ -151,7 +154,7 @@ lsquic_cubic_ack (struct lsquic_cubic *cubic, lsquic_time_t now,
}
else if (!app_limited)
{
cubic_update(cubic, now, n_bytes);
cubic_update(cubic, now_time, n_bytes);
LSQ_DEBUG("ACK: cwnd: %lu", cubic->cu_cwnd);
}

View file

@ -9,24 +9,17 @@
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_data_in_if.h"
static const struct data_in_iface di_if_error;
static const struct data_in error_data_in = {
.di_if = &di_if_error,
.di_flags = 0,
};
struct data_in *
data_in_error_new (struct lsquic_conn_public *conn_pub)
{
return (struct data_in *) &error_data_in;
}
static void
@ -87,3 +80,12 @@ static const struct data_in_iface di_if_error = {
.di_mem_used = error_di_mem_used,
.di_switch_impl = error_di_switch_impl,
};
static const struct data_in error_data_in = {
.di_if = &di_if_error,
.di_flags = 0,
};
struct data_in *
data_in_error_new (struct lsquic_conn_public *conn_pub)
{
return (struct data_in *) &error_data_in;
}

View file

@ -53,15 +53,14 @@ struct data_block
unsigned char db_data[DB_DATA_SIZE];
};
typedef char db_set_covers_all_db_data[(N_DB_SETS * 64 >= DB_DATA_SIZE) - 1];
typedef char db_set_no_waste[(N_DB_SETS * 64 - 64 <= DB_DATA_SIZE) - 1];
typedef char db_block_is_4K[(sizeof(struct data_block) == 0x1000) - 1];
typedef char db_set_covers_all_db_data[(N_DB_SETS * 64 >= DB_DATA_SIZE) ?1: - 1];
typedef char db_set_no_waste[(N_DB_SETS * 64 - 64 <= DB_DATA_SIZE)?1: - 1];
typedef char db_block_is_4K[(sizeof(struct data_block) == 0x1000) ?1:- 1];
TAILQ_HEAD(dblock_head, data_block);
static const struct data_in_iface di_if_hash;
struct hash_data_in
@ -109,43 +108,6 @@ my_log2 /* silly name to suppress compiler warning */ (unsigned sz)
}
struct data_in *
data_in_hash_new (struct lsquic_conn_public *conn_pub, uint32_t stream_id,
uint64_t byteage)
{
struct hash_data_in *hdi;
unsigned n;
hdi = malloc(sizeof(*hdi));
if (!hdi)
return NULL;
hdi->hdi_data_in.di_if = &di_if_hash;
hdi->hdi_data_in.di_flags = 0;
hdi->hdi_conn_pub = conn_pub;
hdi->hdi_stream_id = stream_id;
hdi->hdi_fin_off = 0;
hdi->hdi_flags = 0;
hdi->hdi_last_block = NULL;
if (byteage >= DB_DATA_SIZE /* __builtin_clz is undefined if
argument is 0 */)
hdi->hdi_nbits = my_log2(byteage / DB_DATA_SIZE) + 2;
else
hdi->hdi_nbits = 3;
hdi->hdi_count = 0;
hdi->hdi_buckets = malloc(sizeof(hdi->hdi_buckets[0]) *
N_BUCKETS(hdi->hdi_nbits));
if (!hdi->hdi_buckets)
{
free(hdi);
return NULL;
}
for (n = 0; n < N_BUCKETS(hdi->hdi_nbits); ++n)
TAILQ_INIT(&hdi->hdi_buckets[n]);
return &hdi->hdi_data_in;
}
static void
@ -637,3 +599,40 @@ static const struct data_in_iface di_if_hash = {
.di_mem_used = hash_di_mem_used,
.di_switch_impl = hash_di_switch_impl,
};
struct data_in *
data_in_hash_new (struct lsquic_conn_public *conn_pub, uint32_t stream_id,
uint64_t byteage)
{
struct hash_data_in *hdi;
unsigned n;
hdi = malloc(sizeof(*hdi));
if (!hdi)
return NULL;
hdi->hdi_data_in.di_if = &di_if_hash;
hdi->hdi_data_in.di_flags = 0;
hdi->hdi_conn_pub = conn_pub;
hdi->hdi_stream_id = stream_id;
hdi->hdi_fin_off = 0;
hdi->hdi_flags = 0;
hdi->hdi_last_block = NULL;
if (byteage >= DB_DATA_SIZE /* __builtin_clz is undefined if
argument is 0 */)
hdi->hdi_nbits = my_log2(byteage / DB_DATA_SIZE) + 2;
else
hdi->hdi_nbits = 3;
hdi->hdi_count = 0;
hdi->hdi_buckets = malloc(sizeof(hdi->hdi_buckets[0]) *
N_BUCKETS(hdi->hdi_nbits));
if (!hdi->hdi_buckets)
{
free(hdi);
return NULL;
}
for (n = 0; n < N_BUCKETS(hdi->hdi_nbits); ++n)
TAILQ_INIT(&hdi->hdi_buckets[n]);
return &hdi->hdi_data_in;
}

View file

@ -116,30 +116,8 @@ struct nocopy_data_in
((unsigned char *) (data_frame) - offsetof(struct stream_frame, data_frame))
static const struct data_in_iface di_if_nocopy;
struct data_in *
data_in_nocopy_new (struct lsquic_conn_public *conn_pub, uint32_t stream_id)
{
struct nocopy_data_in *ncdi;
ncdi = malloc(sizeof(*ncdi));
if (!ncdi)
return NULL;
TAILQ_INIT(&ncdi->ncdi_frames_in);
ncdi->ncdi_data_in.di_if = &di_if_nocopy;
ncdi->ncdi_data_in.di_flags = 0;
ncdi->ncdi_conn_pub = conn_pub;
ncdi->ncdi_stream_id = stream_id;
ncdi->ncdi_byteage = 0;
ncdi->ncdi_n_frames = 0;
ncdi->ncdi_n_holes = 0;
ncdi->ncdi_cons_far = 0;
return &ncdi->ncdi_data_in;
}
static void
nocopy_di_destroy (struct data_in *data_in)
@ -444,3 +422,24 @@ static const struct data_in_iface di_if_nocopy = {
.di_mem_used = nocopy_di_mem_used,
.di_switch_impl = nocopy_di_switch_impl,
};
struct data_in *
data_in_nocopy_new (struct lsquic_conn_public *conn_pub, uint32_t stream_id)
{
struct nocopy_data_in *ncdi;
ncdi = malloc(sizeof(*ncdi));
if (!ncdi)
return NULL;
TAILQ_INIT(&ncdi->ncdi_frames_in);
ncdi->ncdi_data_in.di_if = &di_if_nocopy;
ncdi->ncdi_data_in.di_flags = 0;
ncdi->ncdi_conn_pub = conn_pub;
ncdi->ncdi_stream_id = stream_id;
ncdi->ncdi_byteage = 0;
ncdi->ncdi_n_frames = 0;
ncdi->ncdi_n_holes = 0;
ncdi->ncdi_cons_far = 0;
return &ncdi->ncdi_data_in;
}

View file

@ -1,5 +1,9 @@
/* Copyright (c) 2017 LiteSpeed Technologies Inc. See LICENSE. */
#include <time.h>
#ifdef WIN32
#include <vc_compat.h>
#define localtime_r(a,b) localtime_s(b,a)
#endif
#include "lsquic_eng_hist.h"

View file

@ -11,14 +11,16 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#include <sys/time.h>
#include <time.h>
#ifndef WIN32
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#endif
@ -164,9 +166,11 @@ struct lsquic_engine
union {
struct {
/* This iterator does not have any state: it uses `conns_in' */
int ignore;
} conn_in;
struct {
/* This iterator does not have any state: it uses `conns_pend_rw' */
int ignore;
} rw_pend;
struct {
/* Iterator state to process connections in Advisory Tick Time
@ -176,6 +180,7 @@ struct lsquic_engine
} attq;
struct {
/* Iterator state to process all connections */
int ignore;
} all;
struct {
lsquic_conn_t *conn;

View file

@ -1,9 +1,14 @@
/* Copyright (c) 2017 LiteSpeed Technologies Inc. See LICENSE. */
#ifndef WIN32
#include <arpa/inet.h>
#else
#include <vc_compat.h>
#endif
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#include "lsquic.h"
#include "lsquic_types.h"
@ -25,7 +30,7 @@
/* Messages that do not include connection ID go above this point */
#define LSQUIC_LOG_CONN_ID cid
#define LCID(a...) LSQ_LOG2(LSQ_LOG_DEBUG, a) /* LCID: log with CID */
#define LCID(...) LSQ_LOG2(LSQ_LOG_DEBUG, __VA_ARGS__) /* LCID: log with CID */
/* Messages that are to include connection ID go below this point */
/* |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| */

View file

@ -19,171 +19,171 @@ struct uncompressed_headers;
/* Log a generic event not tied to any particular connection */
#define EV_LOG_GENERIC_EVENT(args...) do { \
#define EV_LOG_GENERIC_EVENT(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_logger_log1(LSQ_LOG_DEBUG, LSQLM_EVENT, args); \
lsquic_logger_log1(LSQ_LOG_DEBUG, LSQLM_EVENT, __VA_ARGS__); \
} while (0)
/* Log a generic event associated with connection `cid' */
#define EV_LOG_CONN_EVENT(cid, args...) do { \
#define EV_LOG_CONN_EVENT(cid, ...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_logger_log2(LSQ_LOG_DEBUG, LSQLM_EVENT, cid, args); \
lsquic_logger_log2(LSQ_LOG_DEBUG, LSQLM_EVENT, cid, __VA_ARGS__); \
} while (0)
void
lsquic_ev_log_packet_in (lsquic_cid_t, const struct lsquic_packet_in *);
#define EV_LOG_PACKET_IN(args...) do { \
#define EV_LOG_PACKET_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_packet_in(args); \
lsquic_ev_log_packet_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_ack_frame_in (lsquic_cid_t, const struct ack_info *);
#define EV_LOG_ACK_FRAME_IN(args...) do { \
#define EV_LOG_ACK_FRAME_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_ack_frame_in(args); \
lsquic_ev_log_ack_frame_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_stream_frame_in (lsquic_cid_t, const struct stream_frame *);
#define EV_LOG_STREAM_FRAME_IN(args...) do { \
#define EV_LOG_STREAM_FRAME_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_stream_frame_in(args); \
lsquic_ev_log_stream_frame_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_window_update_frame_in (lsquic_cid_t, uint32_t stream_id,
uint64_t offset);
#define EV_LOG_WINDOW_UPDATE_FRAME_IN(args...) do { \
#define EV_LOG_WINDOW_UPDATE_FRAME_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_window_update_frame_in(args); \
lsquic_ev_log_window_update_frame_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_blocked_frame_in (lsquic_cid_t, uint32_t stream_id);
#define EV_LOG_BLOCKED_FRAME_IN(args...) do { \
#define EV_LOG_BLOCKED_FRAME_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_blocked_frame_in(args); \
lsquic_ev_log_blocked_frame_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_stop_waiting_frame_in (lsquic_cid_t, lsquic_packno_t);
#define EV_LOG_STOP_WAITING_FRAME_IN(args...) do { \
#define EV_LOG_STOP_WAITING_FRAME_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_stop_waiting_frame_in(args); \
lsquic_ev_log_stop_waiting_frame_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_connection_close_frame_in (lsquic_cid_t, uint32_t error_code,
int reason_len, const char *reason);
#define EV_LOG_CONNECTION_CLOSE_FRAME_IN(args...) do { \
#define EV_LOG_CONNECTION_CLOSE_FRAME_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_connection_close_frame_in(args); \
lsquic_ev_log_connection_close_frame_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_goaway_frame_in (lsquic_cid_t, uint32_t error_code,
uint32_t stream_id, int reason_len, const char *reason);
#define EV_LOG_GOAWAY_FRAME_IN(args...) do { \
#define EV_LOG_GOAWAY_FRAME_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_goaway_frame_in(args); \
lsquic_ev_log_goaway_frame_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_rst_stream_frame_in (lsquic_cid_t, uint32_t stream_id,
uint64_t offset, uint32_t error_code);
#define EV_LOG_RST_STREAM_FRAME_IN(args...) do { \
#define EV_LOG_RST_STREAM_FRAME_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_rst_stream_frame_in(args); \
lsquic_ev_log_rst_stream_frame_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_padding_frame_in (lsquic_cid_t, size_t len);
#define EV_LOG_PADDING_FRAME_IN(args...) do { \
#define EV_LOG_PADDING_FRAME_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_padding_frame_in(args); \
lsquic_ev_log_padding_frame_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_ping_frame_in (lsquic_cid_t);
#define EV_LOG_PING_FRAME_IN(args...) do { \
#define EV_LOG_PING_FRAME_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_ping_frame_in(args); \
lsquic_ev_log_ping_frame_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_packet_created (lsquic_cid_t, const struct lsquic_packet_out *);
#define EV_LOG_PACKET_CREATED(args...) do { \
#define EV_LOG_PACKET_CREATED(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_packet_created(args); \
lsquic_ev_log_packet_created(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_packet_sent (lsquic_cid_t, const struct lsquic_packet_out *);
#define EV_LOG_PACKET_SENT(args...) do { \
#define EV_LOG_PACKET_SENT(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_packet_sent(args); \
lsquic_ev_log_packet_sent(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_packet_not_sent (lsquic_cid_t, const struct lsquic_packet_out *);
#define EV_LOG_PACKET_NOT_SENT(args...) do { \
#define EV_LOG_PACKET_NOT_SENT(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_packet_not_sent(args); \
lsquic_ev_log_packet_not_sent(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_http_headers_in (lsquic_cid_t, int is_server,
const struct uncompressed_headers *);
#define EV_LOG_HTTP_HEADERS_IN(args...) do { \
#define EV_LOG_HTTP_HEADERS_IN(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_http_headers_in(args); \
lsquic_ev_log_http_headers_in(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_action_stream_frame (lsquic_cid_t, const struct parse_funcs *pf,
const unsigned char *, size_t len, const char *action);
#define EV_LOG_GENERATED_STREAM_FRAME(args...) do { \
#define EV_LOG_GENERATED_STREAM_FRAME(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_action_stream_frame(args, "generated"); \
lsquic_ev_log_action_stream_frame(__VA_ARGS__, "generated"); \
} while (0)
#define EV_LOG_UPDATED_STREAM_FRAME(args...) do { \
#define EV_LOG_UPDATED_STREAM_FRAME(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_action_stream_frame(args, "updated"); \
lsquic_ev_log_action_stream_frame(__VA_ARGS__, "updated"); \
} while (0)
void
lsquic_ev_log_generated_ack_frame (lsquic_cid_t, const struct parse_funcs *,
const unsigned char *, size_t len);
#define EV_LOG_GENERATED_ACK_FRAME(args...) do { \
#define EV_LOG_GENERATED_ACK_FRAME(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_generated_ack_frame(args); \
lsquic_ev_log_generated_ack_frame(__VA_ARGS__); \
} while (0)
void
lsquic_ev_log_generated_stop_waiting_frame (lsquic_cid_t, lsquic_packno_t);
#define EV_LOG_GENERATED_STOP_WAITING_FRAME(args...) do { \
#define EV_LOG_GENERATED_STOP_WAITING_FRAME(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_generated_stop_waiting_frame(args); \
lsquic_ev_log_generated_stop_waiting_frame(__VA_ARGS__); \
} while (0)
void
@ -192,9 +192,9 @@ lsquic_ev_log_generated_http_headers (lsquic_cid_t, uint32_t stream_id,
const struct lsquic_http_headers *);
#define EV_LOG_GENERATED_HTTP_HEADERS(args...) do { \
#define EV_LOG_GENERATED_HTTP_HEADERS(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_generated_http_headers(args); \
lsquic_ev_log_generated_http_headers(__VA_ARGS__); \
} while (0)
void
@ -203,9 +203,9 @@ lsquic_ev_log_generated_http_push_promise (lsquic_cid_t, uint32_t stream_id,
const struct lsquic_http_headers *headers,
const struct lsquic_http_headers *extra_headers);
#define EV_LOG_GENERATED_HTTP_PUSH_PROMISE(args...) do { \
#define EV_LOG_GENERATED_HTTP_PUSH_PROMISE(...) do { \
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
lsquic_ev_log_generated_http_push_promise(args); \
lsquic_ev_log_generated_http_push_promise(__VA_ARGS__); \
} while (0)
#endif

View file

@ -3,7 +3,9 @@
* lsquic_frame_reader.c -- Read HTTP frames from stream
*/
#ifndef WIN32
#include <arpa/inet.h>
#endif
#include <assert.h>
#include <ctype.h>
#include <errno.h>
@ -698,11 +700,12 @@ code_str_to_reason (const char *code_str, int code_len)
};
long code;
char code_buf[ code_len + 1 ];
char * code_buf = malloc(code_len + 1 );
strncpy(code_buf, code_str, code_len);
code_buf[code_len] = '\0';
code = strtol(code_buf, NULL, 10) - 100;
free(code_buf);
if (code > 0 && code < (long) (sizeof(http_reason_phrases) /
sizeof(http_reason_phrases[0])))
return http_reason_phrases[code];

View file

@ -8,7 +8,9 @@
* the whole frame.
*/
#ifndef WIN32
#include <arpa/inet.h>
#endif
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
@ -54,7 +56,7 @@ struct frame_buf
/* Make sure that frab_buf is at least five bytes long, otherwise a frame
* won't fit into two adjacent frabs.
*/
typedef char three_byte_frab_buf[(sizeof(((struct frame_buf *)0)->frab_buf) >= 5) - 1];
typedef char three_byte_frab_buf[(sizeof(((struct frame_buf *)0)->frab_buf) >= 5) ?1 : - 1];
TAILQ_HEAD(frame_buf_head, frame_buf);

View file

@ -6,13 +6,15 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/time.h>
#endif
#include <sys/queue.h>
#include "lsquic_types.h"
#include "lsquic.h"
@ -208,22 +210,22 @@ struct full_conn
#define MAX_ERRMSG 256
#define SET_ERRMSG(conn, errmsg...) do { \
#define SET_ERRMSG(conn, ...) do { \
if (!(conn)->fc_errmsg) \
(conn)->fc_errmsg = malloc(MAX_ERRMSG); \
if ((conn)->fc_errmsg) \
snprintf((conn)->fc_errmsg, MAX_ERRMSG, errmsg); \
snprintf((conn)->fc_errmsg, MAX_ERRMSG, __VA_ARGS__); \
} while (0)
#define ABORT_WITH_FLAG(conn, flag, errmsg...) do { \
SET_ERRMSG(conn, errmsg); \
#define ABORT_WITH_FLAG(conn, flag, ...) do { \
SET_ERRMSG(conn, __VA_ARGS__); \
(conn)->fc_flags |= flag; \
LSQ_ERROR("Abort connection: " errmsg); \
LSQ_ERROR("Abort connection: " __VA_ARGS__); \
} while (0)
#define ABORT_ERROR(errmsg...) ABORT_WITH_FLAG(conn, FC_ERROR, errmsg)
#define ABORT_ERROR(...) ABORT_WITH_FLAG(conn, FC_ERROR, __VA_ARGS__)
#define ABORT_TIMEOUT(errmsg...) ABORT_WITH_FLAG(conn, FC_TIMED_OUT, errmsg)
#define ABORT_TIMEOUT(...) ABORT_WITH_FLAG(conn, FC_TIMED_OUT, __VA_ARGS__)
static void
idle_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now);
@ -249,7 +251,6 @@ write_is_possible (struct full_conn *);
static int
dispatch_stream_read_events (struct full_conn *, struct lsquic_stream *);
static const struct headers_stream_callbacks headers_callbacks;
#if KEEP_CLOSED_STREAM_HISTORY
@ -512,174 +513,9 @@ apply_peer_settings (struct full_conn *conn)
}
static const struct conn_iface full_conn_iface;
static struct full_conn *
new_conn_common (lsquic_cid_t cid, struct lsquic_engine_public *enpub,
const struct lsquic_stream_if *stream_if,
void *stream_if_ctx, unsigned flags,
unsigned short max_packet_size)
{
struct full_conn *conn;
lsquic_stream_t *headers_stream;
int saved_errno;
assert(0 == (flags & ~(FC_SERVER|FC_HTTP)));
conn = calloc(1, sizeof(*conn));
if (!conn)
return NULL;
headers_stream = NULL;
conn->fc_conn.cn_cid = cid;
conn->fc_conn.cn_pack_size = max_packet_size;
conn->fc_flags = flags;
conn->fc_enpub = enpub;
conn->fc_pub.enpub = enpub;
conn->fc_pub.mm = &enpub->enp_mm;
conn->fc_pub.lconn = &conn->fc_conn;
conn->fc_pub.send_ctl = &conn->fc_send_ctl;
conn->fc_pub.packet_out_malo =
lsquic_malo_create(sizeof(struct lsquic_packet_out));
conn->fc_stream_ifs[STREAM_IF_STD].stream_if = stream_if;
conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx = stream_if_ctx;
conn->fc_settings = &enpub->enp_settings;
/* Calculate maximum number of incoming streams using the same mechanism
* and parameters as found in Chrome:
*/
conn->fc_cfg.max_streams_in =
(unsigned) ((float) enpub->enp_settings.es_max_streams_in * 1.1f);
if (conn->fc_cfg.max_streams_in <
enpub->enp_settings.es_max_streams_in + 10)
conn->fc_cfg.max_streams_in =
enpub->enp_settings.es_max_streams_in + 10;
/* `max_streams_out' gets reset when handshake is complete and we
* learn of peer settings. 100 seems like a sane default value
* because it is what other implementations use. In server mode,
* we do not open any streams until the handshake is complete; in
* client mode, we are limited to 98 outgoing requests alongside
* handshake and headers streams.
*/
conn->fc_cfg.max_streams_out = 100;
TAILQ_INIT(&conn->fc_pub.sending_streams);
TAILQ_INIT(&conn->fc_pub.read_streams);
TAILQ_INIT(&conn->fc_pub.write_streams);
TAILQ_INIT(&conn->fc_pub.service_streams);
STAILQ_INIT(&conn->fc_stream_ids_to_reset);
lsquic_conn_cap_init(&conn->fc_pub.conn_cap, LSQUIC_MIN_FCW);
lsquic_alarmset_init(&conn->fc_alset, cid);
lsquic_alarmset_init_alarm(&conn->fc_alset, AL_IDLE, idle_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->fc_alset, AL_ACK, ack_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->fc_alset, AL_PING, ping_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->fc_alset, AL_HANDSHAKE, handshake_alarm_expired, conn);
lsquic_set32_init(&conn->fc_closed_stream_ids[0]);
lsquic_set32_init(&conn->fc_closed_stream_ids[1]);
lsquic_cfcw_init(&conn->fc_pub.cfcw, &conn->fc_pub, conn->fc_settings->es_cfcw);
lsquic_send_ctl_init(&conn->fc_send_ctl, &conn->fc_alset, conn->fc_enpub,
&conn->fc_ver_neg, &conn->fc_pub, conn->fc_conn.cn_pack_size);
conn->fc_pub.all_streams = lsquic_hash_create();
if (!conn->fc_pub.all_streams)
goto cleanup_on_error;
lsquic_rechist_init(&conn->fc_rechist, cid);
if (conn->fc_flags & FC_HTTP)
{
conn->fc_pub.hs = lsquic_headers_stream_new(
!!(conn->fc_flags & FC_SERVER), conn->fc_pub.mm, conn->fc_settings,
&headers_callbacks, conn);
if (!conn->fc_pub.hs)
goto cleanup_on_error;
conn->fc_stream_ifs[STREAM_IF_HDR].stream_if = lsquic_headers_stream_if;
conn->fc_stream_ifs[STREAM_IF_HDR].stream_if_ctx = conn->fc_pub.hs;
headers_stream = new_stream(conn, LSQUIC_STREAM_HEADERS,
SCF_CALL_ON_NEW);
if (!headers_stream)
goto cleanup_on_error;
}
else
{
conn->fc_stream_ifs[STREAM_IF_HDR].stream_if = stream_if;
conn->fc_stream_ifs[STREAM_IF_HDR].stream_if_ctx = stream_if_ctx;
}
if (conn->fc_settings->es_support_push)
conn->fc_flags |= FC_SUPPORT_PUSH;
conn->fc_conn.cn_if = &full_conn_iface;
return conn;
cleanup_on_error:
saved_errno = errno;
if (conn->fc_pub.all_streams)
lsquic_hash_destroy(conn->fc_pub.all_streams);
lsquic_rechist_cleanup(&conn->fc_rechist);
if (conn->fc_flags & FC_HTTP)
{
if (conn->fc_pub.hs)
lsquic_headers_stream_destroy(conn->fc_pub.hs);
if (headers_stream)
lsquic_stream_destroy(headers_stream);
}
memset(conn, 0, sizeof(*conn));
free(conn);
errno = saved_errno;
return NULL;
}
struct lsquic_conn *
full_conn_client_new (struct lsquic_engine_public *enpub,
const struct lsquic_stream_if *stream_if,
void *stream_if_ctx, unsigned flags,
const char *hostname, unsigned short max_packet_size)
{
struct full_conn *conn;
enum lsquic_version version;
lsquic_cid_t cid;
const struct enc_session_funcs *esf;
version = highest_bit_set(enpub->enp_settings.es_versions);
esf = select_esf_by_ver(version);
cid = esf->esf_generate_cid();
conn = new_conn_common(cid, enpub, stream_if, stream_if_ctx, flags,
max_packet_size);
if (!conn)
return NULL;
conn->fc_conn.cn_esf = esf;
conn->fc_conn.cn_enc_session =
conn->fc_conn.cn_esf->esf_create_client(hostname, cid, conn->fc_enpub);
if (!conn->fc_conn.cn_enc_session)
{
LSQ_WARN("could not create enc session: %s", strerror(errno));
conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
return NULL;
}
if (conn->fc_flags & FC_HTTP)
conn->fc_last_stream_id = LSQUIC_STREAM_HEADERS; /* Client goes 5, 7, 9.... */
else
conn->fc_last_stream_id = LSQUIC_STREAM_HANDSHAKE;
conn->fc_hsk_ctx.client.lconn = &conn->fc_conn;
conn->fc_hsk_ctx.client.mm = &enpub->enp_mm;
conn->fc_hsk_ctx.client.ver_neg = &conn->fc_ver_neg;
conn->fc_stream_ifs[STREAM_IF_HSK]
.stream_if = &lsquic_client_hsk_stream_if;
conn->fc_stream_ifs[STREAM_IF_HSK].stream_if_ctx = &conn->fc_hsk_ctx.client;
init_ver_neg(conn, conn->fc_settings->es_versions);
conn->fc_conn.cn_pf = select_pf_by_ver(conn->fc_ver_neg.vn_ver);
if (conn->fc_settings->es_handshake_to)
lsquic_alarmset_set(&conn->fc_alset, AL_HANDSHAKE,
lsquic_time_now() + conn->fc_settings->es_handshake_to);
if (!new_stream(conn, LSQUIC_STREAM_HANDSHAKE, SCF_CALL_ON_NEW))
{
LSQ_WARN("could not create handshake stream: %s", strerror(errno));
conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
return NULL;
}
conn->fc_flags |= FC_CREATED_OK;
LSQ_INFO("Created new client connection");
EV_LOG_CONN_EVENT(cid, "created full connection");
return &conn->fc_conn;
}
void
@ -982,7 +818,7 @@ lsquic_conn_get_engine (lsquic_conn_t *lconn)
}
static unsigned
static ssize_t
count_zero_bytes (const unsigned char *p, size_t len)
{
const unsigned char *const end = p + len;
@ -997,11 +833,11 @@ process_padding_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
const unsigned char *p, size_t len)
{
if (conn->fc_conn.cn_version >= LSQVER_038)
return count_zero_bytes(p, len);
return (unsigned)count_zero_bytes(p, len);
if (lsquic_is_zero(p, len))
{
EV_LOG_PADDING_FRAME_IN(LSQUIC_LOG_CONN_ID, len);
return len;
return (unsigned )len;
}
else
return 0;
@ -3154,3 +2990,167 @@ static const struct conn_iface full_conn_iface = {
.ci_tick = full_conn_ci_tick,
.ci_user_wants_read = full_conn_ci_user_wants_read,
};
static struct full_conn *
new_conn_common (lsquic_cid_t cid, struct lsquic_engine_public *enpub,
const struct lsquic_stream_if *stream_if,
void *stream_if_ctx, unsigned flags,
unsigned short max_packet_size)
{
struct full_conn *conn;
lsquic_stream_t *headers_stream;
int saved_errno;
assert(0 == (flags & ~(FC_SERVER|FC_HTTP)));
conn = calloc(1, sizeof(*conn));
if (!conn)
return NULL;
headers_stream = NULL;
conn->fc_conn.cn_cid = cid;
conn->fc_conn.cn_pack_size = max_packet_size;
conn->fc_flags = flags;
conn->fc_enpub = enpub;
conn->fc_pub.enpub = enpub;
conn->fc_pub.mm = &enpub->enp_mm;
conn->fc_pub.lconn = &conn->fc_conn;
conn->fc_pub.send_ctl = &conn->fc_send_ctl;
conn->fc_pub.packet_out_malo =
lsquic_malo_create(sizeof(struct lsquic_packet_out));
conn->fc_stream_ifs[STREAM_IF_STD].stream_if = stream_if;
conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx = stream_if_ctx;
conn->fc_settings = &enpub->enp_settings;
/* Calculate maximum number of incoming streams using the same mechanism
* and parameters as found in Chrome:
*/
conn->fc_cfg.max_streams_in =
(unsigned) ((float) enpub->enp_settings.es_max_streams_in * 1.1f);
if (conn->fc_cfg.max_streams_in <
enpub->enp_settings.es_max_streams_in + 10)
conn->fc_cfg.max_streams_in =
enpub->enp_settings.es_max_streams_in + 10;
/* `max_streams_out' gets reset when handshake is complete and we
* learn of peer settings. 100 seems like a sane default value
* because it is what other implementations use. In server mode,
* we do not open any streams until the handshake is complete; in
* client mode, we are limited to 98 outgoing requests alongside
* handshake and headers streams.
*/
conn->fc_cfg.max_streams_out = 100;
TAILQ_INIT(&conn->fc_pub.sending_streams);
TAILQ_INIT(&conn->fc_pub.read_streams);
TAILQ_INIT(&conn->fc_pub.write_streams);
TAILQ_INIT(&conn->fc_pub.service_streams);
STAILQ_INIT(&conn->fc_stream_ids_to_reset);
lsquic_conn_cap_init(&conn->fc_pub.conn_cap, LSQUIC_MIN_FCW);
lsquic_alarmset_init(&conn->fc_alset, cid);
lsquic_alarmset_init_alarm(&conn->fc_alset, AL_IDLE, idle_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->fc_alset, AL_ACK, ack_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->fc_alset, AL_PING, ping_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->fc_alset, AL_HANDSHAKE, handshake_alarm_expired, conn);
lsquic_set32_init(&conn->fc_closed_stream_ids[0]);
lsquic_set32_init(&conn->fc_closed_stream_ids[1]);
lsquic_cfcw_init(&conn->fc_pub.cfcw, &conn->fc_pub, conn->fc_settings->es_cfcw);
lsquic_send_ctl_init(&conn->fc_send_ctl, &conn->fc_alset, conn->fc_enpub,
&conn->fc_ver_neg, &conn->fc_pub, conn->fc_conn.cn_pack_size);
conn->fc_pub.all_streams = lsquic_hash_create();
if (!conn->fc_pub.all_streams)
goto cleanup_on_error;
lsquic_rechist_init(&conn->fc_rechist, cid);
if (conn->fc_flags & FC_HTTP)
{
conn->fc_pub.hs = lsquic_headers_stream_new(
!!(conn->fc_flags & FC_SERVER), conn->fc_pub.mm, conn->fc_settings,
&headers_callbacks, conn);
if (!conn->fc_pub.hs)
goto cleanup_on_error;
conn->fc_stream_ifs[STREAM_IF_HDR].stream_if = lsquic_headers_stream_if;
conn->fc_stream_ifs[STREAM_IF_HDR].stream_if_ctx = conn->fc_pub.hs;
headers_stream = new_stream(conn, LSQUIC_STREAM_HEADERS,
SCF_CALL_ON_NEW);
if (!headers_stream)
goto cleanup_on_error;
}
else
{
conn->fc_stream_ifs[STREAM_IF_HDR].stream_if = stream_if;
conn->fc_stream_ifs[STREAM_IF_HDR].stream_if_ctx = stream_if_ctx;
}
if (conn->fc_settings->es_support_push)
conn->fc_flags |= FC_SUPPORT_PUSH;
conn->fc_conn.cn_if = &full_conn_iface;
return conn;
cleanup_on_error:
saved_errno = errno;
if (conn->fc_pub.all_streams)
lsquic_hash_destroy(conn->fc_pub.all_streams);
lsquic_rechist_cleanup(&conn->fc_rechist);
if (conn->fc_flags & FC_HTTP)
{
if (conn->fc_pub.hs)
lsquic_headers_stream_destroy(conn->fc_pub.hs);
if (headers_stream)
lsquic_stream_destroy(headers_stream);
}
memset(conn, 0, sizeof(*conn));
free(conn);
errno = saved_errno;
return NULL;
}
struct lsquic_conn *
full_conn_client_new (struct lsquic_engine_public *enpub,
const struct lsquic_stream_if *stream_if,
void *stream_if_ctx, unsigned flags,
const char *hostname, unsigned short max_packet_size)
{
struct full_conn *conn;
enum lsquic_version version;
lsquic_cid_t cid;
const struct enc_session_funcs *esf;
version = highest_bit_set(enpub->enp_settings.es_versions);
esf = select_esf_by_ver(version);
cid = esf->esf_generate_cid();
conn = new_conn_common(cid, enpub, stream_if, stream_if_ctx, flags,
max_packet_size);
if (!conn)
return NULL;
conn->fc_conn.cn_esf = esf;
conn->fc_conn.cn_enc_session =
conn->fc_conn.cn_esf->esf_create_client(hostname, cid, conn->fc_enpub);
if (!conn->fc_conn.cn_enc_session)
{
LSQ_WARN("could not create enc session: %s", strerror(errno));
conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
return NULL;
}
if (conn->fc_flags & FC_HTTP)
conn->fc_last_stream_id = LSQUIC_STREAM_HEADERS; /* Client goes 5, 7, 9.... */
else
conn->fc_last_stream_id = LSQUIC_STREAM_HANDSHAKE;
conn->fc_hsk_ctx.client.lconn = &conn->fc_conn;
conn->fc_hsk_ctx.client.mm = &enpub->enp_mm;
conn->fc_hsk_ctx.client.ver_neg = &conn->fc_ver_neg;
conn->fc_stream_ifs[STREAM_IF_HSK]
.stream_if = &lsquic_client_hsk_stream_if;
conn->fc_stream_ifs[STREAM_IF_HSK].stream_if_ctx = &conn->fc_hsk_ctx.client;
init_ver_neg(conn, conn->fc_settings->es_versions);
conn->fc_conn.cn_pf = select_pf_by_ver(conn->fc_ver_neg.vn_ver);
if (conn->fc_settings->es_handshake_to)
lsquic_alarmset_set(&conn->fc_alset, AL_HANDSHAKE,
lsquic_time_now() + conn->fc_settings->es_handshake_to);
if (!new_stream(conn, LSQUIC_STREAM_HANDSHAKE, SCF_CALL_ON_NEW))
{
LSQ_WARN("could not create handshake stream: %s", strerror(errno));
conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
return NULL;
}
conn->fc_flags |= FC_CREATED_OK;
LSQ_INFO("Created new client connection");
EV_LOG_CONN_EVENT(cid, "created full connection");
return &conn->fc_conn;
}

View file

@ -5,7 +5,9 @@
#include <time.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <sys/socket.h>
#endif
#include <openssl/ssl.h>
#include <openssl/crypto.h>
@ -933,7 +935,7 @@ lsquic_enc_session_gen_chlo (lsquic_enc_session_t *enc_session,
unsigned char pub_key[32];
size_t ua_len;
uint32_t opts[1]; /* Only NSTP is supported for now */
unsigned n_opts, msg_len, n_tags, pad_size;
unsigned n_opts, msg_len, n_tags, pad_size = 0;
struct message_writer mw;
/* Before we do anything else, sanity check: */

View file

@ -8,6 +8,9 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_malo.h"
#include "lsquic_hash.h"

View file

@ -9,6 +9,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#include <vc_compat.h>
#include "lsquic_types.h"
#include "lsquic_frame_common.h"
@ -28,7 +29,6 @@
#define LSQUIC_LOG_CONN_ID lsquic_conn_id(lsquic_stream_conn(hs->hs_stream))
#include "lsquic_logger.h"
static const struct frame_reader_callbacks frame_callbacks;
struct headers_stream
{
@ -48,6 +48,7 @@ struct headers_stream
HS_HENC_INITED = (1 << 1),
} hs_flags;
};
static lsquic_stream_ctx_t * headers_on_new_stream(void *stream_if_ctx, lsquic_stream_t *stream);
int
@ -70,42 +71,6 @@ lsquic_headers_stream_send_settings (struct headers_stream *hs,
}
static lsquic_stream_ctx_t *
headers_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
{
struct headers_stream *hs = stream_if_ctx;
lsquic_hdec_init(&hs->hs_hdec);
if (0 != lsquic_henc_init(&hs->hs_henc))
{
LSQ_WARN("could not initialize HPACK encoder: %s", strerror(errno));
return NULL;
}
hs->hs_flags |= HS_HENC_INITED;
hs->hs_stream = stream;
LSQ_DEBUG("stream created");
hs->hs_fr = lsquic_frame_reader_new((hs->hs_flags & HS_IS_SERVER) ? FRF_SERVER : 0,
MAX_HEADERS_SIZE, hs->hs_mm,
stream, lsquic_stream_read, &hs->hs_hdec,
&frame_callbacks, hs);
if (!hs->hs_fr)
{
LSQ_WARN("could not create frame reader: %s", strerror(errno));
hs->hs_callbacks->hsc_on_conn_error(hs->hs_cb_ctx);
return NULL;
}
hs->hs_fw = lsquic_frame_writer_new(hs->hs_mm, stream, 0, &hs->hs_henc,
lsquic_stream_write,
(hs->hs_flags & HS_IS_SERVER));
if (!hs->hs_fw)
{
LSQ_WARN("could not create frame writer: %s", strerror(errno));
hs->hs_callbacks->hsc_on_conn_error(hs->hs_cb_ctx);
return NULL;
}
lsquic_stream_wantread(stream, 1);
return (lsquic_stream_ctx_t *) hs;
}
static void
headers_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *ctx)
@ -414,3 +379,39 @@ static const struct frame_reader_callbacks frame_callbacks = {
.frc_on_settings = headers_on_settings,
.frc_on_priority = headers_on_priority,
};
static lsquic_stream_ctx_t *
headers_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
{
struct headers_stream *hs = stream_if_ctx;
lsquic_hdec_init(&hs->hs_hdec);
if (0 != lsquic_henc_init(&hs->hs_henc))
{
LSQ_WARN("could not initialize HPACK encoder: %s", strerror(errno));
return NULL;
}
hs->hs_flags |= HS_HENC_INITED;
hs->hs_stream = stream;
LSQ_DEBUG("stream created");
hs->hs_fr = lsquic_frame_reader_new((hs->hs_flags & HS_IS_SERVER) ? FRF_SERVER : 0,
MAX_HEADERS_SIZE, hs->hs_mm,
stream, lsquic_stream_read, &hs->hs_hdec,
&frame_callbacks, hs);
if (!hs->hs_fr)
{
LSQ_WARN("could not create frame reader: %s", strerror(errno));
hs->hs_callbacks->hsc_on_conn_error(hs->hs_cb_ctx);
return NULL;
}
hs->hs_fw = lsquic_frame_writer_new(hs->hs_mm, stream, 0, &hs->hs_henc,
lsquic_stream_write,
(hs->hs_flags & HS_IS_SERVER));
if (!hs->hs_fw)
{
LSQ_WARN("could not create frame writer: %s", strerror(errno));
hs->hs_callbacks->hsc_on_conn_error(hs->hs_cb_ctx);
return NULL;
}
lsquic_stream_wantread(stream, 1);
return (lsquic_stream_ctx_t *) hs;
}

View file

@ -6,6 +6,9 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_arr.h"
#include "lsquic_hpack_common.h"

View file

@ -9,6 +9,9 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_hpack_common.h"
#include "lsquic_hpack_enc.h"

View file

@ -9,7 +9,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include <time.h>
#define LSQUIC_LOGGER_MODULE LSQLM_LOGGER /* Quis custodiet ipsos custodes? */
@ -122,6 +124,7 @@ lsquic_printf (const char *fmt, ...)
static void
print_timestamp (void)
{
#ifndef WIN32
struct tm tm;
struct timeval tv;
gettimeofday(&tv, NULL);
@ -143,6 +146,27 @@ print_timestamp (void)
else if (g_llts == LLTS_CHROMELIKE)
lsquic_printf("%02d%02d/%02d%02d%02d.%06d ", tm.tm_mon + 1,
tm.tm_mday,tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tv.tv_usec);
#else
SYSTEMTIME tm = { 0 };
GetSystemTime(&tm);
if (g_llts == LLTS_YYYYMMDD_HHMMSSUS)
lsquic_printf("%04d-%02d-%02d %02d:%02d:%02d.%06d ",
tm.wYear + 1900, tm.wMonth + 1, tm.wDay,
tm.wHour, tm.wMinute, tm.wSecond, tm.wMilliseconds*1000 );
else if (g_llts == LLTS_YYYYMMDD_HHMMSSMS)
lsquic_printf("%04d-%02d-%02d %02d:%02d:%02d.%03d ",
tm.wYear + 1900, tm.wMonth + 1, tm.wDay,
tm.wHour, tm.wMinute, tm.wSecond, tm.wMilliseconds*1000 );
else if (g_llts == LLTS_HHMMSSMS)
lsquic_printf("%02d:%02d:%02d.%03d ", tm.wHour, tm.wMinute,
tm.wSecond, tm.wMilliseconds );
else if (g_llts == LLTS_HHMMSSUS)
lsquic_printf("%02d:%02d:%02d.%03d ", tm.wHour, tm.wMinute,
tm.wSecond, tm.wMilliseconds*1000 );
else if (g_llts == LLTS_CHROMELIKE)
lsquic_printf("%02d%02d/%02d%02d%02d.%06d ", tm.wMonth + 1,
tm.wDay,tm.wHour, tm.wMinute, tm.wSecond, (int) tm.wMilliseconds*1000);
#endif
}

View file

@ -48,6 +48,9 @@
#include <stdint.h>
#include <stdlib.h>
#include <sys/queue.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "fiu-local.h"
#include "lsquic_malo.h"
@ -75,7 +78,7 @@ struct malo_page {
};
typedef char malo_header_fits_in_one_slot
[0 - (sizeof(struct malo_page) > (1 << MALO_MAX_NBITS))];
[(sizeof(struct malo_page) > (1 << MALO_MAX_NBITS)) ? -1 : 1];
struct malo {
struct malo_page page_header;
@ -187,10 +190,18 @@ lsquic_malo_destroy (struct malo *malo)
while (page != &malo->page_header)
{
next = SLIST_NEXT(page, next_page);
#ifndef WIN32
free(page);
#else
_aligned_free(page);
#endif
page = next;
}
#ifndef WIN32
free(page);
#else
_aligned_free(page);
#endif
}

View file

@ -6,6 +6,9 @@
#include <stdlib.h> /* getenv */
#endif
#include <string.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_types.h"
#include "lsquic_int_types.h"

View file

@ -10,40 +10,6 @@
#include "lsquic_packet_common.h"
static const char * const frame_type_2_str[N_QUIC_FRAMES] = {
[QUIC_FRAME_INVALID] = "QUIC_FRAME_INVALID",
[QUIC_FRAME_STREAM] = "QUIC_FRAME_STREAM",
[QUIC_FRAME_ACK] = "QUIC_FRAME_ACK",
[QUIC_FRAME_PADDING] = "QUIC_FRAME_PADDING",
[QUIC_FRAME_RST_STREAM] = "QUIC_FRAME_RST_STREAM",
[QUIC_FRAME_CONNECTION_CLOSE] = "QUIC_FRAME_CONNECTION_CLOSE",
[QUIC_FRAME_GOAWAY] = "QUIC_FRAME_GOAWAY",
[QUIC_FRAME_WINDOW_UPDATE] = "QUIC_FRAME_WINDOW_UPDATE",
[QUIC_FRAME_BLOCKED] = "QUIC_FRAME_BLOCKED",
[QUIC_FRAME_STOP_WAITING] = "QUIC_FRAME_STOP_WAITING",
[QUIC_FRAME_PING] = "QUIC_FRAME_PING",
};
#define SLEN(x) (sizeof(#x) - sizeof("QUIC_FRAME_"))
const size_t lsquic_frame_types_str_sz =
/* We don't need to include INVALID frame in this list because it is
* never a part of any frame list bitmask (e.g. po_frame_types).
*/
SLEN(QUIC_FRAME_STREAM) + 1 +
SLEN(QUIC_FRAME_ACK) + 1 +
SLEN(QUIC_FRAME_PADDING) + 1 +
SLEN(QUIC_FRAME_RST_STREAM) + 1 +
SLEN(QUIC_FRAME_CONNECTION_CLOSE) + 1 +
SLEN(QUIC_FRAME_GOAWAY) + 1 +
SLEN(QUIC_FRAME_WINDOW_UPDATE) + 1 +
SLEN(QUIC_FRAME_BLOCKED) + 1 +
SLEN(QUIC_FRAME_STOP_WAITING) + 1 +
SLEN(QUIC_FRAME_PING) + 1;
const char *
lsquic_frame_types_to_str (char *buf, size_t bufsz,
enum quic_ft_bit frame_types)

View file

@ -50,7 +50,40 @@ enum quic_ft_bit {
QUIC_FTBIT_PING = 1 << QUIC_FRAME_PING,
};
extern const size_t lsquic_frame_types_str_sz;
static const char * const frame_type_2_str[N_QUIC_FRAMES] = {
[QUIC_FRAME_INVALID] = "QUIC_FRAME_INVALID",
[QUIC_FRAME_STREAM] = "QUIC_FRAME_STREAM",
[QUIC_FRAME_ACK] = "QUIC_FRAME_ACK",
[QUIC_FRAME_PADDING] = "QUIC_FRAME_PADDING",
[QUIC_FRAME_RST_STREAM] = "QUIC_FRAME_RST_STREAM",
[QUIC_FRAME_CONNECTION_CLOSE] = "QUIC_FRAME_CONNECTION_CLOSE",
[QUIC_FRAME_GOAWAY] = "QUIC_FRAME_GOAWAY",
[QUIC_FRAME_WINDOW_UPDATE] = "QUIC_FRAME_WINDOW_UPDATE",
[QUIC_FRAME_BLOCKED] = "QUIC_FRAME_BLOCKED",
[QUIC_FRAME_STOP_WAITING] = "QUIC_FRAME_STOP_WAITING",
[QUIC_FRAME_PING] = "QUIC_FRAME_PING",
};
#define SLEN(x) (sizeof(#x) - sizeof("QUIC_FRAME_"))
/* We don't need to include INVALID frame in this list because it is
* never a part of any frame list bitmask (e.g. po_frame_types).
*/
#define lsquic_frame_types_str_sz \
SLEN(QUIC_FRAME_STREAM) + 1 + \
SLEN(QUIC_FRAME_ACK) + 1 + \
SLEN(QUIC_FRAME_PADDING) + 1 + \
SLEN(QUIC_FRAME_RST_STREAM) + 1 + \
SLEN(QUIC_FRAME_CONNECTION_CLOSE) + 1 + \
SLEN(QUIC_FRAME_GOAWAY) + 1 + \
SLEN(QUIC_FRAME_WINDOW_UPDATE) + 1 + \
SLEN(QUIC_FRAME_BLOCKED) + 1 + \
SLEN(QUIC_FRAME_STOP_WAITING) + 1 + \
SLEN(QUIC_FRAME_PING) + 1
const char *
lsquic_frame_types_to_str (char *buf, size_t bufsz, enum quic_ft_bit);

View file

@ -2,6 +2,10 @@
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <sys/queue.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_int_types.h"
#include "lsquic_types.h"

View file

@ -6,7 +6,6 @@
#ifndef LSQUIC_PACKET_IN_H
#define LSQUIC_PACKET_IN_H 1
#include <sys/queue.h>
struct lsquic_packet_in;

View file

@ -24,7 +24,7 @@
#include "lsquic_ev_log.h"
typedef char _stream_rec_arr_is_at_most_64bytes[
(sizeof(struct stream_rec_arr) <= 64) - 1];
(sizeof(struct stream_rec_arr) <= 64)? 1: - 1];
static struct stream_rec *
srec_one_posi_first (struct packet_out_srec_iter *posi,
@ -615,7 +615,7 @@ lsquic_packet_out_split_in_two (struct lsquic_mm *mm,
struct stream_rec **new_srecs, **srecs = local_arr;
struct stream_rec *srec;
unsigned n_srecs_alloced = sizeof(local_arr) / sizeof(local_arr[0]);
unsigned n_srecs, max_idx, n, nbytes;
unsigned n_srecs, max_idx = 0, n, nbytes;
#ifndef NDEBUG
unsigned short frame_sum = 0;
#endif

View file

@ -5,7 +5,11 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <sys/types.h>
#else
#include <vc_compat.h>
#endif
#include "lsquic_types.h"
#include "lsquic_alarmset.h"
@ -464,11 +468,13 @@ gquic_ietf_gen_ack_frame (unsigned char *outbuf, size_t outbuf_sz,
p += largest_acked_len;
CHECKOUT(2);
lsquic_time_t diff = now - rechist_largest_recv(rechist);
gquic_be_write_float_time16(diff, p);
LSQ_DEBUG("%s: diff: %"PRIu64"; encoded: 0x%04X", __func__, diff,
*(uint16_t*)p);
p += 2;
{
lsquic_time_t diff = now - rechist_largest_recv(rechist);
gquic_be_write_float_time16(diff, p);
LSQ_DEBUG("%s: diff: %"PRIu64"; encoded: 0x%04X", __func__, diff,
*(uint16_t*)p);
p += 2;
}
*has_missing = n_ranges > 1;
if (n_ranges > 1)

View file

@ -10,7 +10,11 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <sys/types.h>
#else
#include <vc_compat.h>
#endif
#include "lsquic_types.h"
#include "lsquic_alarmset.h"
@ -880,11 +884,13 @@ gquic_be_gen_ack_frame (unsigned char *outbuf, size_t outbuf_sz,
p += largest_acked_len;
CHECKOUT(2);
lsquic_time_t diff = now - rechist_largest_recv(rechist);
gquic_be_write_float_time16(diff, p);
LSQ_DEBUG("%s: diff: %"PRIu64"; encoded: 0x%04X", __func__, diff,
*(uint16_t*)p);
p += 2;
{
lsquic_time_t diff = now - rechist_largest_recv(rechist);
gquic_be_write_float_time16(diff, p);
LSQ_DEBUG("%s: diff: %"PRIu64"; encoded: 0x%04X", __func__, diff,
*(uint16_t*)p);
p += 2;
}
if (n_ranges > 1)
{

View file

@ -18,6 +18,10 @@
#define bswap_16 OSSwapInt16
#define bswap_32 OSSwapInt32
#define bswap_64 OSSwapInt64
#elif defined(WIN32)
#define bswap_16 _byteswap_ushort
#define bswap_32 _byteswap_ulong
#define bswap_64 _byteswap_uint64
#else
#include <byteswap.h>
#endif

View file

@ -8,7 +8,12 @@
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <sys/queue.h>
#ifndef WIN32
#include <sys/types.h>
#else
#include <vc_compat.h>
#endif
#include "lsquic_types.h"
#include "lsquic_packet_common.h"

View file

@ -10,7 +10,11 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <sys/types.h>
#else
#include <vc_compat.h>
#endif
#include "lsquic_types.h"
#include "lsquic_alarmset.h"
@ -766,11 +770,13 @@ gquic_le_gen_ack_frame (unsigned char *outbuf, size_t outbuf_sz,
p += largest_acked_len;
CHECKOUT(2);
lsquic_time_t diff = now - rechist_largest_recv(rechist);
gquic_le_write_float_time16(diff, p);
LSQ_DEBUG("%s: diff: %"PRIu64"; encoded: 0x%04X", __func__, diff,
*(uint16_t*)p);
p += 2;
{
lsquic_time_t diff = now - rechist_largest_recv(rechist);
gquic_le_write_float_time16(diff, p);
LSQ_DEBUG("%s: diff: %"PRIu64"; encoded: 0x%04X", __func__, diff,
*(uint16_t*)p);
p += 2;
}
if (n_ranges > 1)
{

View file

@ -8,6 +8,7 @@
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <vc_compat.h>
#include "lsquic_int_types.h"
#include "lsquic_types.h"

View file

@ -5,7 +5,9 @@
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic_int_types.h"
#include "lsquic_rtt.h"

View file

@ -299,7 +299,7 @@ static void
set_retx_alarm (lsquic_send_ctl_t *ctl)
{
enum retx_mode rm;
lsquic_time_t delay, now;
lsquic_time_t delay = 0, now;
assert(!TAILQ_EMPTY(&ctl->sc_unacked_packets));
@ -879,8 +879,10 @@ lsquic_send_ctl_pacer_blocked (struct lsquic_send_ctl *ctl)
#ifndef NDEBUG
#if __GNUC__
__attribute__((weak))
#endif
#endif
int
lsquic_send_ctl_can_send (lsquic_send_ctl_t *ctl)
{
@ -912,7 +914,7 @@ static void
send_ctl_expire (lsquic_send_ctl_t *ctl, enum expire_filter filter)
{
lsquic_packet_out_t *packet_out, *next;
int n_resubmitted;
int n_resubmitted =0;
static const char *const filter_type2str[] = {
[EXFI_ALL] = "all",
[EXFI_HSK] = "handshake",
@ -1282,7 +1284,7 @@ lsquic_send_ctl_set_tcid0 (lsquic_send_ctl_t *ctl, int tcid0)
void
lsquic_send_ctl_elide_stream_frames (lsquic_send_ctl_t *ctl, uint32_t stream_id)
{
struct lsquic_packet_out *packet_out, *next;
struct lsquic_packet_out *packet_out = NULL, *next = NULL;
unsigned n, adj;
for (packet_out = TAILQ_FIRST(&ctl->sc_scheduled_packets); packet_out;
@ -1337,8 +1339,10 @@ lsquic_send_ctl_elide_stream_frames (lsquic_send_ctl_t *ctl, uint32_t stream_id)
* packets.
*/
#ifndef NDEBUG
#if __GNUC__
__attribute__((weak))
#endif
#endif
int
lsquic_send_ctl_have_delayed_packets (const lsquic_send_ctl_t *ctl)
{

View file

@ -10,6 +10,9 @@
#include <string.h>
#include <sys/queue.h>
#include <sys/types.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_types.h"
#include "lsquic_int_types.h"
@ -21,7 +24,7 @@
#define LSQUIC_LOG_CONN_ID iter->spi_cid
#include "lsquic_logger.h"
#define SPI_DEBUG(fmt, a...) LSQ_DEBUG("%s: " fmt, iter->spi_name, a)
#define SPI_DEBUG(fmt, ...) LSQ_DEBUG("%s: " fmt, iter->spi_name, __VA_ARGS__)
#define NEXT_STREAM(stream, off) \
(* (struct lsquic_stream **) ((unsigned char *) (stream) + (off)))

View file

@ -1702,7 +1702,7 @@ lsquic_stream_write (lsquic_stream_t *stream, const void *buf, size_t len)
struct inner_reader_iovec {
const struct iovec *iov;
const struct iovec *const end;
const struct iovec *end;
unsigned cur_iovec_off;
};

View file

@ -7,9 +7,13 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#ifndef WIN32
#include <sys/time.h>
#include <unistd.h>
#else
#include <vc_compat.h>
#endif
#if !(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(__APPLE__)
#include <mach/mach_time.h>
@ -22,6 +26,9 @@
#if defined(__APPLE__)
static mach_timebase_info_data_t timebase;
#endif
#if defined(WIN32)
static LARGE_INTEGER perf_frequency;
#endif
void
lsquic_init_timers (void)
@ -29,6 +36,9 @@ lsquic_init_timers (void)
#if defined(__APPLE__)
mach_timebase_info(&timebase);
#endif
#if defined(WIN32)
QueryPerformanceFrequency(&perf_frequency);
#endif
}
@ -45,6 +55,14 @@ lsquic_time_now (void)
t /= timebase.denom;
t /= 1000;
return t;
#elif defined(WIN32)
LARGE_INTEGER counter;
lsquic_time_t t;
QueryPerformanceCounter(&counter);
t = counter.QuadPart;
t *= 1000000;
t /= perf_frequency.QuadPart;
return t;
#else
# warn Monotonically increasing clock is not available on this platform
struct timeval tv;
@ -96,7 +114,7 @@ char *get_bin_str(const void *s, size_t len, size_t max_display_len)
pOutput = &str[0] + sprintf(str, "(%zd/%zd)=0x", len, lenOrg);
for(p = s, pEnd = s + len; p < pEnd; ++p)
for(p = s, pEnd = (unsigned char*)s + len; p < pEnd; ++p)
{
sprintf(pOutput, "%02X", *p);
pOutput += 2;

View file

@ -3,16 +3,29 @@
* http_client.c -- A simple HTTP/QUIC client
*/
#ifndef WIN32
#include <arpa/inet.h>
#include <netinet/in.h>
#else
#include <Windows.h>
#include <WinSock2.h>
#include <io.h>
#include <stdlib.h>
#include <getopt.h>
#define STDOUT_FILENO 1
#define random rand
#pragma warning(disable:4996) //POSIX name deprecated
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/queue.h>
#ifndef WIN32
#include <unistd.h>
#include <sys/types.h>
#endif
#include <sys/stat.h>
#include <fcntl.h>
@ -33,362 +46,365 @@ static int promise_fd = -1;
struct lsquic_conn_ctx;
struct path_elem {
TAILQ_ENTRY(path_elem) next_pe;
const char *path;
TAILQ_ENTRY(path_elem) next_pe;
const char *path;
};
struct http_client_ctx {
TAILQ_HEAD(, lsquic_conn_ctx)
conn_ctxs;
struct service_port *sport;
const char *hostname;
const char *method;
const char *payload;
char payload_size[20];
TAILQ_HEAD(, lsquic_conn_ctx)
conn_ctxs;
struct service_port *sport;
const char *hostname;
const char *method;
const char *payload;
char payload_size[20];
/* hcc_path_elems holds a list of paths which are to be requested from
* the server. Each new request gets the next path from the list (the
* iterator is stored in hcc_cur_pe); when the end is reached, the
* iterator wraps around.
*/
TAILQ_HEAD(, path_elem) hcc_path_elems;
struct path_elem *hcc_cur_pe;
/* hcc_path_elems holds a list of paths which are to be requested from
* the server. Each new request gets the next path from the list (the
* iterator is stored in hcc_cur_pe); when the end is reached, the
* iterator wraps around.
*/
TAILQ_HEAD(, path_elem) hcc_path_elems;
struct path_elem *hcc_cur_pe;
unsigned hcc_total_n_reqs;
unsigned hcc_reqs_per_conn;
unsigned hcc_concurrency;
unsigned hcc_n_open_conns;
unsigned hcc_total_n_reqs;
unsigned hcc_reqs_per_conn;
unsigned hcc_concurrency;
unsigned hcc_n_open_conns;
enum {
HCC_DISCARD_RESPONSE = (1 << 0),
HCC_SEEN_FIN = (1 << 1),
HCC_ABORT_ON_INCOMPLETE = (1 << 2),
} hcc_flags;
struct prog *prog;
enum {
HCC_DISCARD_RESPONSE = (1 << 0),
HCC_SEEN_FIN = (1 << 1),
HCC_ABORT_ON_INCOMPLETE = (1 << 2),
} hcc_flags;
struct prog *prog;
};
struct lsquic_conn_ctx {
TAILQ_ENTRY(lsquic_conn_ctx) next_ch;
lsquic_conn_t *conn;
struct http_client_ctx *client_ctx;
unsigned ch_n_reqs; /* This number gets decremented as streams are closed and
* incremented as push promises are accepted.
*/
TAILQ_ENTRY(lsquic_conn_ctx) next_ch;
lsquic_conn_t *conn;
struct http_client_ctx *client_ctx;
unsigned ch_n_reqs; /* This number gets decremented as streams are closed and
* incremented as push promises are accepted.
*/
};
static void
create_connections (struct http_client_ctx *client_ctx)
{
while (client_ctx->hcc_n_open_conns < client_ctx->hcc_concurrency &&
client_ctx->hcc_total_n_reqs > 0)
if (0 != prog_connect(client_ctx->prog))
{
LSQ_ERROR("connection failed");
exit(EXIT_FAILURE);
}
while (client_ctx->hcc_n_open_conns < client_ctx->hcc_concurrency &&
client_ctx->hcc_total_n_reqs > 0)
if (0 != prog_connect(client_ctx->prog))
{
LSQ_ERROR("connection failed");
exit(EXIT_FAILURE);
}
}
static lsquic_conn_ctx_t *
http_client_on_new_conn (void *stream_if_ctx, lsquic_conn_t *conn)
{
struct http_client_ctx *client_ctx = stream_if_ctx;
lsquic_conn_ctx_t *conn_h = calloc(1, sizeof(*conn_h));
conn_h->conn = conn;
conn_h->client_ctx = client_ctx;
conn_h->ch_n_reqs = client_ctx->hcc_total_n_reqs <
client_ctx->hcc_reqs_per_conn ?
client_ctx->hcc_total_n_reqs : client_ctx->hcc_reqs_per_conn;
client_ctx->hcc_total_n_reqs -= conn_h->ch_n_reqs;
TAILQ_INSERT_TAIL(&client_ctx->conn_ctxs, conn_h, next_ch);
++conn_h->client_ctx->hcc_n_open_conns;
lsquic_conn_make_stream(conn);
return conn_h;
struct http_client_ctx *client_ctx = stream_if_ctx;
lsquic_conn_ctx_t *conn_h = calloc(1, sizeof(*conn_h));
conn_h->conn = conn;
conn_h->client_ctx = client_ctx;
conn_h->ch_n_reqs = client_ctx->hcc_total_n_reqs <
client_ctx->hcc_reqs_per_conn ?
client_ctx->hcc_total_n_reqs : client_ctx->hcc_reqs_per_conn;
client_ctx->hcc_total_n_reqs -= conn_h->ch_n_reqs;
TAILQ_INSERT_TAIL(&client_ctx->conn_ctxs, conn_h, next_ch);
++conn_h->client_ctx->hcc_n_open_conns;
lsquic_conn_make_stream(conn);
return conn_h;
}
static void
http_client_on_conn_closed (lsquic_conn_t *conn)
{
lsquic_conn_ctx_t *conn_h = lsquic_conn_get_ctx(conn);
enum LSQUIC_CONN_STATUS status;
char errmsg[80];
lsquic_conn_ctx_t *conn_h = lsquic_conn_get_ctx(conn);
enum LSQUIC_CONN_STATUS status;
char errmsg[80];
status = lsquic_conn_status(conn, errmsg, sizeof(errmsg));
LSQ_INFO("Connection closed. Status: %d. Message: %s", status,
errmsg[0] ? errmsg : "<not set>");
status = lsquic_conn_status(conn, errmsg, sizeof(errmsg));
LSQ_INFO("Connection closed. Status: %d. Message: %s", status,
errmsg[0] ? errmsg : "<not set>");
#ifndef NDEBUG
if (conn_h->client_ctx->hcc_flags & HCC_ABORT_ON_INCOMPLETE)
assert(conn_h->client_ctx->hcc_flags & HCC_SEEN_FIN);
if (conn_h->client_ctx->hcc_flags & HCC_ABORT_ON_INCOMPLETE)
assert(conn_h->client_ctx->hcc_flags & HCC_SEEN_FIN);
#endif
TAILQ_REMOVE(&conn_h->client_ctx->conn_ctxs, conn_h, next_ch);
--conn_h->client_ctx->hcc_n_open_conns;
create_connections(conn_h->client_ctx);
if (0 == conn_h->client_ctx->hcc_n_open_conns)
{
LSQ_INFO("All connections are closed: stop engine");
prog_stop(conn_h->client_ctx->prog);
}
free(conn_h);
TAILQ_REMOVE(&conn_h->client_ctx->conn_ctxs, conn_h, next_ch);
--conn_h->client_ctx->hcc_n_open_conns;
create_connections(conn_h->client_ctx);
if (0 == conn_h->client_ctx->hcc_n_open_conns)
{
LSQ_INFO("All connections are closed: stop engine");
prog_stop(conn_h->client_ctx->prog);
}
free(conn_h);
}
struct lsquic_stream_ctx {
lsquic_stream_t *stream;
struct http_client_ctx *client_ctx;
const char *path;
enum {
HEADERS_SENT = (1 << 0),
} sh_flags;
unsigned count;
struct lsquic_reader reader;
lsquic_stream_t *stream;
struct http_client_ctx *client_ctx;
const char *path;
enum {
HEADERS_SENT = (1 << 0),
} sh_flags;
unsigned count;
struct lsquic_reader reader;
};
static lsquic_stream_ctx_t *
http_client_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
{
const int pushed = lsquic_stream_is_pushed(stream);
const int pushed = lsquic_stream_is_pushed(stream);
if (pushed)
{
LSQ_INFO("not accepting server push");
lsquic_stream_refuse_push(stream);
return NULL;
}
if (pushed)
{
LSQ_INFO("not accepting server push");
lsquic_stream_refuse_push(stream);
return NULL;
}
lsquic_stream_ctx_t *st_h = calloc(1, sizeof(*st_h));
st_h->stream = stream;
st_h->client_ctx = stream_if_ctx;
if (st_h->client_ctx->hcc_cur_pe)
{
st_h->client_ctx->hcc_cur_pe = TAILQ_NEXT(
st_h->client_ctx->hcc_cur_pe, next_pe);
if (!st_h->client_ctx->hcc_cur_pe) /* Wrap around */
st_h->client_ctx->hcc_cur_pe =
TAILQ_FIRST(&st_h->client_ctx->hcc_path_elems);
}
else
st_h->client_ctx->hcc_cur_pe = TAILQ_FIRST(
&st_h->client_ctx->hcc_path_elems);
st_h->path = st_h->client_ctx->hcc_cur_pe->path;
if (st_h->client_ctx->payload)
{
st_h->reader.lsqr_read = test_reader_read;
st_h->reader.lsqr_size = test_reader_size;
st_h->reader.lsqr_ctx = create_lsquic_reader_ctx(st_h->client_ctx->payload);
if (!st_h->reader.lsqr_ctx)
exit(1);
}
else
st_h->reader.lsqr_ctx = NULL;
LSQ_INFO("created new stream, path: %s", st_h->path);
lsquic_stream_wantwrite(stream, 1);
lsquic_stream_ctx_t *st_h = calloc(1, sizeof(*st_h));
st_h->stream = stream;
st_h->client_ctx = stream_if_ctx;
if (st_h->client_ctx->hcc_cur_pe)
{
st_h->client_ctx->hcc_cur_pe = TAILQ_NEXT(
st_h->client_ctx->hcc_cur_pe, next_pe);
if (!st_h->client_ctx->hcc_cur_pe) /* Wrap around */
st_h->client_ctx->hcc_cur_pe =
TAILQ_FIRST(&st_h->client_ctx->hcc_path_elems);
}
else
st_h->client_ctx->hcc_cur_pe = TAILQ_FIRST(
&st_h->client_ctx->hcc_path_elems);
st_h->path = st_h->client_ctx->hcc_cur_pe->path;
if (st_h->client_ctx->payload)
{
st_h->reader.lsqr_read = test_reader_read;
st_h->reader.lsqr_size = test_reader_size;
st_h->reader.lsqr_ctx = create_lsquic_reader_ctx(st_h->client_ctx->payload);
if (!st_h->reader.lsqr_ctx)
exit(1);
}
else
st_h->reader.lsqr_ctx = NULL;
LSQ_INFO("created new stream, path: %s", st_h->path);
lsquic_stream_wantwrite(stream, 1);
return st_h;
return st_h;
}
static void
send_headers (lsquic_stream_ctx_t *st_h)
{
lsquic_http_header_t headers_arr[] = {
{
.name = { .iov_base = ":method", .iov_len = 7, },
.value = { .iov_base = (void *) st_h->client_ctx->method,
.iov_len = strlen(st_h->client_ctx->method), },
},
{
.name = { .iov_base = ":scheme", .iov_len = 7, },
.value = { .iov_base = "HTTP", .iov_len = 4, }
},
{
.name = { .iov_base = ":path", .iov_len = 5, },
.value = { .iov_base = (void *) st_h->path,
.iov_len = strlen(st_h->path), },
},
{
.name = { ":authority", 10, },
.value = { .iov_base = (void *) st_h->client_ctx->hostname,
.iov_len = strlen(st_h->client_ctx->hostname), },
},
/*
{
.name = { "host", 4 },
.value = { .iov_base = (void *) st_h->client_ctx->hostname,
.iov_len = strlen(st_h->client_ctx->hostname), },
},
*/
{
.name = { .iov_base = "user-agent", .iov_len = 10, },
.value = { .iov_base = (char *) st_h->client_ctx->prog->prog_settings.es_ua,
.iov_len = strlen(st_h->client_ctx->prog->prog_settings.es_ua), },
},
/* The following headers only gets sent if there is request payload: */
{
.name = { .iov_base = "content-type", .iov_len = 12, },
.value = { .iov_base = "application/octet-stream", .iov_len = 24, },
},
{
.name = { .iov_base = "content-length", .iov_len = 14, },
.value = { .iov_base = (void *) st_h->client_ctx->payload_size,
.iov_len = strlen(st_h->client_ctx->payload_size), },
},
};
lsquic_http_headers_t headers = {
.count = sizeof(headers_arr) / sizeof(headers_arr[0]),
.headers = headers_arr,
};
if (!st_h->client_ctx->payload)
headers.count -= 2;
if (0 != lsquic_stream_send_headers(st_h->stream, &headers,
st_h->client_ctx->payload == NULL))
{
LSQ_ERROR("cannot send headers: %s", strerror(errno));
exit(1);
}
lsquic_http_header_t headers_arr[] = {
{
.name = { .iov_base = ":method", .iov_len = 7, },
.value = { .iov_base = (void *) st_h->client_ctx->method,
.iov_len = strlen(st_h->client_ctx->method), },
},
{
.name = { .iov_base = ":scheme", .iov_len = 7, },
.value = { .iov_base = "HTTP", .iov_len = 4, }
},
{
.name = { .iov_base = ":path", .iov_len = 5, },
.value = { .iov_base = (void *) st_h->path,
.iov_len = strlen(st_h->path), },
},
{
.name = { ":authority", 10, },
.value = { .iov_base = (void *) st_h->client_ctx->hostname,
.iov_len = strlen(st_h->client_ctx->hostname), },
},
/*
{
.name = { "host", 4 },
.value = { .iov_base = (void *) st_h->client_ctx->hostname,
.iov_len = strlen(st_h->client_ctx->hostname), },
},
*/
{
.name = { .iov_base = "user-agent", .iov_len = 10, },
.value = { .iov_base = (char *) st_h->client_ctx->prog->prog_settings.es_ua,
.iov_len = strlen(st_h->client_ctx->prog->prog_settings.es_ua), },
},
/* The following headers only gets sent if there is request payload: */
{
.name = { .iov_base = "content-type", .iov_len = 12, },
.value = { .iov_base = "application/octet-stream", .iov_len = 24, },
},
{
.name = { .iov_base = "content-length", .iov_len = 14, },
.value = { .iov_base = (void *) st_h->client_ctx->payload_size,
.iov_len = strlen(st_h->client_ctx->payload_size), },
},
};
lsquic_http_headers_t headers = {
.count = sizeof(headers_arr) / sizeof(headers_arr[0]),
.headers = headers_arr,
};
if (!st_h->client_ctx->payload)
headers.count -= 2;
if (0 != lsquic_stream_send_headers(st_h->stream, &headers,
st_h->client_ctx->payload == NULL))
{
LSQ_ERROR("cannot send headers: %s", strerror(errno));
exit(1);
}
}
static void
http_client_on_write (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
{
ssize_t nw;
ssize_t nw;
if (st_h->sh_flags & HEADERS_SENT)
{
if (st_h->client_ctx->payload && test_reader_size(st_h->reader.lsqr_ctx) > 0)
{
nw = lsquic_stream_writef(stream, &st_h->reader);
if (nw < 0)
{
LSQ_ERROR("write error: %s", strerror(errno));
exit(1);
}
if (test_reader_size(st_h->reader.lsqr_ctx) > 0)
{
lsquic_stream_wantwrite(stream, 1);
}
else
{
lsquic_stream_shutdown(stream, 1);
lsquic_stream_wantread(stream, 1);
}
}
else
{
lsquic_stream_shutdown(stream, 1);
lsquic_stream_wantread(stream, 1);
}
}
else
{
st_h->sh_flags |= HEADERS_SENT;
send_headers(st_h);
}
if (st_h->sh_flags & HEADERS_SENT)
{
if (st_h->client_ctx->payload && test_reader_size(st_h->reader.lsqr_ctx) > 0)
{
nw = lsquic_stream_writef(stream, &st_h->reader);
if (nw < 0)
{
LSQ_ERROR("write error: %s", strerror(errno));
exit(1);
}
if (test_reader_size(st_h->reader.lsqr_ctx) > 0)
{
lsquic_stream_wantwrite(stream, 1);
}
else
{
lsquic_stream_shutdown(stream, 1);
lsquic_stream_wantread(stream, 1);
}
}
else
{
lsquic_stream_shutdown(stream, 1);
lsquic_stream_wantread(stream, 1);
}
}
else
{
st_h->sh_flags |= HEADERS_SENT;
send_headers(st_h);
}
}
static void
http_client_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
{
struct http_client_ctx *const client_ctx = st_h->client_ctx;
ssize_t nread;
unsigned old_prio, new_prio;
unsigned char buf[0x200];
unsigned nreads = 0;
do
{
nread = lsquic_stream_read(stream, buf, sizeof(buf));
if (nread > 0)
{
if (!(client_ctx->hcc_flags & HCC_DISCARD_RESPONSE))
write(STDOUT_FILENO, buf, nread);
if (randomly_reprioritize_streams && (st_h->count++ & 0x3F) == 0)
{
old_prio = lsquic_stream_priority(stream);
new_prio = random() & 0xFF;
#ifndef NDEBUG
const int s =
struct http_client_ctx *const client_ctx = st_h->client_ctx;
ssize_t nread;
unsigned old_prio, new_prio;
unsigned char buf[0x200];
unsigned nreads = 0;
#ifdef WIN32
srand(GetTickCount());
#endif
lsquic_stream_set_priority(stream, new_prio);
assert(s == 0);
LSQ_NOTICE("changed stream %u priority from %u to %u",
lsquic_stream_id(stream), old_prio, new_prio);
}
}
else if (0 == nread)
{
client_ctx->hcc_flags |= HCC_SEEN_FIN;
lsquic_stream_shutdown(stream, 0);
break;
}
else if (client_ctx->prog->prog_settings.es_rw_once && EWOULDBLOCK == errno)
{
LSQ_NOTICE("emptied the buffer in 'once' mode");
break;
}
else
{
LSQ_ERROR("could not read: %s", strerror(errno));
exit(2);
}
}
while (client_ctx->prog->prog_settings.es_rw_once
&& nreads++ < 3 /* Emulate just a few reads */);
do
{
nread = lsquic_stream_read(stream, buf, sizeof(buf));
if (nread > 0)
{
if (!(client_ctx->hcc_flags & HCC_DISCARD_RESPONSE))
write(STDOUT_FILENO, buf, nread);
if (randomly_reprioritize_streams && (st_h->count++ & 0x3F) == 0)
{
old_prio = lsquic_stream_priority(stream);
new_prio = random() & 0xFF;
#ifndef NDEBUG
const int s =
#endif
lsquic_stream_set_priority(stream, new_prio);
assert(s == 0);
LSQ_NOTICE("changed stream %u priority from %u to %u",
lsquic_stream_id(stream), old_prio, new_prio);
}
}
else if (0 == nread)
{
client_ctx->hcc_flags |= HCC_SEEN_FIN;
lsquic_stream_shutdown(stream, 0);
break;
}
else if (client_ctx->prog->prog_settings.es_rw_once && EWOULDBLOCK == errno)
{
LSQ_NOTICE("emptied the buffer in 'once' mode");
break;
}
else
{
LSQ_ERROR("could not read: %s", strerror(errno));
exit(2);
}
}
while (client_ctx->prog->prog_settings.es_rw_once
&& nreads++ < 3 /* Emulate just a few reads */);
}
static void
http_client_on_close (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
{
const int pushed = lsquic_stream_is_pushed(stream);
if (pushed)
{
assert(NULL == st_h);
return;
}
const int pushed = lsquic_stream_is_pushed(stream);
if (pushed)
{
assert(NULL == st_h);
return;
}
LSQ_INFO("%s called", __func__);
lsquic_conn_t *conn = lsquic_stream_conn(stream);
lsquic_conn_ctx_t *conn_h;
TAILQ_FOREACH(conn_h, &st_h->client_ctx->conn_ctxs, next_ch)
if (conn_h->conn == conn)
break;
assert(conn_h);
--conn_h->ch_n_reqs;
if (0 == conn_h->ch_n_reqs)
{
LSQ_INFO("all requests completed, closing connection");
lsquic_conn_close(conn_h->conn);
}
else
lsquic_conn_make_stream(conn);
if (st_h->reader.lsqr_ctx)
destroy_lsquic_reader_ctx(st_h->reader.lsqr_ctx);
free(st_h);
LSQ_INFO("%s called", __func__);
lsquic_conn_t *conn = lsquic_stream_conn(stream);
lsquic_conn_ctx_t *conn_h;
TAILQ_FOREACH(conn_h, &st_h->client_ctx->conn_ctxs, next_ch)
if (conn_h->conn == conn)
break;
assert(conn_h);
--conn_h->ch_n_reqs;
if (0 == conn_h->ch_n_reqs)
{
LSQ_INFO("all requests completed, closing connection");
lsquic_conn_close(conn_h->conn);
}
else
lsquic_conn_make_stream(conn);
if (st_h->reader.lsqr_ctx)
destroy_lsquic_reader_ctx(st_h->reader.lsqr_ctx);
free(st_h);
}
const struct lsquic_stream_if http_client_if = {
.on_new_conn = http_client_on_new_conn,
.on_conn_closed = http_client_on_conn_closed,
.on_new_stream = http_client_on_new_stream,
.on_read = http_client_on_read,
.on_write = http_client_on_write,
.on_close = http_client_on_close,
.on_new_conn = http_client_on_new_conn,
.on_conn_closed = http_client_on_conn_closed,
.on_new_stream = http_client_on_new_stream,
.on_read = http_client_on_read,
.on_write = http_client_on_write,
.on_close = http_client_on_close,
};
static void
usage (const char *prog)
{
const char *const slash = strrchr(prog, '/');
if (slash)
prog = slash + 1;
printf(
const char *const slash = strrchr(prog, '/');
if (slash)
prog = slash + 1;
printf(
"Usage: %s [opts]\n"
"\n"
"Options:\n"
@ -404,117 +420,121 @@ usage (const char *prog)
" content-length\n"
" -K Discard server response\n"
" -I Abort on incomplete reponse from server\n"
, prog);
, prog);
}
int
main (int argc, char **argv)
{
int opt, s;
struct http_client_ctx client_ctx;
struct stat st;
struct path_elem *pe;
struct sport_head sports;
struct prog prog;
int opt, s;
struct http_client_ctx client_ctx;
struct stat st;
struct path_elem *pe;
struct sport_head sports;
struct prog prog;
TAILQ_INIT(&sports);
memset(&client_ctx, 0, sizeof(client_ctx));
client_ctx.hcc_concurrency = 1;
TAILQ_INIT(&client_ctx.hcc_path_elems);
TAILQ_INIT(&client_ctx.conn_ctxs);
client_ctx.hostname = "localhost";
client_ctx.method = "GET";
client_ctx.hcc_concurrency = 1;
client_ctx.hcc_reqs_per_conn = 1;
client_ctx.hcc_total_n_reqs = 1;
client_ctx.prog = &prog;
TAILQ_INIT(&sports);
memset(&client_ctx, 0, sizeof(client_ctx));
client_ctx.hcc_concurrency = 1;
TAILQ_INIT(&client_ctx.hcc_path_elems);
TAILQ_INIT(&client_ctx.conn_ctxs);
client_ctx.hostname = "localhost";
client_ctx.method = "GET";
client_ctx.hcc_concurrency = 1;
client_ctx.hcc_reqs_per_conn = 1;
client_ctx.hcc_total_n_reqs = 1;
client_ctx.prog = &prog;
#ifdef WIN32
WSADATA wsd;
WSAStartup(MAKEWORD(2, 2), &wsd);
#endif
prog_init(&prog, LSENG_HTTP, &sports, &http_client_if, &client_ctx);
prog_init(&prog, LSENG_HTTP, &sports, &http_client_if, &client_ctx);
while (-1 != (opt = getopt(argc, argv, PROG_OPTS "r:R:Ku:EP:M:n:H:p:h")))
{
switch (opt) {
case 'I':
client_ctx.hcc_flags |= HCC_ABORT_ON_INCOMPLETE;
break;
case 'K':
client_ctx.hcc_flags |= HCC_DISCARD_RESPONSE;
break;
case 'u': /* Accept p<U>sh promise */
promise_fd = open(optarg, O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (promise_fd < 0)
{
perror("open");
exit(1);
}
prog.prog_settings.es_support_push = 1; /* Pokes into prog */
break;
case 'E': /* E: randomly reprioritize str<E>ams. Now, that's
* pretty random. :)
*/
randomly_reprioritize_streams = 1;
break;
case 'n':
client_ctx.hcc_concurrency = atoi(optarg);
break;
case 'P':
client_ctx.payload = optarg;
if (0 != stat(optarg, &st))
{
perror("stat");
exit(2);
}
sprintf(client_ctx.payload_size, "%jd", (intmax_t) st.st_size);
break;
case 'M':
client_ctx.method = optarg;
break;
case 'r':
client_ctx.hcc_total_n_reqs = atoi(optarg);
break;
case 'R':
client_ctx.hcc_reqs_per_conn = atoi(optarg);
break;
case 'H':
client_ctx.hostname = optarg;
prog.prog_hostname = optarg; /* Pokes into prog */
break;
case 'p':
pe = calloc(1, sizeof(*pe));
pe->path = optarg;
TAILQ_INSERT_TAIL(&client_ctx.hcc_path_elems, pe, next_pe);
break;
case 'h':
usage(argv[0]);
prog_print_common_options(&prog, stdout);
exit(0);
default:
if (0 != prog_set_opt(&prog, opt, optarg))
exit(1);
}
}
while (-1 != (opt = getopt(argc, argv, PROG_OPTS "r:R:Ku:EP:M:n:H:p:h")))
{
switch (opt) {
case 'I':
client_ctx.hcc_flags |= HCC_ABORT_ON_INCOMPLETE;
break;
case 'K':
client_ctx.hcc_flags |= HCC_DISCARD_RESPONSE;
break;
case 'u': /* Accept p<U>sh promise */
promise_fd = open(optarg, O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (promise_fd < 0)
{
perror("open");
exit(1);
}
prog.prog_settings.es_support_push = 1; /* Pokes into prog */
break;
case 'E': /* E: randomly reprioritize str<E>ams. Now, that's
* pretty random. :)
*/
randomly_reprioritize_streams = 1;
break;
case 'n':
client_ctx.hcc_concurrency = atoi(optarg);
break;
case 'P':
client_ctx.payload = optarg;
if (0 != stat(optarg, &st))
{
perror("stat");
exit(2);
}
sprintf(client_ctx.payload_size, "%jd", (intmax_t) st.st_size);
break;
case 'M':
client_ctx.method = optarg;
break;
case 'r':
client_ctx.hcc_total_n_reqs = atoi(optarg);
break;
case 'R':
client_ctx.hcc_reqs_per_conn = atoi(optarg);
break;
case 'H':
client_ctx.hostname = optarg;
prog.prog_hostname = optarg; /* Pokes into prog */
break;
case 'p':
pe = calloc(1, sizeof(*pe));
pe->path = optarg;
TAILQ_INSERT_TAIL(&client_ctx.hcc_path_elems, pe, next_pe);
break;
case 'h':
usage(argv[0]);
prog_print_common_options(&prog, stdout);
exit(0);
default:
if (0 != prog_set_opt(&prog, opt, optarg))
exit(1);
}
}
if (TAILQ_EMPTY(&client_ctx.hcc_path_elems))
{
fprintf(stderr, "Specify at least one path using -p option\n");
exit(1);
}
if (TAILQ_EMPTY(&client_ctx.hcc_path_elems))
{
fprintf(stderr, "Specify at least one path using -p option\n");
exit(1);
}
if (0 != prog_prep(&prog))
{
LSQ_ERROR("could not prep");
exit(EXIT_FAILURE);
}
if (0 != prog_prep(&prog))
{
LSQ_ERROR("could not prep");
exit(EXIT_FAILURE);
}
create_connections(&client_ctx);
create_connections(&client_ctx);
LSQ_DEBUG("entering event loop");
LSQ_DEBUG("entering event loop");
s = prog_run(&prog);
prog_cleanup(&prog);
if (promise_fd >= 0)
(void) close(promise_fd);
s = prog_run(&prog);
prog_cleanup(&prog);
if (promise_fd >= 0)
(void) close(promise_fd);
exit(0 == s ? EXIT_SUCCESS : EXIT_FAILURE);
exit(0 == s ? EXIT_SUCCESS : EXIT_FAILURE);
}

View file

@ -1,12 +1,19 @@
/* Copyright (c) 2017 LiteSpeed Technologies Inc. See LICENSE. */
#include <assert.h>
#ifndef WIN32
#include <netinet/in.h>
#include <signal.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <getopt.h>
#pragma warning(disable:4028)
#endif// WIN32
#include <event2/event.h>
@ -349,9 +356,11 @@ prog_run (struct prog *prog)
prog->prog_timer = event_new(prog->prog_eb, -1, EV_PERSIST,
prog_timer_handler, prog);
event_add(prog->prog_timer, &timeout);
#ifndef WIN32
prog->prog_usr1 = evsignal_new(prog->prog_eb, SIGUSR1,
prog_usr1_handler, prog);
evsignal_add(prog->prog_usr1, NULL);
#endif
event_base_loop(prog->prog_eb, 0);

View file

@ -8,13 +8,21 @@
#if defined(__APPLE__)
# define __APPLE_USE_RFC_3542 1
#endif
#ifndef WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#else
#include <Windows.h>
#include <WinSock2.h>
#include<io.h>
#pragma warning(disable:4996)//posix name deprecated
#define close closesocket
#endif
#include <sys/stat.h>
#include <sys/queue.h>
#include <fcntl.h>
#include <event2/event.h>
@ -75,7 +83,7 @@ allocate_packets_in (int fd)
int recvsz;
opt_len = sizeof(recvsz);
if (0 != getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &recvsz, &opt_len))
if (0 != getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&recvsz, &opt_len))
{
LSQ_ERROR("getsockopt failed: %s", strerror(errno));
return NULL;
@ -415,6 +423,7 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
}
/* Make socket non-blocking */
#ifndef WIN32
flags = fcntl(sockfd, F_GETFL);
if (-1 == flags) {
saved_errno = errno;
@ -429,6 +438,12 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
errno = saved_errno;
return -1;
}
#else
{
on = 1;
ioctlsocket(sockfd, FIONBIO, &on);
}
#endif
on = 1;
if (AF_INET == sa_local->sa_family)

View file

@ -32,7 +32,11 @@ enum sport_flags
struct service_port {
TAILQ_ENTRY(service_port) next_sport;
#ifndef WIN32
int fd;
#else
SOCKET fd;
#endif
#if __linux__
uint32_t n_dropped;
int drop_init;

View file

@ -3,237 +3,278 @@ include_directories( BEFORE ../../ssl/include )
include_directories( ../../include )
include_directories( ../../src/liblsquic )
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-value")
set(MIN_LIBS_LIST "m ${FIULIB}")
set(LIBS_LIST "pthread libssl.a libcrypto.a z ${MIN_LIBS_LIST}")
ELSE()
set(MIN_LIBS_LIST ${FIULIB} ws2_32)
set(LIBS_LIST ssl crypto ${ZLIB_NAME} ${MIN_LIBS_LIST})
ENDIF()
enable_testing()
add_executable(test_rechist test_rechist.c)
target_link_libraries(test_rechist lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_rechist lsquic ${LIBS_LIST})
add_test(rechist test_rechist)
add_executable(test_senhist test_senhist.c)
target_link_libraries(test_senhist lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_senhist lsquic ${LIBS_LIST})
add_test(senhist test_senhist)
add_executable(test_rtt test_rtt.c)
target_link_libraries(test_rtt lsquic m ${FIULIB})
target_link_libraries(test_rtt lsquic ${MIN_LIBS_LIST})
add_test(rtt test_rtt)
add_executable(test_set test_set.c)
target_link_libraries(test_set lsquic m ${FIULIB})
target_link_libraries(test_set lsquic ${MIN_LIBS_LIST})
add_test(set test_set)
add_executable(test_engine_ctor test_engine_ctor.c)
target_link_libraries(test_engine_ctor lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_engine_ctor lsquic ${LIBS_LIST})
add_test(engine_ctor test_engine_ctor)
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
add_executable(test_stream test_stream.c)
target_link_libraries(test_stream lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_stream lsquic ${LIBS_LIST})
ELSE()
add_executable(test_stream test_stream.c ../../wincompat/getopt.c ../../wincompat/getopt1.c)
target_link_libraries(test_stream lsquic ${LIBS_LIST} -FORCE:multiple)
ENDIF()
add_test(stream test_stream)
add_test(stream_hash test_stream -h)
add_test(stream_A test_stream -A)
add_test(stream_hash_A test_stream -A -h)
add_executable(test_spi test_spi.c)
target_link_libraries(test_spi lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_spi lsquic ${LIBS_LIST})
add_test(spi test_spi)
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
add_executable(test_malo test_malo.c)
target_link_libraries(test_malo lsquic m ${FIULIB})
ELSE()
add_executable(test_malo test_malo.c ../../wincompat/getopt.c ../../wincompat/getopt1.c)
ENDIF()
target_link_libraries(test_malo lsquic ${MIN_LIBS_LIST})
add_test(malo test_malo)
add_executable(test_conn_hash test_conn_hash.c)
target_link_libraries(test_conn_hash lsquic m ${FIULIB})
target_link_libraries(test_conn_hash lsquic ${MIN_LIBS_LIST})
add_test(conn_hash test_conn_hash)
add_executable(test_lsquic_hash test_lsquic_hash.c)
target_link_libraries(test_lsquic_hash lsquic m ${FIULIB})
target_link_libraries(test_lsquic_hash lsquic ${MIN_LIBS_LIST})
add_test(lsquic_hash test_lsquic_hash)
add_executable(test_blocked_gquic_le test_blocked_gquic_le.c)
target_link_libraries(test_blocked_gquic_le lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_blocked_gquic_le lsquic ${LIBS_LIST})
add_test(blocked_gquic_le test_blocked_gquic_le)
add_executable(test_blocked_gquic_be test_blocked_gquic_be.c)
target_link_libraries(test_blocked_gquic_be lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_blocked_gquic_be lsquic ${LIBS_LIST})
add_test(blocked_gquic_be test_blocked_gquic_be)
add_executable(test_rst_stream_gquic_le test_rst_stream_gquic_le.c)
target_link_libraries(test_rst_stream_gquic_le lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_rst_stream_gquic_le lsquic ${LIBS_LIST})
add_test(rst_stream_gquic_le test_rst_stream_gquic_le)
add_executable(test_rst_stream_gquic_be test_rst_stream_gquic_be.c)
target_link_libraries(test_rst_stream_gquic_be lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_rst_stream_gquic_be lsquic ${LIBS_LIST})
add_test(rst_stream_gquic_be test_rst_stream_gquic_be)
add_executable(test_rst_stream_ietf test_rst_stream_ietf.c)
target_link_libraries(test_rst_stream_ietf lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_rst_stream_ietf lsquic ${LIBS_LIST})
add_test(rst_stream_ietf test_rst_stream_ietf)
add_executable(test_conn_close_gquic_le test_conn_close_gquic_le.c)
target_link_libraries(test_conn_close_gquic_le lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_conn_close_gquic_le lsquic ${LIBS_LIST})
add_test(conn_close_gquic_le test_conn_close_gquic_le)
add_executable(test_conn_close_gquic_be test_conn_close_gquic_be.c)
target_link_libraries(test_conn_close_gquic_be lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_conn_close_gquic_be lsquic ${LIBS_LIST})
add_test(conn_close_gquic_be test_conn_close_gquic_be)
add_executable(test_goaway_gquic_le test_goaway_gquic_le.c)
target_link_libraries(test_goaway_gquic_le lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_goaway_gquic_le lsquic ${LIBS_LIST})
add_test(goaway_gquic_le test_goaway_gquic_le)
add_executable(test_goaway_gquic_be test_goaway_gquic_be.c)
target_link_libraries(test_goaway_gquic_be lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_goaway_gquic_be lsquic ${LIBS_LIST})
add_test(goaway_gquic_be test_goaway_gquic_be)
add_executable(test_wuf_gquic_le test_wuf_gquic_le.c)
target_link_libraries(test_wuf_gquic_le lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_wuf_gquic_le lsquic ${LIBS_LIST})
add_test(wuf_gquic_le test_wuf_gquic_le)
add_executable(test_wuf_gquic_be test_wuf_gquic_be.c)
target_link_libraries(test_wuf_gquic_be lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_wuf_gquic_be lsquic ${LIBS_LIST})
add_test(wuf_gquic_be test_wuf_gquic_be)
add_executable(test_ackparse_gquic_le test_ackparse_gquic_le.c)
target_link_libraries(test_ackparse_gquic_le lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_ackparse_gquic_le lsquic ${LIBS_LIST})
add_test(ackparse_gquic_le test_ackparse_gquic_le)
add_executable(test_ackparse_gquic_be test_ackparse_gquic_be.c)
target_link_libraries(test_ackparse_gquic_be lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_ackparse_gquic_be lsquic ${LIBS_LIST})
add_test(ackparse_gquic_be test_ackparse_gquic_be)
add_executable(test_ackparse_gquic_ietf test_ackparse_gquic_ietf.c)
target_link_libraries(test_ackparse_gquic_ietf lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_ackparse_gquic_ietf lsquic ${LIBS_LIST})
add_test(ackparse_gquic_ietf test_ackparse_gquic_ietf)
add_executable(test_ackgen_gquic_le test_ackgen_gquic_le.c)
target_link_libraries(test_ackgen_gquic_le lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_ackgen_gquic_le lsquic ${LIBS_LIST})
add_test(ackgen_gquic_le test_ackgen_gquic_le)
add_executable(test_ackgen_gquic_be test_ackgen_gquic_be.c)
target_link_libraries(test_ackgen_gquic_be lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_ackgen_gquic_be lsquic ${LIBS_LIST})
add_test(ackgen_gquic_be test_ackgen_gquic_be)
add_executable(test_ackgen_gquic_ietf test_ackgen_gquic_ietf.c)
target_link_libraries(test_ackgen_gquic_ietf lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_ackgen_gquic_ietf lsquic ${LIBS_LIST})
add_test(ackgen_gquic_ietf test_ackgen_gquic_ietf)
add_executable(test_sfcw test_sfcw.c)
target_link_libraries(test_sfcw lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_sfcw lsquic ${LIBS_LIST})
add_test(sfcw test_sfcw)
add_executable(test_alarmset test_alarmset.c)
target_link_libraries(test_alarmset lsquic m ${FIULIB})
target_link_libraries(test_alarmset lsquic ${MIN_LIBS_LIST})
add_test(alarmset test_alarmset)
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
add_executable(graph_cubic graph_cubic.c)
target_link_libraries(graph_cubic lsquic m ${FIULIB})
ELSE()
add_executable(graph_cubic graph_cubic.c ../../wincompat/getopt.c ../../wincompat/getopt1.c)
ENDIF()
target_link_libraries(graph_cubic lsquic ${MIN_LIBS_LIST})
add_executable(test_streamparse test_streamparse.c)
target_link_libraries(test_streamparse lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_streamparse lsquic ${LIBS_LIST})
add_test(streamparse test_streamparse)
add_executable(test_packet_out test_packet_out.c)
target_link_libraries(test_packet_out lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_packet_out lsquic ${LIBS_LIST})
add_test(packet_out test_packet_out)
add_executable(test_reg_pkt_headergen test_reg_pkt_headergen.c)
target_link_libraries(test_reg_pkt_headergen lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_reg_pkt_headergen lsquic ${LIBS_LIST})
add_test(reg_pkt_headergen test_reg_pkt_headergen)
add_executable(test_ver_nego test_ver_nego.c)
target_link_libraries(test_ver_nego lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_ver_nego lsquic ${LIBS_LIST})
add_test(ver_nego test_ver_nego)
add_executable(test_packno_len test_packno_len.c)
target_link_libraries(test_packno_len lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_packno_len lsquic ${LIBS_LIST})
add_test(packno_len test_packno_len)
add_executable(test_streamgen test_streamgen.c)
target_link_libraries(test_streamgen lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_streamgen lsquic ${LIBS_LIST})
add_test(streamgen test_streamgen)
add_executable(test_some_packets test_some_packets.c)
target_link_libraries(test_some_packets lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_some_packets lsquic ${LIBS_LIST})
add_test(some_packets test_some_packets)
add_executable(test_elision test_elision.c)
target_link_libraries(test_elision lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
target_link_libraries(test_elision lsquic ${LIBS_LIST})
ELSE()
target_link_libraries(test_elision lsquic ${LIBS_LIST} -FORCE:multiple)
ENDIF()
add_test(elision test_elision)
add_executable(test_stop_waiting_gquic_le test_stop_waiting_gquic_le.c)
target_link_libraries(test_stop_waiting_gquic_le lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_stop_waiting_gquic_le lsquic ${LIBS_LIST})
add_test(stop_waiting_gquic_le test_stop_waiting_gquic_le)
add_executable(test_stop_waiting_gquic_be test_stop_waiting_gquic_be.c)
target_link_libraries(test_stop_waiting_gquic_be lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_stop_waiting_gquic_be lsquic ${LIBS_LIST})
add_test(stop_waiting_gquic_be test_stop_waiting_gquic_be)
add_executable(test_parse_packet_in test_parse_packet_in.c)
target_link_libraries(test_parse_packet_in lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_parse_packet_in lsquic ${LIBS_LIST})
add_test(parse_packet_in test_parse_packet_in)
add_executable(test_quic_le_floats test_quic_le_floats.c)
target_link_libraries(test_quic_le_floats lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_quic_le_floats lsquic ${LIBS_LIST})
add_test(quic_le_floats test_quic_le_floats)
add_executable(test_quic_be_floats test_quic_be_floats.c)
target_link_libraries(test_quic_be_floats lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_quic_be_floats lsquic ${LIBS_LIST})
add_test(quic_be_floats test_quic_be_floats)
add_executable(test_export_key test_export_key.c)
target_link_libraries(test_export_key lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_export_key lsquic ${LIBS_LIST})
add_test(export_key test_export_key)
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
add_executable(test_frame_reader test_frame_reader.c)
target_link_libraries(test_frame_reader lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
ELSE()
add_executable(test_frame_reader test_frame_reader.c ../../wincompat/getopt.c ../../wincompat/getopt1.c)
ENDIF()
target_link_libraries(test_frame_reader lsquic ${LIBS_LIST})
add_test(frame_reader test_frame_reader)
add_executable(test_frame_writer test_frame_writer.c)
target_link_libraries(test_frame_writer lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_frame_writer lsquic ${LIBS_LIST})
add_test(frame_writer test_frame_writer)
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
add_executable(test_frame_chop test_frame_chop.c)
target_link_libraries(test_frame_chop lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
ELSE()
add_executable(test_frame_chop test_frame_chop.c ../../wincompat/getopt.c ../../wincompat/getopt1.c)
ENDIF()
target_link_libraries(test_frame_chop lsquic ${LIBS_LIST})
add_test(frame_chop test_frame_chop)
IF (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
IF (NOT ( (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") OR (CMAKE_C_COMPILER MATCHES "MSVC")) )
add_executable(test_frame_rw test_frame_rw.c)
target_link_libraries(test_frame_rw lsquic pthread libssl.a libcrypto.a z m ${FIULIB})
target_link_libraries(test_frame_rw lsquic ${LIBS_LIST})
add_test(frame_rw test_frame_rw)
ENDIF()
add_executable(test_hpack test_hpack.c)
target_link_libraries(test_hpack lsquic m ${FIULIB})
target_link_libraries(test_hpack lsquic ${MIN_LIBS_LIST})
add_test(hpack test_hpack)
add_executable(test_hkdf test_hkdf.c)
target_link_libraries(test_hkdf lsquic pthread libssl.a libcrypto.a m ${FIULIB})
target_link_libraries(test_hkdf lsquic ${LIBS_LIST})
add_test(hkdf test_hkdf)
add_executable(test_attq test_attq.c)
target_link_libraries(test_attq lsquic pthread libssl.a libcrypto.a m ${FIULIB})
target_link_libraries(test_attq lsquic ${LIBS_LIST})
add_test(attq test_attq)
add_executable(test_arr test_arr.c)
target_link_libraries(test_arr lsquic pthread libssl.a libcrypto.a m ${FIULIB})
target_link_libraries(test_arr lsquic ${LIBS_LIST})
add_test(arr test_arr)
add_executable(test_buf test_buf.c)
target_link_libraries(test_buf lsquic pthread libssl.a libcrypto.a m ${FIULIB})
target_link_libraries(test_buf lsquic ${LIBS_LIST})
add_test(buf test_buf)
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
add_executable(test_cubic test_cubic.c)
target_link_libraries(test_cubic lsquic pthread libssl.a libcrypto.a m ${FIULIB})
ELSE()
add_executable(test_cubic test_cubic.c ../../wincompat/getopt.c ../../wincompat/getopt1.c)
ENDIF()
target_link_libraries(test_cubic lsquic ${LIBS_LIST})
add_test(cubic test_cubic)
IF (NOT (CMAKE_C_COMPILER MATCHES "MSVC"))
add_executable(test_dec test_dec.c)
target_link_libraries(test_dec libssl.a libcrypto.a z m pthread ${FIULIB})
ELSE()
add_executable(test_dec test_dec.c ../../wincompat/getopt.c ../../wincompat/getopt1.c)
ENDIF()
target_link_libraries(test_dec ${LIBS_LIST})

View file

@ -7,9 +7,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#else
#include <getopt.h>
#endif
#include "lsquic_types.h"
#include "lsquic_int_types.h"
@ -60,7 +64,9 @@ main (int argc, char **argv)
struct rec *recs = NULL;
unsigned max_cwnd, width;
char *line;
#ifndef WIN32
struct winsize winsize;
#endif
enum cubic_flags flags;
lsquic_cubic_init(&cubic, 0);
@ -116,6 +122,7 @@ main (int argc, char **argv)
}
}
#ifndef WIN32
if (isatty(STDIN_FILENO))
{
if (0 == ioctl(STDIN_FILENO, TIOCGWINSZ, &winsize))
@ -127,6 +134,7 @@ main (int argc, char **argv)
}
}
else
#endif
width = 80;
width -= 5 /* cwnd */ + 1 /* space */ + 1 /* event type */ +

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic_types.h"
#include "lsquic_parse.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic_types.h"
#include "lsquic_parse.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic_types.h"
#include "lsquic_parse.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -2,6 +2,9 @@
#include <assert.h>
#include <stddef.h>
#include <string.h>
#ifdef WIN32
#include <vc_compat.h>
#endif
#include "lsquic_buf.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -5,7 +5,9 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include "lsquic.h"
#include "lsquic_int_types.h"

View file

@ -3,7 +3,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <getopt.h>
#endif
#include "lsquic.h"
#include "lsquic_int_types.h"

View file

@ -8,7 +8,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <getopt.h>
#endif
#include <openssl/aead.h>
#include <openssl/rand.h>

View file

@ -83,7 +83,6 @@ lsquic_stream_acked (lsquic_stream_t *stream)
static void
elide_single_stream_frame (void)
{
struct packet_out_srec_iter posi;
struct lsquic_engine_public enpub;
lsquic_stream_t streams[1];
lsquic_packet_out_t *packet_out;

View file

@ -7,6 +7,10 @@
#include "lsquic_crypto.h"
#ifdef WIN32
#pragma warning(disable:4295 4245) //4295: array is too small to include a terminating null character, 4245:initializing': conversion from 'int' to 'unsigned char', signed/unsigned mismatch
#endif
struct export_key_test
{
/* Line number for easy verification: */
@ -63,7 +67,7 @@ static const struct export_key_test tests[] = {
{
.ekt_lineno = __LINE__,
.ekt_ikm = "secret",
.ekt_ikm_sz = 6,
.ekt_ikm_sz = 6,
BUF_PAIR(salt,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
@ -436,13 +440,13 @@ run_ekt_test (const struct export_key_test *test)
assert(test->ekt_server_iv_sz < sizeof(server_iv));
assert(test->ekt_client_iv_sz < sizeof(client_iv));
s = export_key_material(test->ekt_ikm, test->ekt_ikm_sz,
test->ekt_salt, test->ekt_salt_sz,
test->ekt_context, test->ekt_context_sz,
test->ekt_client_key_sz, client_key,
test->ekt_server_key_sz, server_key,
test->ekt_client_iv_sz, client_iv,
test->ekt_server_iv_sz, server_iv,
s = export_key_material(test->ekt_ikm, (uint16_t)test->ekt_ikm_sz,
test->ekt_salt, (uint16_t)test->ekt_salt_sz,
test->ekt_context, (uint16_t)test->ekt_context_sz,
(uint16_t)test->ekt_client_key_sz, client_key,
(uint16_t)test->ekt_server_key_sz, server_key,
(uint16_t)test->ekt_client_iv_sz, client_iv,
(uint16_t)test->ekt_server_iv_sz, server_iv,
sub_key);
assert(0 == s); /* This function always returns zero */

View file

@ -13,7 +13,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <getopt.h>
#endif
#include <sys/queue.h>
#include "lsquic.h"

View file

@ -4,7 +4,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <getopt.h>
#endif
#include <sys/queue.h>
#include "lsquic.h"

View file

@ -15,7 +15,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <sys/queue.h>
#include "lsquic.h"

View file

@ -4,7 +4,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include <sys/queue.h>
#include "lsquic.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -10,7 +10,7 @@ void test_HKDF()
{
unsigned char prk[32];
unsigned char okm[100];
int L;
uint16_t L;
/*test case 1 */
lshkdf_extract((const unsigned char *) "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
22,

View file

@ -185,24 +185,28 @@ void displayHeader(unsigned char *buf, int len)
static void
printTable (struct lsquic_henc *enc)
{
#ifndef NDEBUG
struct enc_dyn_table_entry entry;
lsquic_henc_iter_reset(enc);
printf("Dynamic Table : \n");
while (0 == lsquic_henc_iter_next(enc, &entry))
printf("[%d] `%.*s' = `%.*s'\n",
entry.entry_id, entry.name_len, entry.name, entry.value_len, entry.value);
#endif //NDEBUG
}
void testNameValue(const char *name, const char *val, int result,
int val_match_result)
{
#ifndef NDEBUG
int val_match;
int index = lsquic_henc_get_stx_tab_id((char *)name, (uint16_t)strlen(name) ,
(char *)val, (uint16_t)strlen(val), &val_match);
printf("name: %s, val: %s, index = %d match = %d\n", name, val, index,
val_match);
assert(index == result && val_match == val_match_result);
#endif //NDEBUG
}
@ -655,6 +659,7 @@ test_hpack_encode_and_decode (void)
static void
test_hpack_self_enc_dec_test_firefox_error (void)
{
#ifndef NDEBUG
unsigned char respBuf[8192] = {0};
unsigned char *respBufEnd;
// Hpack hpack;
@ -732,6 +737,7 @@ test_hpack_self_enc_dec_test_firefox_error (void)
assert(memcmp(respBuf, buf, 90) == 0);
lsquic_henc_cleanup(&henc);
lsquic_hdec_cleanup(&hdec);
#endif //NDEBUG
}
@ -985,6 +991,7 @@ test_henc_long_uncompressable (void)
static void
test_static_table_search_exhaustive (void)
{
#ifndef NDEBUG
int i;
int count = sizeof(g_HpackStaticTableTset) / sizeof(hpack_hdr_tbl_t);
assert(count == 61);
@ -1046,12 +1053,14 @@ test_static_table_search_exhaustive (void)
assert(val_matched == 0);
printf("%s Done.\n", __func__);
#endif //NDEBUG
}
static void
test_integer_decoding (void)
{
#ifndef NDEBUG
static const struct integer_decoding_test
{
int idt_lineno;
@ -1129,12 +1138,14 @@ test_integer_decoding (void)
if (0 == s)
assert(value == test->idt_value);
}
#endif //NDEBUG
}
static void
test_huffman_encoding_corner_cases (void)
{
#ifndef NDEBUG
int s;
unsigned char buf[0x10];
@ -1162,6 +1173,7 @@ test_huffman_encoding_corner_cases (void)
s = lsquic_henc_enc_str(buf, 1, (unsigned char *) "a", 1000);
assert(-1 == s);
assert(0 == buf[1]);
#endif //NDEBUG
}

View file

@ -5,7 +5,9 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include "lsquic_hash.h"

View file

@ -3,7 +3,11 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <getopt.h>
#endif
#include "lsquic_malo.h"

View file

@ -7,7 +7,9 @@
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <fcntl.h>
#include <openssl/md5.h>

View file

@ -4,7 +4,9 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"
@ -253,7 +255,7 @@ test_restore (enum lsquic_packno_bits bits)
unsigned len, n;
enum { OP_PLUS, OP_MINUS, N_OPS } op;
uint64_t epoch, epoch_delta;
lsquic_packno_t orig_packno, cur_packno, restored_packno;
lsquic_packno_t orig_packno= 0, cur_packno, restored_packno;
len = packno_bits2len(bits);
epoch_delta = 1ULL << (len << 3);

View file

@ -3,14 +3,15 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#include "lsquic.h"
#include "lsquic_mm.h"
#include "lsquic_types.h"
#include "lsquic_int_types.h"
#include "lsquic_packet_common.h"
#include "lsquic_packet_in.h"
#include "lsquic_parse.h"
#include "lsquic_mm.h"
#include "lsquic.h"
#include "lsquic_packet_in.h"
#include "lsquic_engine_public.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"
@ -86,6 +88,7 @@ static const struct float_test to_float_tests[] = {
static void
run_to_float_tests (void)
{
#ifndef NDEBUG
const struct float_test *test;
const struct float_test *const test_end =
&to_float_tests[ sizeof(to_float_tests) / sizeof(to_float_tests[0]) ];
@ -96,6 +99,7 @@ run_to_float_tests (void)
assert(("Convertion to QUIC float format is successful",
0 == memcmp(out, test->float_time, 2)));
}
#endif //NDEBUG
}
@ -147,6 +151,7 @@ static const struct float_test from_float_tests[] = {
static void
run_from_float_tests (void)
{
#ifndef NDEBUG
const struct float_test *test;
const struct float_test *const test_end =
&from_float_tests[ sizeof(from_float_tests) / sizeof(from_float_tests[0]) ];
@ -156,6 +161,7 @@ run_from_float_tests (void)
assert(("Convertion to QUIC float format is successful",
result == test->long_time));
}
#endif // NDEBUG
}

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"
@ -86,6 +88,7 @@ static const struct float_test to_float_tests[] = {
static void
run_to_float_tests (void)
{
#ifndef NDEBUG
const struct float_test *test;
const struct float_test *const test_end =
&to_float_tests[ sizeof(to_float_tests) / sizeof(to_float_tests[0]) ];
@ -96,6 +99,7 @@ run_to_float_tests (void)
assert(("Convertion to QUIC float format is successful",
0 == memcmp(out, test->float_time, 2)));
}
#endif //NDEBUG
}
@ -147,6 +151,7 @@ static const struct float_test from_float_tests[] = {
static void
run_from_float_tests (void)
{
#ifndef NDEBUG
const struct float_test *test;
const struct float_test *const test_end =
&from_float_tests[ sizeof(from_float_tests) / sizeof(from_float_tests[0]) ];
@ -156,6 +161,7 @@ run_from_float_tests (void)
assert(("Convertion to QUIC float format is successful",
result == test->long_time));
}
#endif //NDEBUG
}

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic_types.h"
#include "lsquic_alarmset.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic_int_types.h"
#include "lsquic_rtt.h"

View file

@ -5,7 +5,9 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include "lsquic.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -8,7 +8,11 @@
#include <sys/types.h>
#include <fcntl.h>
#include <limits.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <getopt.h>
#endif
#include "lsquic.h"
@ -183,7 +187,7 @@ read_from_scheduled_packets (lsquic_send_ctl_t *send_ctl, uint32_t stream_id,
unsigned char *const begin, size_t bufsz, uint64_t first_offset, int *p_fin,
int fullcheck)
{
const struct parse_funcs *const pf = send_ctl->sc_conn_pub->lconn->cn_pf;
const struct parse_funcs *const pf_local = send_ctl->sc_conn_pub->lconn->cn_pf;
unsigned char *p = begin;
unsigned char *const end = p + bufsz;
const struct stream_rec *srec;
@ -216,7 +220,7 @@ read_from_scheduled_packets (lsquic_send_ctl_t *send_ctl, uint32_t stream_id,
srec->sr_stream->id == stream_id)
{
assert(!fin);
len = pf->pf_parse_stream_frame(packet_out->po_data + srec->sr_off,
len = pf_local->pf_parse_stream_frame(packet_out->po_data + srec->sr_off,
packet_out->po_data_sz - srec->sr_off, &frame);
assert(len > 0);
assert(frame.stream_id == srec->sr_stream->id);
@ -1421,8 +1425,8 @@ test_writing_to_stream_schedule_stream_packets_immediately (void)
n_closed = 0;
stream = new_stream(&tobjs, 123);
assert(("Stream initialized", stream));
const struct test_ctx *const test_ctx = tobjs.stream_if_ctx;
assert(("on_new_stream called correctly", stream == test_ctx->stream));
const struct test_ctx *const test_ctx_local = tobjs.stream_if_ctx;
assert(("on_new_stream called correctly", stream == test_ctx_local->stream));
assert(LSQUIC_STREAM_DEFAULT_PRIO == lsquic_stream_priority(stream));
assert(lconn == lsquic_stream_conn(stream));
@ -1489,8 +1493,8 @@ test_writing_to_stream_outside_callback (void)
n_closed = 0;
stream = new_stream(&tobjs, 123);
assert(("Stream initialized", stream));
const struct test_ctx *const test_ctx = tobjs.stream_if_ctx;
assert(("on_new_stream called correctly", stream == test_ctx->stream));
const struct test_ctx *const test_ctx_local = tobjs.stream_if_ctx;
assert(("on_new_stream called correctly", stream == test_ctx_local->stream));
assert(LSQUIC_STREAM_DEFAULT_PRIO == lsquic_stream_priority(stream));
assert(lconn == lsquic_stream_conn(stream));
@ -2357,7 +2361,7 @@ static void
init_buf (void *buf, size_t sz)
{
unsigned char *p = buf;
unsigned char *const end = buf + sz;
unsigned char *const end = (unsigned char*)buf + sz;
size_t n;
while (p < end)

View file

@ -4,14 +4,16 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"
#include "lsquic_alarmset.h"
#include "lsquic_parse.h"
#include "lsquic_sfcw.h"
#include "lsquic_stream.h"
#include "lsquic.h"
struct test {
int lineno;
@ -747,18 +749,18 @@ static struct test_ctx {
static int
stream_tosend_fin (void *stream)
{
struct test_ctx *test_ctx = stream;
return test_ctx->test->fin[ test_ctx->next_fin++ ];
struct test_ctx *test_ctx2 = stream;
return test_ctx2->test->fin[ test_ctx2->next_fin++ ];
}
static size_t
stream_tosend_read (void *stream, void *buf, size_t len, int *reached_fin)
{
struct test_ctx *test_ctx = stream;
if (test_ctx->test->data_sz < len)
len = test_ctx->test->data_sz;
memcpy(buf, test_ctx->test->data, len);
struct test_ctx *test_ctx2 = stream;
if (test_ctx2->test->data_sz < len)
len = test_ctx2->test->data_sz;
memcpy(buf, test_ctx2->test->data, len);
*reached_fin = stream_tosend_fin(stream);
return len;
}
@ -767,8 +769,8 @@ stream_tosend_read (void *stream, void *buf, size_t len, int *reached_fin)
static size_t
stream_tosend_size (void *stream)
{
struct test_ctx *test_ctx = stream;
return test_ctx->test->data_sz;
struct test_ctx *test_ctx2 = stream;
return test_ctx2->test->data_sz;
}

View file

@ -3,14 +3,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include <sys/queue.h>
#include "lsquic.h"
#include "lsquic_types.h"
#include "lsquic_alarmset.h"
#include "lsquic_parse.h"
#include "lsquic_packet_common.h"
#include "lsquic_packet_in.h"
#include "lsquic.h"
struct test {
const char *name;

View file

@ -4,7 +4,9 @@
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

View file

@ -3,7 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include "lsquic.h"
#include "lsquic_types.h"

8
wincompat/README.txt Normal file
View file

@ -0,0 +1,8 @@
- vcpkg does not have boringssl, so you'll have to build it yourself. Follow the instructions at the boringssl repository.
With the caveat that you should do it from a VC command prompt for the correct architecture and make sure to set all
the paths for perl,ninja,etc. correctly. Also watch out for C runtime library mismatches. The easiest fix for me was to
change the flags in the CMake cache file.
- zlib and libevent do exist in vcpkg.
- getopt files are really old and could probably use updating.

758
wincompat/getopt.c Normal file
View file

@ -0,0 +1,758 @@
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
#ifndef _NO_PROTO
#define _NO_PROTO
#endif
#pragma warning(disable:4131)
#ifdef HAVE_CONFIG_H
#if defined (emacs) || defined (CONFIG_BROKETS)
/* We use <config.h> instead of "config.h" so that a compilation
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because it found this file in $srcdir). */
#include <config.h>
#else
#include "config.h"
#endif
#endif
#ifndef __STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
#include <string.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
#endif /* GNU C library. */
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "getopt.h"
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = NULL;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* XXX 1003.2 says this must be 1 before any call. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Set to an option character which was unrecognized.
This must be initialized on some systems to avoid linking in the
system's own getopt implementation. */
int optopt = '?';
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
/* Value of POSIXLY_CORRECT environment variable. */
static char *posixly_correct;
#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
#define my_index strchr
#else
/* Avoid depending on library functions or files
whose names are inconsistent. */
char *getenv ();
static char *
my_index (str, chr)
const char *str;
int chr;
{
while (*str)
{
if (*str == chr)
return (char *) str;
str++;
}
return 0;
}
/* If using GCC, we can safely declare strlen this way.
If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
That was relevant to code that was here before. */
#ifndef __STDC__
/* gcc with -traditional declares the built-in strlen to return int,
and has done so at least since version 2.4.5. -- rms. */
extern int strlen (const char *);
#endif /* not __STDC__ */
#endif /* __GNUC__ */
#endif /* not __GNU_LIBRARY__ */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (argv)
char **argv;
{
int bottom = first_nonopt;
int middle = last_nonopt;
int top = optind;
char *tem;
/* Exchange the shorter segment with the far end of the longer segment.
That puts the shorter segment into the right place.
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
/* Bottom segment is the short one. */
int len = middle - bottom;
register int i;
/* Swap it with the top part of the top segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
/* Exclude the moved bottom segment from further swapping. */
top -= len;
}
else
{
/* Top segment is the short one. */
int len = top - middle;
register int i;
/* Swap it with the bottom part of the bottom segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
/* Exclude the moved top segment from further swapping. */
bottom += len;
}
}
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
/* Initialize the internal data when the first call is made. */
static const char *
_getopt_initialize (optstring)
const char *optstring;
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
posixly_correct = getenv ("POSIXLY_CORRECT");
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (posixly_correct != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
return optstring;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc;
char *const *argv;
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{
optarg = NULL;
if (optind == 0)
optstring = _getopt_initialize (optstring);
if (nextchar == NULL || *nextchar == '\0')
{
/* Advance to the next ARGV-element. */
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0'))
optind++;
last_nonopt = optind;
}
/* The special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Skip the initial punctuation. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
/* Decode the current option-ARGV-element. */
/* Check whether the ARGV-element is a long option.
If long_only and the ARGV-element has the form "-f", where f is
a valid short option, don't consider it an abbreviated form of
a long option that starts with f. Otherwise there would be no
way to give the -f short option.
On the other hand, if there's a long option "fubar" and
the ARGV-element is "-fu", do consider that an abbreviation of
the long option, just like "--fu", and not "-f" with arg "u".
This distinction seems to be the most useful approach. */
if (longopts != NULL
&& (argv[optind][1] == '-'
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
{
char *nameend;
const struct option *p;
const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound = 0;
int option_index;
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
/* Do nothing. */ ;
/* Test all long options for either exact match
or abbreviated matches. */
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar))
{
if (nameend - nextchar == (int) strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second or later nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
fprintf (stderr, "%s: option `%s' is ambiguous\n",
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
if (*nameend)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = nameend + 1;
else
{
if (opterr)
{
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
"%s: option `--%s' doesn't allow an argument\n",
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
"%s: option `%c%s' doesn't allow an argument\n",
argv[0], argv[optind - 1][0], pfound->name);
}
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
if (opterr)
fprintf (stderr, "%s: option `%s' requires an argument\n",
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
nextchar += strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, "%s: unrecognized option `--%s'\n",
argv[0], nextchar);
else
/* +option or -option */
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++;
return '?';
}
}
/* Look at and handle the next short option-character. */
{
char c = *nextchar++;
char *temp = my_index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
++optind;
if (temp == NULL || c == ':')
{
if (opterr)
{
if (posixly_correct)
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
else
fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
}
optopt = c;
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
{
optarg = nextchar;
optind++;
}
else
optarg = NULL;
nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != '\0')
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr)
{
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: option requires an argument -- %c\n",
argv[0], c);
}
optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
}
}
return c;
}
}
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

131
wincompat/getopt.h Normal file
View file

@ -0,0 +1,131 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* $CVSid: @(#)getopt.h 1.7 94/09/21 $ */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#if __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if __STDC__
#if defined(__GNU_LIBRARY__)
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* not __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* not __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

188
wincompat/getopt1.c Normal file
View file

@ -0,0 +1,188 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#if defined (emacs) || defined (CONFIG_BROKETS)
/* We use <config.h> instead of "config.h" so that a compilation
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because it found this file in $srcdir). */
#include <config.h>
#else
#include "config.h"
#endif
#endif
#pragma warning(disable:4131)
#include "getopt.h"
#ifndef __STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#else
char *getenv ();
#endif
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == EOF)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

859
wincompat/sys/queue.h Normal file
View file

@ -0,0 +1,859 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
* $FreeBSD$
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
/*
* This file defines four types of data structures: singly-linked lists,
* singly-linked tail queues, lists and tail queues.
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A singly-linked tail queue is headed by a pair of pointers, one to the
* head of the list and the other to the tail of the list. The elements are
* singly linked for minimum space and pointer manipulation overhead at the
* expense of O(n) removal for arbitrary elements. New elements can be added
* to the list after an existing element, at the head of the list, or at the
* end of the list. Elements being removed from the head of the tail queue
* should use the explicit macro for this purpose for optimum efficiency.
* A singly-linked tail queue may only be traversed in the forward direction.
* Singly-linked tail queues are ideal for applications with large datasets
* and few or no removals or for implementing a FIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may be traversed in either direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* For details on the use of these macros, see the queue(3) manual page.
*
* Below is a summary of implemented functions where:
* + means the macro is available
* - means the macro is not available
* s means the macro is available but is slow (runs in O(n) time)
*
* SLIST LIST STAILQ TAILQ
* _HEAD + + + +
* _CLASS_HEAD + + + +
* _HEAD_INITIALIZER + + + +
* _ENTRY + + + +
* _CLASS_ENTRY + + + +
* _INIT + + + +
* _EMPTY + + + +
* _FIRST + + + +
* _NEXT + + + +
* _PREV - + - +
* _LAST - - + +
* _FOREACH + + + +
* _FOREACH_FROM + + + +
* _FOREACH_SAFE + + + +
* _FOREACH_FROM_SAFE + + + +
* _FOREACH_REVERSE - - - +
* _FOREACH_REVERSE_FROM - - - +
* _FOREACH_REVERSE_SAFE - - - +
* _FOREACH_REVERSE_FROM_SAFE - - - +
* _INSERT_HEAD + + + +
* _INSERT_BEFORE - + - +
* _INSERT_AFTER + + + +
* _INSERT_TAIL - - + +
* _CONCAT s s + +
* _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + -
* _REMOVE s + s +
* _SWAP + + + +
*
*/
#ifdef QUEUE_MACRO_DEBUG
#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH
#define QUEUE_MACRO_DEBUG_TRACE
#define QUEUE_MACRO_DEBUG_TRASH
#endif
#ifdef QUEUE_MACRO_DEBUG_TRACE
/* Store the last 2 places the queue element or head was altered */
struct qm_trace {
unsigned long lastline;
unsigned long prevline;
const char *lastfile;
const char *prevfile;
};
#define TRACEBUF struct qm_trace trace;
#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } ,
#define QMD_TRACE_HEAD(head) do { \
(head)->trace.prevline = (head)->trace.lastline; \
(head)->trace.prevfile = (head)->trace.lastfile; \
(head)->trace.lastline = __LINE__; \
(head)->trace.lastfile = __FILE__; \
} while (0)
#define QMD_TRACE_ELEM(elem) do { \
(elem)->trace.prevline = (elem)->trace.lastline; \
(elem)->trace.prevfile = (elem)->trace.lastfile; \
(elem)->trace.lastline = __LINE__; \
(elem)->trace.lastfile = __FILE__; \
} while (0)
#else /* !QUEUE_MACRO_DEBUG_TRACE */
#define QMD_TRACE_ELEM(elem)
#define QMD_TRACE_HEAD(head)
#define TRACEBUF
#define TRACEBUF_INITIALIZER
#endif /* QUEUE_MACRO_DEBUG_TRACE */
#ifdef QUEUE_MACRO_DEBUG_TRASH
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1)
#else /* !QUEUE_MACRO_DEBUG_TRASH */
#define TRASHIT(x)
#define QMD_IS_TRASHED(x) 0
#endif /* QUEUE_MACRO_DEBUG_TRASH */
#if defined(QUEUE_MACRO_DEBUG_TRACE) || defined(QUEUE_MACRO_DEBUG_TRASH)
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
#else /* !QUEUE_MACRO_DEBUG_TRACE && !QUEUE_MACRO_DEBUG_TRASH */
#define QMD_SAVELINK(name, link)
#endif /* QUEUE_MACRO_DEBUG_TRACE || QUEUE_MACRO_DEBUG_TRASH */
#ifdef __cplusplus
/*
* In C++ there can be structure lists and class lists:
*/
#define QUEUE_TYPEOF(type) type
#else
#define QUEUE_TYPEOF(type) struct type
#endif
/*
* Singly-linked List declarations.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_CLASS_HEAD(name, type) \
struct name { \
class type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
#define SLIST_CLASS_ENTRY(type) \
struct { \
class type *sle_next; /* next element */ \
}
/*
* Singly-linked List functions.
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \
if (*(prevp) != (elm)) \
panic("Bad prevptr *(%p) == %p != %p", \
(prevp), *(prevp), (elm)); \
} while (0)
#else
#define QMD_SLIST_CHECK_PREVPTR(prevp, elm)
#endif
#define SLIST_CONCAT(head1, head2, type, field) do { \
QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \
if (curelm == NULL) { \
if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \
SLIST_INIT(head2); \
} else if (SLIST_FIRST(head2) != NULL) { \
while (SLIST_NEXT(curelm, field) != NULL) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \
SLIST_INIT(head2); \
} \
} while (0)
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST((head)); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != NULL; \
(varp) = &SLIST_NEXT((var), field))
#define SLIST_INIT(head) do { \
SLIST_FIRST((head)) = NULL; \
} while (0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
} while (0)
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
else { \
QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \
while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_REMOVE_AFTER(curelm, field); \
} \
TRASHIT(*oldnext); \
} while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \
SLIST_NEXT(elm, field) = \
SLIST_NEXT(SLIST_NEXT(elm, field), field); \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \
QMD_SLIST_CHECK_PREVPTR(prevp, elm); \
*(prevp) = SLIST_NEXT(elm, field); \
TRASHIT((elm)->field.sle_next); \
} while (0)
#define SLIST_SWAP(head1, head2, type) do { \
QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
SLIST_FIRST(head2) = swap_first; \
} while (0)
/*
* Singly-linked Tail queue declarations.
*/
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first;/* first element */ \
struct type **stqh_last;/* addr of last next element */ \
}
#define STAILQ_CLASS_HEAD(name, type) \
struct name { \
class type *stqh_first; /* first element */ \
class type **stqh_last; /* addr of last next element */ \
}
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
#define STAILQ_CLASS_ENTRY(type) \
struct { \
class type *stqe_next; /* next element */ \
}
/*
* Singly-linked Tail queue functions.
*/
#define STAILQ_CONCAT(head1, head2) do { \
if (!STAILQ_EMPTY((head2))) { \
*(head1)->stqh_last = (head2)->stqh_first; \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_INIT((head2)); \
} \
} while (0)
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_FOREACH(var, head, field) \
for((var) = STAILQ_FIRST((head)); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = STAILQ_FIRST((head)); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((tqelm), field) = (elm); \
} while (0)
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \
} while (0)
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? NULL : \
__containerof((head)->stqh_last, \
QUEUE_TYPEOF(type), field.stqe_next))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} \
else { \
QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
STAILQ_REMOVE_AFTER(head, curelm, field); \
} \
TRASHIT(*oldnext); \
} while (0)
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
if ((STAILQ_NEXT(elm, field) = \
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_SWAP(head1, head2, type) do { \
QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \
QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \
STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_FIRST(head2) = swap_first; \
(head2)->stqh_last = swap_last; \
if (STAILQ_EMPTY(head1)) \
(head1)->stqh_last = &STAILQ_FIRST(head1); \
if (STAILQ_EMPTY(head2)) \
(head2)->stqh_last = &STAILQ_FIRST(head2); \
} while (0)
/*
* List declarations.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_CLASS_HEAD(name, type) \
struct name { \
class type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
#define LIST_CLASS_ENTRY(type) \
struct { \
class type *le_next; /* next element */ \
class type **le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
/*
* QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME)
*
* If the list is non-empty, validates that the first element of the list
* points back at 'head.'
*/
#define QMD_LIST_CHECK_HEAD(head, field) do { \
if (LIST_FIRST((head)) != NULL && \
LIST_FIRST((head))->field.le_prev != \
&LIST_FIRST((head))) \
panic("Bad list head %p first->prev != head", (head)); \
} while (0)
/*
* QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME)
*
* If an element follows 'elm' in the list, validates that the next element
* points back at 'elm.'
*/
#define QMD_LIST_CHECK_NEXT(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL && \
LIST_NEXT((elm), field)->field.le_prev != \
&((elm)->field.le_next)) \
panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0)
/*
* QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME)
*
* Validates that the previous element (or head of the list) points to 'elm.'
*/
#define QMD_LIST_CHECK_PREV(elm, field) do { \
if (*(elm)->field.le_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \
} while (0)
#else
#define QMD_LIST_CHECK_HEAD(head, field)
#define QMD_LIST_CHECK_NEXT(elm, field)
#define QMD_LIST_CHECK_PREV(elm, field)
#endif /* (_KERNEL && INVARIANTS) */
#define LIST_CONCAT(head1, head2, type, field) do { \
QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \
if (curelm == NULL) { \
if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \
LIST_FIRST(head2)->field.le_prev = \
&LIST_FIRST((head1)); \
LIST_INIT(head2); \
} \
} else if (LIST_FIRST(head2) != NULL) { \
while (LIST_NEXT(curelm, field) != NULL) \
curelm = LIST_NEXT(curelm, field); \
LIST_NEXT(curelm, field) = LIST_FIRST(head2); \
LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \
LIST_INIT(head2); \
} \
} while (0)
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST((head)); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
QMD_LIST_CHECK_NEXT(listelm, field); \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
QMD_LIST_CHECK_PREV(listelm, field); \
(elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
QMD_LIST_CHECK_HEAD((head), field); \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0)
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_PREV(elm, head, type, field) \
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
__containerof((elm)->field.le_prev, \
QUEUE_TYPEOF(type), field.le_next))
#define LIST_REMOVE(elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
QMD_LIST_CHECK_NEXT(elm, field); \
QMD_LIST_CHECK_PREV(elm, field); \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
} while (0)
#define LIST_SWAP(head1, head2, type, field) do { \
QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \
LIST_FIRST((head1)) = LIST_FIRST((head2)); \
LIST_FIRST((head2)) = swap_tmp; \
if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
} while (0)
/*
* Tail queue declarations.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
TRACEBUF \
}
#define TAILQ_CLASS_HEAD(name, type) \
struct name { \
class type *tqh_first; /* first element */ \
class type **tqh_last; /* addr of last next element */ \
TRACEBUF \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
TRACEBUF \
}
#define TAILQ_CLASS_ENTRY(type) \
struct { \
class type *tqe_next; /* next element */ \
class type **tqe_prev; /* address of previous next element */ \
TRACEBUF \
}
/*
* Tail queue functions.
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
/*
* QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME)
*
* If the tailq is non-empty, validates that the first element of the tailq
* points back at 'head.'
*/
#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
if (!TAILQ_EMPTY(head) && \
TAILQ_FIRST((head))->field.tqe_prev != \
&TAILQ_FIRST((head))) \
panic("Bad tailq head %p first->prev != head", (head)); \
} while (0)
/*
* QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME)
*
* Validates that the tail of the tailq is a pointer to pointer to NULL.
*/
#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
if (*(head)->tqh_last != NULL) \
panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
} while (0)
/*
* QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME)
*
* If an element follows 'elm' in the tailq, validates that the next element
* points back at 'elm.'
*/
#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
if (TAILQ_NEXT((elm), field) != NULL && \
TAILQ_NEXT((elm), field)->field.tqe_prev != \
&((elm)->field.tqe_next)) \
panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0)
/*
* QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME)
*
* Validates that the previous element (or head of the tailq) points to 'elm.'
*/
#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
if (*(elm)->field.tqe_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \
} while (0)
#else
#define QMD_TAILQ_CHECK_HEAD(head, field)
#define QMD_TAILQ_CHECK_TAIL(head, headname)
#define QMD_TAILQ_CHECK_NEXT(elm, field)
#define QMD_TAILQ_CHECK_PREV(elm, field)
#endif /* (_KERNEL && INVARIANTS) */
#define TAILQ_CONCAT(head1, head2, field) do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
QMD_TRACE_HEAD(head1); \
QMD_TRACE_HEAD(head2); \
} \
} while (0)
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST((head), headname); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
QMD_TRACE_HEAD(head); \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
QMD_TAILQ_CHECK_NEXT(listelm, field); \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
TAILQ_NEXT((elm), field)->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else { \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
QMD_TRACE_HEAD(head); \
} \
TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&(listelm)->field); \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
QMD_TAILQ_CHECK_PREV(listelm, field); \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&(listelm)->field); \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
QMD_TAILQ_CHECK_HEAD(head, field); \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
QMD_TAILQ_CHECK_TAIL(head, field); \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
QMD_TAILQ_CHECK_NEXT(elm, field); \
QMD_TAILQ_CHECK_PREV(elm, field); \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else { \
(head)->tqh_last = (elm)->field.tqe_prev; \
QMD_TRACE_HEAD(head); \
} \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_SWAP(head1, head2, type, field) do { \
QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \
QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \
(head1)->tqh_first = (head2)->tqh_first; \
(head1)->tqh_last = (head2)->tqh_last; \
(head2)->tqh_first = swap_first; \
(head2)->tqh_last = swap_last; \
if ((swap_first = (head1)->tqh_first) != NULL) \
swap_first->field.tqe_prev = &(head1)->tqh_first; \
else \
(head1)->tqh_last = &(head1)->tqh_first; \
if ((swap_first = (head2)->tqh_first) != NULL) \
swap_first->field.tqe_prev = &(head2)->tqh_first; \
else \
(head2)->tqh_last = &(head2)->tqh_first; \
} while (0)
#endif /* !_SYS_QUEUE_H_ */

1019
wincompat/test_common_win.c Normal file

File diff suppressed because it is too large Load diff

34
wincompat/vc_compat.h Normal file
View file

@ -0,0 +1,34 @@
#pragma once
#include <Windows.h>
#include <winsock2.h>
typedef SSIZE_T ssize_t;
struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes to transfer */
};
#define strcasecmp(a,b) _strcmpi(a,b)
#define strdup _strdup
#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno)
#pragma warning(disable: 4018 4100 4127 4189 4200 4204 4214 4152 4221 4244 4245 4267 4334 4702 4706 4804 )
/*
4018:signed/unsigned mismatch
4100:unreferenced formal parameter,
4127: conditional expression is constant
4152: nonstandard extension, function/data pointer conversion in expression
4189:local variable is initialized but not referenced
4200:zero-sized-array in struct,
4204: nonstandard extension used: non-constant aggregate initializer,
4214: nonstandard extension used: bit field types other than int
4221: nonstandard extension used:xx cannot be initialized using address of automatic variable y,
4244: '+=': conversion from 'int' to 'unsigned short', possible loss of data
4245:'=': conversion from 'int' to 'unsigned int', signed/unsigned mismatch
4267 function': conversion from 'size_t' to 'int', possible loss of data
4334: '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
4702: unreachable code
4706: assignment within conditional expression,
4804: '-': unsafe use of type 'bool' in operation
*/