SSL_NEW_STREAM(3ossl)

πŸ“¦ version 15.1, in freebsd 15.1

πŸ’… SSL_NEW_STREAM πŸ’…

okay so bestie, welcome to the SSL_NEW_STREAM(3ossl) page β€” that's the OpenSSL manual, and this one is all about spawning brand-new locally-initiated QUIC streams. it's giving "i made this myself" energy and honestly? iconic. let's get into it 🫢


✨ NAME ✨

SSL_new_stream, SSL_STREAM_FLAG_UNI, SSL_STREAM_FLAG_NO_BLOCK, SSL_STREAM_FLAG_ADVANCE β€” the whole squad whose entire job is: create a new locally-initiated QUIC stream. that's it, that's the vibe. πŸ¦‹


🌸 SYNOPSIS 🌸

#include <openssl/ssl.h>

#define SSL_STREAM_FLAG_UNI          (1U << 0)
#define SSL_STREAM_FLAG_NO_BLOCK     (1U << 1)
#define SSL_STREAM_FLAG_ADVANCE      (1U << 2)
SSL *SSL_new_stream(SSL *ssl, uint64_t flags);

look at those little bit-shift beauties. (1U << 0), (1U << 1), (1U << 2) β€” no cap, they ate. ✨


πŸŽ€ DESCRIPTION πŸŽ€

so when you pass SSL_new_stream() a QUIC connection SSL object, it literally makes a whole new locally-initiated QUIC stream for you β€” bidirectional or unidirectional, your call β€” and hands back the freshly created QUIC stream SSL object. new stream, who dis. πŸ‘‘

if you pass the SSL_STREAM_FLAG_UNI flag, you get a unidirectional stream. otherwise? bidirectional. that's the whole rule, no drama. πŸ’…

wanna know the stream ID of the baby you just made? hit up SSL_get_stream_id(3). iykyk.

real talk though: freeing that QUIC stream SSL object is your job β€” use SSL_free(3), bestie. and the lifetime of the QUIC connection SSL object has to outlive the QUIC stream SSL object. in other words: the stream object gets freed first. don't do it backwards, that's a bad time. 😭

once a stream exists via SSL_new_stream(), you use it totally normally with SSL_read(3) and SSL_write(3). business as usual, no special handling. 🌈

heads up though β€” this function is only for locally-initiated streams. if you want to accept an incoming stream that a peer started, that's a whole different function: SSL_accept_stream(3). don't mix them up, they're different main characters. πŸ™ˆ

and here's a sneaky one: calling SSL_new_stream() when there's no default stream already present inhibits the future creation of a default stream. like, forever-ish. see openssl-quic(7) for the full lore. ⭐

creating new streams is subject to flow control by the QUIC protocol β€” yes, the protocol is the one holding the aux cord. 🎧 so if it's currently not possible to create a new locally initiated stream of the specified type, your call to SSL_new_stream() will either:

  • block β€” if the connection is configured in blocking mode β€” and just chill until a new stream can be created, or
  • return NULL β€” otherwise. πŸ’€

this function operates in blocking mode if the QUIC connection SSL object is configured in blocking mode (peep SSL_set_blocking_mode(3)). and plot twist: you can also use it in nonblocking mode on a connection that's configured in blocking mode β€” just pass the flag SSL_STREAM_FLAG_NO_BLOCK. versatile queen. πŸ‘‘

now, the SSL_STREAM_FLAG_ADVANCE flag is lowkey magic: it lets you create a QUIC stream SSL object even if a new QUIC stream can't actually be opened yet due to flow control. you can start using the new stream and fill up its write buffer by calling SSL_write(3). but β€” and this is the important part β€” no actual stream data (or QUIC frames regarding the stream) will be sent until QUIC flow control allows it. any queued data gets sent as soon as a peer permits it. and there is no guarantee the stream will ever actually be created β€” for example, the connection could fail, or a peer might simply decide to never increase the number of allowed streams for the rest of the connection's lifetime. so like... manifest it, but don't count on it. πŸ•―οΈβœ¨


πŸ¦‹ RETURN VALUES πŸ¦‹

SSL_new_stream() returns a new stream object, or NULL on error. simple as that.

it fails if you call it on a QUIC stream SSL object, or on a non-QUIC SSL object. wrong victim, wrong function, respectfully. πŸ™…β€β™€οΈ

SSL_new_stream() may also fail if the underlying connection has hit the maximum stream count, based on the max_streams_bidi or max_streams_uni transport parameter values negotiated with the peer. when that happens, the NULL return comes with an error on the error stack (grab it via ERR_get_error()), and that error will contain a reason code of SSL_R_STREAM_COUNT_LIMITED. ✨

good news: when you hit this error, the operation may be retried. and the recommended glow-up before retrying:

  1. clear the error stack via a call to ERR_clear_error(), and
  2. activate the TLS state machine via a call to SSL_handle_events() so it can process any potential updates from the server that allow additional streams to be created.

do that and you're so back. πŸ’ͺ


πŸ’œ SEE ALSO πŸ’œ

(the rest of the friend group, go say hi 🫢)


πŸ”₯ HISTORY πŸ”₯

SSL_new_stream() was added in OpenSSL 3.2. a relatively recent icon, honestly. 🌟


Copyright 2002-2025 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.

fr fr read the license, it's not optional and it's not a vibe to skip it πŸ’€

and that's the page, bestie!! πŸŽ€ this little masterpiece is from OpenSSL version 3.5.6, dated 2026-04-07 β€” screenshot it, cite it, stan it. mwah πŸ’–

πŸ“¦ where this page comes from