You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
UDP Transport Layer for libAES67: Socket and Stream Abstractions
Proposal ID
SE-00002
Author
Nevio Hirani
Motivation
The libAES67 project aims to provide a comprehensive software library for implementing AES67-compliant audio transport. A fundamental aspect of this compliance is the use of UDP (User Datagram Protocol) as the transport layer for real-time audio streaming and control packets. According to the AES67 standard, real-time audio transport protocol (RTP) and its control protocol (RTCP) must be carried over UDP. This requirement is consistent with the established internet standards, where UDP is defined in RFC 768, and RTP/RTCP packet formats and procedures are detailed in RFC 3550.
Currently, libAES67 lacks a dedicated, cross-platform abstraction for handling UDP sockets and streams that can efficiently manage the transmission and reception of RTP and RTCP packets. This proposal outlines a detailed plan to implement native UDP socket management and streaming helpers that handle the intricacies of multicast group membership, socket options, non-blocking I/O, and packet parsing, which are essential for robust AES67 interoperability.
Background
UDP is a connectionless and lightweight transport protocol, chosen for real-time media streaming due to its minimal overhead and low latency. Unlike TCP, UDP does not guarantee packet delivery or ordering, which suits the nature of real-time audio where timely delivery is often more critical than perfect reliability. AES67 streams utilize RTP over UDP for audio data packets, with RTCP providing monitoring and control information.
Multicast UDP is widely used in AES67 to efficiently distribute audio streams to multiple receivers without duplicating network traffic. This multicast usage requires special handling at the socket level, such as joining multicast groups, setting multicast TTL (time-to-live), enabling or disabling multicast loopback, and selecting network interfaces. These operations must adhere to standards such as RFC 1112, which define IP multicast group management and socket options.
To facilitate these operations, libAES67 must offer an abstraction that manages UDP socket lifecycle, socket options, multicast membership, and provides a clean interface for sending and receiving packets asynchronously to avoid blocking the main application threads.
Specification
Proposed Design
The core of this proposal is the introduction of a UDP socket abstraction in libAES67, tentatively named aes67_udp_socket_t. This abstraction will encapsulate the native system socket descriptor and provide methods to bind to local ports, join and leave multicast groups, and configure necessary socket options. Key socket options include SO_REUSEADDR (allowing multiple sockets to bind to the same address for multicast reception), IP_MULTICAST_IF (selecting the network interface used for outgoing multicast packets), IP_MULTICAST_TTL (limiting the hop count of multicast packets), and IP_MULTICAST_LOOP (enabling or disabling multicast loopback).
In addition to socket management, the proposal includes building streaming helpers that will integrate with the UDP socket layer. A streaming receiver component will manage an event-driven or dedicated thread to continuously listen for incoming UDP packets. Upon packet arrival, it will validate the packet structure, parse RTP or RTCP headers as defined in RFC 3550, and forward the payload to higher layers such as jitter buffers or audio decoders.
Similarly, a streaming sender component will manage timely transmission of RTP and RTCP packets. This includes correct packet timestamping, sequence numbering, and periodic sending of RTCP reports for session control and synchronization.
The implementation will emphasize non-blocking socket operations and platform independence, supporting both IPv4 initially, with an eye towards future IPv6 support added. This ensures that real-time audio processing is not hindered by network I/O delays.
Required Types and Functions
To support this specification, libAES67 should define:
UDP Socket Abstraction
aes67_udp_socket_t: Struct encapsulating the native UDP socket descriptor along with state information like multicast memberships and socket options.
UDP Socket Management Functions
aes67_udp_socket_create(): Create a new UDP socket instance.
aes67_udp_socket_destroy(): Close and clean up the UDP socket.
aes67_udp_socket_bind(address, port): Bind the UDP socket to a local IP address (IPv4 or IPv6) and port. (added IPv6 support)
aes67_udp_socket_set_nonblocking(enabled): Enable or disable non-blocking mode for the socket.
aes67_udp_socket_set_reuseaddr(enabled): Enable or disable the SO_REUSEADDR option for multicast support.
aes67_udp_socket_set_multicast_if(interface): Set the network interface for outgoing multicast packets. Accept interface indices (IPv6).
aes67_udp_socket_set_multicast_ttl(ttl): Set the multicast packet time-to-live (TTL).
aes67_udp_socket_set_multicast_loop(enabled): Enable or disable multicast loopback (IPv4).
aes67_udp_socket_set_multicast_loop_v6(enabled): Enable or disable multicast loopback for IPv6 multicast groups (IPv6).
aes67_udp_socket_join_multicast_group(group_address): Join a multicast group (IPv4).
aes67_udp_socket_join_multicast_group_v6(group_address, interface_index): Join an IPv6 multicast group with interface index (IPv6).
aes67_udp_socket_leave_multicast_group(group_address): Leave a multicast group (IPv4).
aes67_udp_socket_leave_multicast_group_v6(group_address, interface_index): Leave an IPv6 multicast group (IPv6).
aes67_udp_socket_sendto(data, length, dest_address, dest_port): Send UDP data to the specified destination (IPv4, IPv6).
aes67_udp_socket_recvfrom(buffer, max_length, source_address, source_port): Receive UDP data and obtain source address and port (IPv4, IPv6).
aes67_udp_socket_set_ipv6_only(enabled): Set socket option to accept only IPv6 packets or both IPv4-mapped IPv6 packets (dual stack) (IPv6).
aes67_udp_socket_set_tos(tos_value): Set the IP Type of Service (TOS) or Differentiated Services Code Point (DSCP) to prioritize audio traffic.
aes67_tos_t enum defines the TOS values such as AES67_TOS_DEFAULT, AES67_TOS_AUDIO, AES67_TOS_VIDEO, etc.
aes67_udp_socket_get_local_address(): Retrieve the local bound address and port of the socket.
aes67_udp_socket_set_receive_buffer_size(size): Adjust the socket’s receive buffer size to handle high-throughput streams.
aes67_udp_socket_set_send_buffer_size(size): Adjust the socket’s send buffer size for smoother streaming.
UDP Streaming Helpers
aes67_udp_stream_t: Struct managing the streaming state over UDP, including references to the associated UDP socket, buffers, and RTP/RTCP sequencing state.
UDP Streaming Functions
aes67_udp_stream_create(udp_socket): Initialize a UDP streaming context linked to a UDP socket.
aes67_udp_stream_destroy(): Clean up the streaming context.
aes67_udp_stream_start(): Start the streaming receive loop (event-driven or thread-based).
aes67_udp_stream_stop(): Stop the streaming receive loop and cleanup resources.
aes67_udp_stream_receive(): Listen for incoming RTP/RTCP packets, parse them, and forward payloads to higher layers.
aes67_udp_stream_set_timeout(timeout_ms): Configure receive or send timeout values.
aes67_udp_stream_flush(): Flush any buffered RTP or RTCP packets waiting to be sent.
aes67_udp_stream_get_stats(): Retrieve statistics such as packets received, lost, jitter, and errors
aes67_udp_stream_set_seqnum_extension(enabled): Optionally support extended sequence number handling.
aes67_udp_stream_set_ssrc_filter(ssrc): Filter incoming packets by SSRC to ignore unrelated streams.
aes67_udp_stream_send_rtp(payload, length): Assemble and send RTP packets with correct headers.
aes67_udp_stream_send_rtcp(rtcp_packet): Send RTCP control packets.
aes67_udp_stream_set_receive_callback(callback): Register a callback to handle incoming RTP/RTCP packets asynchronously.
aes67_udp_stream_set_rtp_callback(aes67_udp_stream_t* stream, aes67_rtp_received_cb callback, void* user_ctx): Sets a callback to handle incoming RTP packets on the UDP stream.
aes67_udp_stream_set_rtcp_callback(aes67_udp_stream_t* stream, aes67_rtcp_received_cb callback, void* user_ctx): Sets a callback to handle incoming RTCP packets on the UDP stream.
Streaming Callbacks
typedef void (*aes67_rtp_received_cb)(const aes67_rtp_packet_t* rtp_packet, void* user_ctx): Callback invoked on receiving an RTP packet.
typedef void (*aes67_rtcp_received_cb)(const aes67_rtcp_packet_t* rtcp_packet, void* user_ctx): Callback invoked on receiving an RTCP packet.
Buffer
aes67_udp_socket_set_receive_buffer_size(size): Configures the underlying socket’s receive buffer to the specified size in bytes. Increasing the receive buffer helps handle high data rates and reduces packet loss by buffering incoming UDP datagrams before they are processed by the application.
aes67_udp_socket_set_send_buffer_size(size): Configures the socket’s send buffer size to the specified number of bytes. A larger send buffer allows smoother transmission of RTP/RTCP packets, particularly when sending bursts or large packets, by accommodating outgoing data until the network stack can send it.
Error Handling
aes67_error_t: A type representing error codes returned by libAES67 functions.
Macros
AES67_DEFAULT_MULTICAST_TTL 64: Default TTL for multicast packets.
AES67_RTP_PORT_OFFSET 0: RTP port offset relative to base port.
AES67_RTCP_PORT_OFFSET 1: RTCP port offset relative to base port.
AES67_IS_MULTICAST_ADDR(ip): Macro to check if an IP address is in the multicast range (224.0.0.0 to 239.255.255.255 for IPv4).
AES67_IS_MULTICAST_ADDR_V6(addr) (((addr).s6_addr[0] == 0xff)): Checks whether the given IPv6 address is a multicast address. IPv6 multicast addresses always start with the byte 0xff. This macro inspects the first byte of the IPv6 address (s6_addr[0]) and returns true if it matches 0xff, indicating multicast.
AES67_DEFAULT_RECV_BUFFER_SIZE (256 * 1024): Defines the default size of the socket receive buffer, set to 256 KB (256 * 1024 bytes). A larger receive buffer helps accommodate bursts of incoming UDP packets, reducing the likelihood of packet loss in high-throughput audio streaming scenarios.
AES67_DEFAULT_SEND_BUFFER_SIZE (128 * 1024): Defines the default size of the socket send buffer, set to 128 KB (128 * 1024 bytes). This buffer size is chosen to provide smooth, continuous transmission of RTP/RTCP packets without blocking the sending application due to buffer underruns.
Affected Layer
network
Alternatives Considered
None
Impact
This proposal introduces new APIs and abstractions without modifying existing libAES67 interfaces, ensuring no backward compatibility breaks. Developers using libAES67 will gain the ability to manage UDP sockets and multicast configurations seamlessly, which is currently handled externally or manually.
Performance considerations are paramount; non-blocking I/O and event-driven design minimize CPU load and latency, both critical for live audio streaming. Handling multicast efficiently reduces unnecessary network traffic, which is important in high-density audio environments.
Comprehensive documentation will accompany these additions, detailing usage patterns, socket option configurations, multicast setup, and example workflows for sending and receiving RTP/RTCP streams. Unit and integration testing plans will cover socket lifecycle, multicast behavior, and correct RTP/RTCP packet handling.
Proposal Title
UDP Transport Layer for libAES67: Socket and Stream Abstractions
Proposal ID
SE-00002
Author
Nevio Hirani
Motivation
The libAES67 project aims to provide a comprehensive software library for implementing AES67-compliant audio transport. A fundamental aspect of this compliance is the use of UDP (User Datagram Protocol) as the transport layer for real-time audio streaming and control packets. According to the AES67 standard, real-time audio transport protocol (RTP) and its control protocol (RTCP) must be carried over UDP. This requirement is consistent with the established internet standards, where UDP is defined in RFC 768, and RTP/RTCP packet formats and procedures are detailed in RFC 3550.
Currently, libAES67 lacks a dedicated, cross-platform abstraction for handling UDP sockets and streams that can efficiently manage the transmission and reception of RTP and RTCP packets. This proposal outlines a detailed plan to implement native UDP socket management and streaming helpers that handle the intricacies of multicast group membership, socket options, non-blocking I/O, and packet parsing, which are essential for robust AES67 interoperability.
Background
UDP is a connectionless and lightweight transport protocol, chosen for real-time media streaming due to its minimal overhead and low latency. Unlike TCP, UDP does not guarantee packet delivery or ordering, which suits the nature of real-time audio where timely delivery is often more critical than perfect reliability. AES67 streams utilize RTP over UDP for audio data packets, with RTCP providing monitoring and control information.
Multicast UDP is widely used in AES67 to efficiently distribute audio streams to multiple receivers without duplicating network traffic. This multicast usage requires special handling at the socket level, such as joining multicast groups, setting multicast TTL (time-to-live), enabling or disabling multicast loopback, and selecting network interfaces. These operations must adhere to standards such as RFC 1112, which define IP multicast group management and socket options.
To facilitate these operations, libAES67 must offer an abstraction that manages UDP socket lifecycle, socket options, multicast membership, and provides a clean interface for sending and receiving packets asynchronously to avoid blocking the main application threads.
Specification
Proposed Design
The core of this proposal is the introduction of a UDP socket abstraction in libAES67, tentatively named
aes67_udp_socket_t. This abstraction will encapsulate the native system socket descriptor and provide methods to bind to local ports, join and leave multicast groups, and configure necessary socket options. Key socket options includeSO_REUSEADDR(allowing multiple sockets to bind to the same address for multicast reception), IP_MULTICAST_IF (selecting the network interface used for outgoing multicast packets),IP_MULTICAST_TTL(limiting the hop count of multicast packets), andIP_MULTICAST_LOOP(enabling or disabling multicast loopback).In addition to socket management, the proposal includes building streaming helpers that will integrate with the UDP socket layer. A streaming receiver component will manage an event-driven or dedicated thread to continuously listen for incoming UDP packets. Upon packet arrival, it will validate the packet structure, parse RTP or RTCP headers as defined in RFC 3550, and forward the payload to higher layers such as jitter buffers or audio decoders.
Similarly, a streaming sender component will manage timely transmission of RTP and RTCP packets. This includes correct packet timestamping, sequence numbering, and periodic sending of RTCP reports for session control and synchronization.
The implementation will emphasize non-blocking socket operations and platform independence, supporting both IPv4 initially, with an eye towards future IPv6 support added. This ensures that real-time audio processing is not hindered by network I/O delays.
Required Types and Functions
To support this specification, libAES67 should define:
UDP Socket Abstraction
aes67_udp_socket_t: Struct encapsulating the native UDP socket descriptor along with state information like multicast memberships and socket options.UDP Socket Management Functions
aes67_udp_socket_create(): Create a new UDP socket instance.aes67_udp_socket_destroy(): Close and clean up the UDP socket.aes67_udp_socket_bind(address, port): Bind the UDP socket to a local IP address (IPv4 or IPv6) and port. (added IPv6 support)aes67_udp_socket_set_nonblocking(enabled): Enable or disable non-blocking mode for the socket.aes67_udp_socket_set_reuseaddr(enabled): Enable or disable the SO_REUSEADDR option for multicast support.aes67_udp_socket_set_multicast_if(interface): Set the network interface for outgoing multicast packets. Accept interface indices (IPv6).aes67_udp_socket_set_multicast_ttl(ttl): Set the multicast packet time-to-live (TTL).aes67_udp_socket_set_multicast_loop(enabled): Enable or disable multicast loopback (IPv4).aes67_udp_socket_set_multicast_loop_v6(enabled): Enable or disable multicast loopback for IPv6 multicast groups (IPv6).aes67_udp_socket_join_multicast_group(group_address): Join a multicast group (IPv4).aes67_udp_socket_join_multicast_group_v6(group_address, interface_index): Join an IPv6 multicast group with interface index (IPv6).aes67_udp_socket_leave_multicast_group(group_address): Leave a multicast group (IPv4).aes67_udp_socket_leave_multicast_group_v6(group_address, interface_index): Leave an IPv6 multicast group (IPv6).aes67_udp_socket_sendto(data, length, dest_address, dest_port): Send UDP data to the specified destination (IPv4, IPv6).aes67_udp_socket_recvfrom(buffer, max_length, source_address, source_port): Receive UDP data and obtain source address and port (IPv4, IPv6).aes67_udp_socket_set_ipv6_only(enabled): Set socket option to accept only IPv6 packets or both IPv4-mapped IPv6 packets (dual stack) (IPv6).aes67_udp_socket_set_tos(tos_value): Set the IP Type of Service (TOS) or Differentiated Services Code Point (DSCP) to prioritize audio traffic.aes67_tos_tenum defines the TOS values such asAES67_TOS_DEFAULT,AES67_TOS_AUDIO,AES67_TOS_VIDEO, etc.aes67_udp_socket_get_local_address(): Retrieve the local bound address and port of the socket.aes67_udp_socket_set_receive_buffer_size(size): Adjust the socket’s receive buffer size to handle high-throughput streams.aes67_udp_socket_set_send_buffer_size(size): Adjust the socket’s send buffer size for smoother streaming.UDP Streaming Helpers
aes67_udp_stream_t: Struct managing the streaming state over UDP, including references to the associated UDP socket, buffers, and RTP/RTCP sequencing state.UDP Streaming Functions
aes67_udp_stream_create(udp_socket): Initialize a UDP streaming context linked to a UDP socket.aes67_udp_stream_destroy(): Clean up the streaming context.aes67_udp_stream_start(): Start the streaming receive loop (event-driven or thread-based).aes67_udp_stream_stop(): Stop the streaming receive loop and cleanup resources.aes67_udp_stream_receive(): Listen for incoming RTP/RTCP packets, parse them, and forward payloads to higher layers.aes67_udp_stream_set_timeout(timeout_ms): Configure receive or send timeout values.aes67_udp_stream_flush(): Flush any buffered RTP or RTCP packets waiting to be sent.aes67_udp_stream_get_stats(): Retrieve statistics such as packets received, lost, jitter, and errorsaes67_udp_stream_set_seqnum_extension(enabled): Optionally support extended sequence number handling.aes67_udp_stream_set_ssrc_filter(ssrc): Filter incoming packets by SSRC to ignore unrelated streams.aes67_udp_stream_send_rtp(payload, length): Assemble and send RTP packets with correct headers.aes67_udp_stream_send_rtcp(rtcp_packet): Send RTCP control packets.aes67_udp_stream_set_receive_callback(callback): Register a callback to handle incoming RTP/RTCP packets asynchronously.aes67_udp_stream_set_rtp_callback(aes67_udp_stream_t* stream, aes67_rtp_received_cb callback, void* user_ctx): Sets a callback to handle incoming RTP packets on the UDP stream.aes67_udp_stream_set_rtcp_callback(aes67_udp_stream_t* stream, aes67_rtcp_received_cb callback, void* user_ctx): Sets a callback to handle incoming RTCP packets on the UDP stream.Streaming Callbacks
typedef void (*aes67_rtp_received_cb)(const aes67_rtp_packet_t* rtp_packet, void* user_ctx): Callback invoked on receiving an RTP packet.typedef void (*aes67_rtcp_received_cb)(const aes67_rtcp_packet_t* rtcp_packet, void* user_ctx): Callback invoked on receiving an RTCP packet.Buffer
aes67_udp_socket_set_receive_buffer_size(size): Configures the underlying socket’s receive buffer to the specified size in bytes. Increasing the receive buffer helps handle high data rates and reduces packet loss by buffering incoming UDP datagrams before they are processed by the application.aes67_udp_socket_set_send_buffer_size(size): Configures the socket’s send buffer size to the specified number of bytes. A larger send buffer allows smoother transmission of RTP/RTCP packets, particularly when sending bursts or large packets, by accommodating outgoing data until the network stack can send it.Error Handling
aes67_error_t: A type representing error codes returned by libAES67 functions.Macros
AES67_DEFAULT_MULTICAST_TTL 64: Default TTL for multicast packets.AES67_RTP_PORT_OFFSET 0: RTP port offset relative to base port.AES67_RTCP_PORT_OFFSET 1: RTCP port offset relative to base port.AES67_IS_MULTICAST_ADDR(ip): Macro to check if an IP address is in the multicast range (224.0.0.0to239.255.255.255for IPv4).AES67_IS_MULTICAST_ADDR_V6(addr) (((addr).s6_addr[0] == 0xff)): Checks whether the given IPv6 address is a multicast address. IPv6 multicast addresses always start with the byte0xff. This macro inspects the first byte of the IPv6 address (s6_addr[0]) and returns true if it matches0xff, indicating multicast.AES67_DEFAULT_RECV_BUFFER_SIZE (256 * 1024): Defines the default size of the socket receive buffer, set to256 KB(256 * 1024 bytes). A larger receive buffer helps accommodate bursts of incoming UDP packets, reducing the likelihood of packet loss in high-throughput audio streaming scenarios.AES67_DEFAULT_SEND_BUFFER_SIZE (128 * 1024): Defines the default size of the socket send buffer, set to128 KB(128 * 1024 bytes). This buffer size is chosen to provide smooth, continuous transmission of RTP/RTCP packets without blocking the sending application due to buffer underruns.Affected Layer
network
Alternatives Considered
None
Impact
This proposal introduces new APIs and abstractions without modifying existing libAES67 interfaces, ensuring no backward compatibility breaks. Developers using libAES67 will gain the ability to manage UDP sockets and multicast configurations seamlessly, which is currently handled externally or manually.
Performance considerations are paramount; non-blocking I/O and event-driven design minimize CPU load and latency, both critical for live audio streaming. Handling multicast efficiently reduces unnecessary network traffic, which is important in high-density audio environments.
Comprehensive documentation will accompany these additions, detailing usage patterns, socket option configurations, multicast setup, and example workflows for sending and receiving RTP/RTCP streams. Unit and integration testing plans will cover socket lifecycle, multicast behavior, and correct RTP/RTCP packet handling.
References
Additional Notes
Community feedback and contributions are highly welcomed to refine and extend this foundational feature.
Is there an existing proposal for this?