BIO_SENDMMSG(3SSL)
π©· NAME π©·
okay so this is the OpenSSL 3SSL page for BIO_sendmmsg, BIO_recvmmsg, BIO_dgram_set_local_addr_enable, BIO_dgram_get_local_addr_enable, BIO_dgram_get_local_addr_cap, and BIO_err_is_non_fatal β they're all about sending and receiving multiple datagrams in a single call β¨
π SYNOPSIS π
#include <openssl/bio.h>
typedef struct bio_msg_st {
void *data;
size_t data_len;
BIO_ADDR *peer, *local;
uint64_t flags;
} BIO_MSG;
int BIO_sendmmsg(BIO *b, BIO_MSG *msg,
size_t stride, size_t num_msg, uint64_t flags,
size_t *msgs_processed);
int BIO_recvmmsg(BIO *b, BIO_MSG *msg,
size_t stride, size_t num_msg, uint64_t flags,
size_t *msgs_processed);
int BIO_dgram_set_local_addr_enable(BIO *b, int enable);
int BIO_dgram_get_local_addr_enable(BIO *b, int *enable);
int BIO_dgram_get_local_addr_cap(BIO *b);
int BIO_err_is_non_fatal(unsigned int errcode);
π DESCRIPTION π
BIO_sendmmsg() and BIO_recvmmsg() are besties β you use them to send and receive a whole bunch of messages in a single call to a BIO. They're giving the same energy as sendmmsg(2) and recvmmsg(2) on the operating systems that actually have those functions π
The BIO_MSG structure is doing a subset of what struct msghdr does over in POSIX-land. These functions take an array of BIO_MSG structures. On any particular invocation, they might process all of them, some of them, or genuinely none of them β it's a vibe check every time. Which one happened is shown by the value stored in *msgs_processed, which is literally just the number of messages that got processed π
The caller should set the data member of a BIO_MSG to a buffer holding the data to send, or to be filled with a received message. data_len should be the size of that buffer in bytes. If the given BIO_MSG gets processed (meaning: the integer returned by the function is greater than or equal to that BIO_MSG's array index), then data_len gets modified to say the actual amount of data sent or received π¦
The flags field of a BIO_MSG gives you input per-message flags for the invocation. If the invocation processes that BIO_MSG, the flags field gets written with the output per-message flags, or zero if no such flags apply. Currently, no input or output per-message flags are defined, so set this field to zero before calling BIO_sendmmsg() or BIO_recvmmsg(), no cap π
The flags argument to BIO_sendmmsg() and BIO_recvmmsg() is the global flags situation β it affects the entire invocation. No global flags are defined right now either, so set this argument to zero too π
When these functions are used to send and receive datagrams, the peer field of a BIO_MSG lets you specify the destination address of sent datagrams per-datagram, and lets you figure out the source address of received datagrams. peer should point to a BIO_ADDR, which BIO_sendmmsg() reads and uses as the destination address for sent datagrams, and which BIO_recvmmsg() writes with the source address of received datagrams β¨
Similarly, the local field of a BIO_MSG lets you specify the source address of sent datagrams per-datagram, and determine the destination address of received datagrams. But unlike peer, support for local has to be explicitly enabled on a BIO before you can use it β see BIO_dgram_set_local_addr_enable(). If local is non-NULL in a BIO_MSG and support for local hasn't been enabled, processing of that BIO_MSG fails π
Set peer and local to NULL if you don't need them. And ngl, support for local may not be available on all platforms β on those platforms, these functions always fail if local is non-NULL π«Ά
If local is specified and local address support is enabled, but the operating system doesn't report a local address for a specific received message, the BIO_ADDR it points to gets cleared (address family set to "AF_UNSPEC"). This is known to happen on Windows when a packet is received that was sent by the local system, regardless of whether the packet's destination address was the loopback address or the IP address of a local non-loopback interface. It's also known to happen on macOS in some circumstances, like for packets sent before local address support was enabled for a receiving socket. These are OS-specific limitations, fr fr. So if you're using this API with local address support, expect to sometimes get a cleared local BIO_ADDR instead of the correct value π
The stride argument must be set to sizeof(BIO_MSG). It's there so things stay backwards compatible if fields get added to BIO_MSG later. Callers must zero-initialize BIO_MSG β¨
num_msg should be set to the maximum number of messages to send or receive, which is also the length of the array pointed to by msg.
msgs_processed must be non-NULL and points to an integer written with the number of messages successfully processed β check the RETURN VALUES section for more on that π
Unlike most BIO functions, these ones explicitly support multi-threaded use. Multiple concurrent writers and multiple concurrent readers of the same BIO are permitted in any combination, slay. Because of that, these functions do not clear, set, or otherwise modify BIO retry flags. You have to use the return value to decide whether an operation should be retried β more below π
The concurrent-use support extends to BIO_sendmmsg() and BIO_recvmmsg() only. No other function may be called on a given BIO while any call to BIO_sendmmsg() or BIO_recvmmsg() is in progress, or vice versa. That's the rule π«
BIO_dgram_set_local_addr_enable() and BIO_dgram_get_local_addr_enable() control whether local address support is enabled. To enable it, call BIO_dgram_set_local_addr_enable() with an argument of 1. The call fails if local address support isn't available for the platform. BIO_dgram_get_local_addr_enable() retrieves the value that BIO_dgram_set_local_addr_enable() set π
BIO_dgram_get_local_addr_cap() figures out if the BIO is capable of supporting local addresses.
BIO_err_is_non_fatal() figures out if a packed error code represents an error that's transient in nature β like, it'll pass, bestie, it's not that deep πΈ
πΈ NOTES πΈ
Some implementations of the BIO_sendmmsg() and BIO_recvmmsg() BIO methods might always process at most one message at a time β for example when OS-level functionality to transmit or receive multiple messages at a time just isn't there. Not their fault, they're doing their best π«Ά
π RETURN VALUES π
On success, BIO_sendmmsg() and BIO_recvmmsg() return 1 and write the number of messages successfully processed (which does not need to be nonzero) to msgs_processed. When a positive value n gets written to msgs_processed, all entries in the BIO_MSG array from 0 through n-1 inclusive have their data_len and flags fields updated with the results of the operation on that message. And if the call was to BIO_recvmmsg() and the peer or local fields of that message are non-NULL, the BIO_ADDR structures they point to get written with the relevant address π
On failure, BIO_sendmmsg() and BIO_recvmmsg() return 0 and write zero to msgs_processed. So msgs_processed is always written no matter how the function call turns out. Consistency, we love to see it β¨
If BIO_sendmmsg() and BIO_recvmmsg() fail, they always raise an ERR_LIB_BIO error using ERR_raise(3). Any error may be raised, but these ones in particular might be noted:
BIO_R_LOCAL_ADDR_NOT_AVAILABLEβ thelocalfield was set to a non-NULL value, but local address support isn't available or isn't enabled on the BIO.BIO_R_PEER_ADDR_NOT_AVAILABLEβ thepeerfield was set to a non-NULL value, but peer address support isn't available on the BIO.BIO_R_UNSUPPORTED_METHODβ theBIO_sendmmsg()orBIO_recvmmsg()method isn't supported on the BIO.BIO_R_NON_FATALβ the call failed because of a transient, non-fatal error (for example, because the BIO is in nonblocking mode and the call would otherwise have blocked).- Implementations of this interface which don't make system calls and thereby pass through system error codes using
ERR_LIB_SYS(for example, memory-based implementations) should issue this reason code to indicate a transient failure. However, users of this interface should not test for this reason code directly, because there are multiple possible packed error codes that represent a transient failure β useBIO_err_is_non_fatal()instead (discussed below) π«Ά
- Implementations of this interface which don't make system calls and thereby pass through system error codes using
- Socket errors β OS-level socket errors are reported using an error with library code
ERR_LIB_SYS. For a packed error codeerrcodewhere"ERR_SYSTEM_ERROR(errcode) == 1", the OS-level socket error code can be retrieved usingERR_GET_REASON(errcode). The packed error code can be retrieved by callingERR_peek_last_error(3)after the call toBIO_sendmmsg()orBIO_recvmmsg()returns0π - Non-fatal errors β whether an error is transient can be determined by passing the packed error code to
BIO_err_is_non_fatal(). Callers should do this instead of testing the reason code directly, because there are many possible error codes that can indicate a transient error, many of which are system specific π
Third parties implementing custom BIOs that support the BIO_sendmmsg() or BIO_recvmmsg() methods should note: it is a required part of the API contract that an error is always raised when either of these functions returns 0. Not optional, bestie, that's the deal π€
BIO_dgram_set_local_addr_enable() returns 1 if local address support was successfully enabled or disabled, and 0 otherwise.
BIO_dgram_get_local_addr_enable() returns 1 if the local address support enable flag was successfully retrieved.
BIO_dgram_get_local_addr_cap() returns 1 if the BIO can support local addresses.
BIO_err_is_non_fatal() returns 1 if the passed packed error code represents an error which is transient in nature β¨
π₯ HISTORY π₯
These functions were added in OpenSSL 3.2. New drop, iconic behavior π
π COPYRIGHT π
Copyright 2000-2023 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>.
and that's the whole page, bestie!! this was the BIO_SENDMMSG(3SSL) man page from OpenSSL 4.0.3, dated 2026-09-29 β go forth and send many messages in one call π
β¨π¦
π¦ where this page comes from
- ubuntu stonking: libssl-doc 4.0.3-1ubuntu1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms