Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2424,6 +2424,19 @@ then
AM_CFLAGS="$AM_CFLAGS -DSHOW_SECRETS -DHAVE_SECRET_CALLBACK -DWOLFSSL_SSLKEYLOGFILE -DWOLFSSL_KEYLOG_EXPORT_WARNED"
fi

# TLS receive read-ahead: when enabled at runtime via wolfSSL_set_read_ahead(),
# the record-header read pulls in up to a full record in one recv(), avoiding a
# second syscall for the body. Opt-in (default: disabled).
AC_ARG_ENABLE([readahead],
[AS_HELP_STRING([--enable-readahead],[Enable TLS receive read-ahead support, activated at runtime with wolfSSL_set_read_ahead() (default: disabled)])],
[ ENABLED_READAHEAD=$enableval ],
[ ENABLED_READAHEAD=no ]
)
if test "$ENABLED_READAHEAD" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TLS_READ_AHEAD"
fi

# TLS v1.3 Draft 18 (Note: only final TLS v1.3 supported, here for backwards build compatibility)
AC_ARG_ENABLE([tls13-draft18],
[AS_HELP_STRING([--enable-tls13-draft18],[Enable wolfSSL TLS v1.3 Draft 18 (default: disabled)])],
Expand Down Expand Up @@ -13623,6 +13636,7 @@ echo " * FrodoKEM decapsulate: $ENABLED_FRODOKEM_DECAPSULATE"
echo " * ERR Queues per Thread: $ENABLED_ERRORQUEUEPERTHREAD"
echo " * rwlock: $ENABLED_RWLOCK"
echo " * keylog export: $ENABLED_KEYLOG_EXPORT"
echo " * TLS receive read-ahead: $ENABLED_READAHEAD"
echo " * AutoSAR : $ENABLED_AUTOSAR"
echo " * ML-KEM standalone: $ENABLED_MLKEM_STANDALONE"
echo " * PQ/T hybrids: $ENABLED_PQC_HYBRIDS"
Expand Down
132 changes: 132 additions & 0 deletions doc/dox_comments/header_files-ja/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4530,6 +4530,138 @@ int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx);
*/
int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v);

/*!
\ingroup Setup

\brief この関数は、このWOLFSSL_CTXから作成されるセッションに対して、リードアヘッドの
受信ウィンドウサイズを設定します。リードアヘッドが有効な場合
(wolfSSL_CTX_set_read_ahead())、1回のrecv()で最大 \p len バイトを読み込みます。
- \p len が0の場合、ウィンドウは1レコード分のデフォルトにリセットされます。これは
新しく作成されたコンテキストがすでに持つウィンドウでもあり、レコードのボディが
ヘッダーと一緒に読み込まれるため、2回目のシステムコールを必要としません。
- \p len が1レコードより大きい場合、1回のrecv()で連続する複数のレコードをまとめて
読み込むことができ、レコードごとに1回ではなく1回のシステムコールで済みます。
- \p len が1レコードより小さい場合、ピアのレコードが小さいと分かっているとき
(例:4KB)に受信バッファのフットプリントを抑え、1レコード分のデフォルトと比べて
ヒープを節約します。
\p len は投機的な先読みウィンドウであり、上限ではありません。\p len より大きな
レコードも正しく受信されます。入力バッファはそのレコードの実際のサイズまでオンデマンドで
拡張され(そのレコードについては追加のシステムコールと再割り当てのコストがかかります)、
その後ウィンドウサイズまで縮小されます。そのため、保持されるフットプリントは、観測された
最大のレコードではなく \p len によって制限されたままになります。この設定は、ライブラリが
リードアヘッドサポート付き(--enable-readahead / WOLFSSL_TLS_READ_AHEAD)で
ビルドされている場合にのみI/Oに影響します。それ以外の場合、値は保存されますが効果は
ありません。これはOpenSSLのSSL_CTX_set_default_read_buffer_len()に相当するwolfSSLの
関数ですが、OpenSSLと異なりステータスコードを返し(戻り値を無視する呼び出し元も
ソース互換のままです)、1レコードより小さいサイズも尊重します(OpenSSLはバッファを
拡大することしかしません)。\p len がWOLFSSL_MAX_READ_AHEAD_SZ(16MB)を超える場合、
その最大値に制限されます。0と過大な値はどちらも正規化されるため、
wolfSSL_CTX_get_default_read_buffer_len()は生の引数ではなく、実効ウィンドウ(未設定の
場合は0ではなく1レコード分のデフォルト)を報告します。

\note これはメモリとシステムコールのトレードオフです。リードアヘッドが有効な間、入力
バッファは接続の存続期間中保持されます(\p len に制限されます)。そのため、大きな
\p len に多数の同時接続を掛け合わせると恒常的なメモリ消費となり、一方で小さな \p len は
接続ごとのフットプリントを抑えますが、それを超えるレコードではより多くのシステムコールが
必要になります。

\return SSL_SUCCESS バッファ長が設定された場合。
\return SSL_FAILURE ctxがNULLの場合。

\param ctx リードアヘッドバッファ長を設定するWOLFSSL_CTX構造体。
\param len リードアヘッドの結合バッファサイズ(バイト単位、0 = 1レコード)。

_Example_
\code
WOLFSSL_CTX* ctx;
// ctxをセットアップ
wolfSSL_CTX_set_read_ahead(ctx, 1);
// 1回のrecv()で最大4つの最大サイズレコードをまとめて読み込む
wolfSSL_CTX_set_default_read_buffer_len(ctx, 4 * 16384);
\endcode

\sa wolfSSL_CTX_set_read_ahead
\sa wolfSSL_set_default_read_buffer_len
\sa wolfSSL_has_pending
*/
int wolfSSL_CTX_set_default_read_buffer_len(WOLFSSL_CTX* ctx, size_t len);

/*!
\ingroup Setup

\brief この関数は、単一のWOLFSSLセッションにリードアヘッドの結合バッファサイズを設定し、
そのWOLFSSL_CTXから継承した値を上書きします。詳しい説明、1レコード分のデフォルト、および
メモリとシステムコールのトレードオフについては、
wolfSSL_CTX_set_default_read_buffer_len()を参照してください。

\return SSL_SUCCESS バッファ長が設定された場合。
\return SSL_FAILURE sslがNULLの場合。

\param ssl リードアヘッドバッファ長を設定するWOLFSSL構造体。
\param len リードアヘッドの結合バッファサイズ(バイト単位、0 = 1レコード)。

\sa wolfSSL_CTX_set_default_read_buffer_len
\sa wolfSSL_set_read_ahead
\sa wolfSSL_has_pending
*/
int wolfSSL_set_default_read_buffer_len(WOLFSSL* ssl, size_t len);

/*!
\ingroup Setup

\brief この関数は、wolfSSL_CTX_set_default_read_buffer_len()によってWOLFSSL_CTXに
設定されたリードアヘッドの結合バッファサイズを返します。設定時に長さ0と過大な値は
正規化されるため、報告される値は生の引数ではなく、実際に使用されている実効ウィンドウ
(長さが一度も変更されていない場合は0ではなく1レコード分のデフォルト)です。

\return len 成功時にはリードアヘッドバッファ長(バイト単位)を返します。
\return SSL_FAILURE ctxがNULLの場合。

\param ctx リードアヘッドバッファ長を取得するWOLFSSL_CTX構造体。

_Example_
\code
WOLFSSL_CTX* ctx;
long len;
// ctxをセットアップ
len = wolfSSL_CTX_get_default_read_buffer_len(ctx);
// lenを確認
\endcode

\sa wolfSSL_CTX_set_default_read_buffer_len
\sa wolfSSL_get_default_read_buffer_len
\sa wolfSSL_CTX_set_read_ahead
*/
long wolfSSL_CTX_get_default_read_buffer_len(WOLFSSL_CTX* ctx);

/*!
\ingroup Setup

\brief この関数は、単一のWOLFSSLセッションで有効なリードアヘッドの結合バッファサイズを
返します。この値は、そのWOLFSSL_CTXから継承されたものか、
wolfSSL_set_default_read_buffer_len()で上書きされたもののいずれかです。WOLFSSL_CTXの
ゲッターと同様に、報告される値は生の引数ではなく、実際に使用されている実効ウィンドウです。

\return len 成功時にはリードアヘッドバッファ長(バイト単位)を返します。
\return SSL_FAILURE sslがNULLの場合。

\param ssl リードアヘッドバッファ長を取得するWOLFSSL構造体。

_Example_
\code
WOLFSSL* ssl;
long len;
// sslをセットアップ
len = wolfSSL_get_default_read_buffer_len(ssl);
// lenを確認
\endcode

\sa wolfSSL_set_default_read_buffer_len
\sa wolfSSL_CTX_get_default_read_buffer_len
\sa wolfSSL_set_read_ahead
*/
long wolfSSL_get_default_read_buffer_len(const WOLFSSL* ssl);

/*!
\ingroup Setup

Expand Down
153 changes: 153 additions & 0 deletions doc/dox_comments/header_files/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5486,6 +5486,21 @@ int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx);
\ingroup Setup

\brief This function sets the read ahead flag in the WOLFSSL_CTX structure.
When enabled, the record-header read pulls in up to a full TLS record in a
single recv(), so the body (and any following buffered records) is obtained
without a second syscall. The flag only changes I/O behaviour when the
library is built with read-ahead support (--enable-readahead /
WOLFSSL_TLS_READ_AHEAD); otherwise it is stored but inert.

\note With read-ahead enabled, undecrypted data can remain buffered
internally while the socket has no more data to read. wolfSSL_has_pending()
reports whether any such data is buffered, but a non-zero return does not
guarantee a full record is available: wolfSSL_read() may still return
WANT_READ when only a partial record is buffered. Event-driven applications
should therefore drain the connection by calling wolfSSL_read() until it
returns WANT_READ (or an error) before returning to select()/poll(), rather
than looping on wolfSSL_has_pending() alone; otherwise buffered data could
be missed or the loop could spin.

\return SSL_SUCCESS If ctx read ahead flag set.
\return SSL_FAILURE If ctx is NULL then SSL_FAILURE is returned.
Expand All @@ -5506,9 +5521,147 @@ int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx);
\sa wolfSSL_CTX_new
\sa wolfSSL_CTX_free
\sa wolfSSL_CTX_get_read_ahead
\sa wolfSSL_has_pending
*/
int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v);

/*!
\ingroup Setup

\brief This function sets the read-ahead receive window size for contexts
created from this WOLFSSL_CTX. When read-ahead is enabled
(wolfSSL_CTX_set_read_ahead()), a single recv() pulls in up to \p len bytes:
- \p len of 0 resets the window to the one-record default. This is also
the window a freshly created context already carries, so the record body
is read together with its header without a second syscall.
- A \p len larger than one record lets a single recv() coalesce several
back-to-back records, one syscall instead of one per record.
- A \p len smaller than one record caps the receive buffer's footprint
when the peer's records are known to be small (e.g. 4 KB), saving heap
versus the one-record default.
\p len is only a speculative read window, not a hard limit: a record larger
than \p len is still received correctly, with the input buffer grown to the
record's actual size on demand (costing an extra syscall and reallocation
for that record) and then reallocated back down to the window once the
oversized record is consumed, so the retained footprint stays bounded by
\p len rather than by the largest record seen. The setting only affects I/O
when the library is built with read-ahead support (--enable-readahead /
WOLFSSL_TLS_READ_AHEAD); otherwise it is stored but inert. This is the
wolfSSL equivalent of OpenSSL's SSL_CTX_set_default_read_buffer_len(); unlike
OpenSSL it returns a status code (callers that ignore the return remain
source-compatible) and it honours sizes below one record, whereas OpenSSL
only ever enlarges the buffer. A \p len above WOLFSSL_MAX_READ_AHEAD_SZ
(16 MB) is clamped to that maximum. Because 0 and oversized values are both
normalised, wolfSSL_CTX_get_default_read_buffer_len() reports the effective
window (the one-record default rather than 0 when unset), not the raw
argument.

\note This is a memory-vs-syscall trade-off. While read-ahead is enabled the
input buffer is retained (bounded to \p len) for the connection's lifetime,
so a large \p len multiplied by many concurrent connections is persistent
memory, while a small \p len bounds per-connection footprint at the cost of
more syscalls for records that exceed it.

\return SSL_SUCCESS If the buffer length was set.
\return SSL_FAILURE If ctx is NULL.

\param ctx WOLFSSL_CTX structure to set the read-ahead buffer length on.
\param len read-ahead coalescing buffer size in bytes (0 = one record).

_Example_
\code
WOLFSSL_CTX* ctx;
// setup ctx
wolfSSL_CTX_set_read_ahead(ctx, 1);
// coalesce up to four max-size records per recv()
wolfSSL_CTX_set_default_read_buffer_len(ctx, 4 * 16384);
\endcode

\sa wolfSSL_CTX_set_read_ahead
\sa wolfSSL_set_default_read_buffer_len
\sa wolfSSL_has_pending
*/
int wolfSSL_CTX_set_default_read_buffer_len(WOLFSSL_CTX* ctx, size_t len);

/*!
\ingroup Setup

\brief This function sets the read-ahead coalescing buffer size on a single
WOLFSSL session, overriding the value inherited from its WOLFSSL_CTX. See
wolfSSL_CTX_set_default_read_buffer_len() for the full description, the
one-record default, and the memory-vs-syscall trade-off.

\return SSL_SUCCESS If the buffer length was set.
\return SSL_FAILURE If ssl is NULL.

\param ssl WOLFSSL structure to set the read-ahead buffer length on.
\param len read-ahead coalescing buffer size in bytes (0 = one record).

\sa wolfSSL_CTX_set_default_read_buffer_len
\sa wolfSSL_set_read_ahead
\sa wolfSSL_has_pending
*/
int wolfSSL_set_default_read_buffer_len(WOLFSSL* ssl, size_t len);

/*!
\ingroup Setup

\brief This function returns the read-ahead coalescing buffer size
configured on a WOLFSSL_CTX by wolfSSL_CTX_set_default_read_buffer_len().
Because a length of 0 and oversized values are normalised when set, the
value reported is the effective window actually in use (the one-record
default rather than 0 when the length was never changed), not the raw
argument last passed.

\return len On success returns the read-ahead buffer length in bytes.
\return SSL_FAILURE If ctx is NULL.

\param ctx WOLFSSL_CTX structure to get the read-ahead buffer length from.

_Example_
\code
WOLFSSL_CTX* ctx;
long len;
// setup ctx
len = wolfSSL_CTX_get_default_read_buffer_len(ctx);
// check len
\endcode

\sa wolfSSL_CTX_set_default_read_buffer_len
\sa wolfSSL_get_default_read_buffer_len
\sa wolfSSL_CTX_set_read_ahead
*/
long wolfSSL_CTX_get_default_read_buffer_len(WOLFSSL_CTX* ctx);

/*!
\ingroup Setup

\brief This function returns the read-ahead coalescing buffer size in
effect for a single WOLFSSL session, whether inherited from its
WOLFSSL_CTX or overridden by wolfSSL_set_default_read_buffer_len(). As with
the WOLFSSL_CTX getter, the value reported is the effective window in use,
not the raw argument last passed.

\return len On success returns the read-ahead buffer length in bytes.
\return SSL_FAILURE If ssl is NULL.

\param ssl WOLFSSL structure to get the read-ahead buffer length from.

_Example_
\code
WOLFSSL* ssl;
long len;
// setup ssl
len = wolfSSL_get_default_read_buffer_len(ssl);
// check len
\endcode

\sa wolfSSL_set_default_read_buffer_len
\sa wolfSSL_CTX_get_default_read_buffer_len
\sa wolfSSL_set_read_ahead
*/
long wolfSSL_get_default_read_buffer_len(const WOLFSSL* ssl);

/*!
\ingroup Setup

Expand Down
14 changes: 14 additions & 0 deletions examples/benchmark/tls_bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,13 @@ static int bench_tls_client(info_t* info)
#endif
wolfSSL_SetIOReadCtx(cli_ssl, info);
wolfSSL_SetIOWriteCtx(cli_ssl, info);
#if defined(WOLFSSL_TLS_READ_AHEAD) && !defined(NO_FILESYSTEM) && \
!defined(NO_STDIO_FILESYSTEM)
/* Optional A/B benchmark toggle for TLS receive read-ahead. Gated on
* filesystem support since XGETENV is only defined there. */
if (XGETENV("WOLF_BENCH_READ_AHEAD") != NULL)
wolfSSL_set_read_ahead(cli_ssl, 1);
#endif

#if !defined(SINGLE_THREADED) && defined(WOLFSSL_DTLS)
/* synchronize with server */
Expand Down Expand Up @@ -1557,6 +1564,13 @@ static int bench_tls_server(info_t* info)

wolfSSL_SetIOReadCtx(srv_ssl, info);
wolfSSL_SetIOWriteCtx(srv_ssl, info);
#if defined(WOLFSSL_TLS_READ_AHEAD) && !defined(NO_FILESYSTEM) && \
!defined(NO_STDIO_FILESYSTEM)
/* Optional A/B benchmark toggle for TLS receive read-ahead. Gated on
* filesystem support since XGETENV is only defined there. */
if (XGETENV("WOLF_BENCH_READ_AHEAD") != NULL)
wolfSSL_set_read_ahead(srv_ssl, 1);
#endif
#ifndef NO_DH
wolfSSL_SetTmpDH(srv_ssl, dhp, sizeof(dhp), dhg, sizeof(dhg));
#endif
Expand Down
9 changes: 9 additions & 0 deletions examples/client/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,15 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port,
if (ssl == NULL)
err_sys("unable to get SSL object");

#if defined(WOLFSSL_TLS_READ_AHEAD) && !defined(NO_FILESYSTEM) && \
!defined(NO_STDIO_FILESYSTEM)
/* Optional A/B toggle: enable TLS receive read-ahead for the throughput
* benchmark when WOLF_BENCH_READ_AHEAD is set in the environment. Gated on
* filesystem support since XGETENV is only defined there. */
if (XGETENV("WOLF_BENCH_READ_AHEAD") != NULL)
wolfSSL_set_read_ahead(ssl, 1);
#endif

tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl);
if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) {
err_sys("error in setting fd");
Expand Down
Loading
Loading