[bTSstream-devel] [Git][videolan/bitstream][master] SRT
Christophe Massiot (@cmassiot)
gitlab at videolan.org
Tue Feb 6 21:56:49 UTC 2024
Christophe Massiot pushed to branch master at VideoLAN / bitstream
Commits:
757e0e6b by Rafaël Carré at 2024-02-02T09:49:30+01:00
SRT
- - - - -
2 changed files:
- Makefile
- + haivision/srt.h
Changes:
=====================================
Makefile
=====================================
@@ -47,6 +47,8 @@ install: bitstream.pc
@install -m 644 smpte/*.h $(INCLUDE)/smpte
@install -d $(INCLUDE)/id3
@install -m 644 id3/*.h $(INCLUDE)/id3
+ @install -d $(INCLUDE)/haivision
+ @install -m 644 haivision/*.h $(INCLUDE)/haivision
@echo "INSTALL $(PKGCONFIG)/bitstream.pc"
@install -d $(PKGCONFIG)
@install -m 644 bitstream.pc $(PKGCONFIG)
=====================================
haivision/srt.h
=====================================
@@ -0,0 +1,968 @@
+/*****************************************************************************
+ * Haivision SRT
+ *****************************************************************************
+ * Copyright (C) 2023 Open Broadcast Systems Ltd.
+ *
+ * Authors: Kieran Kunhya <kierank at obe.tv>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+/*
+ * References:
+ * - SRT Technical Overview
+ */
+
+#ifndef __BITSTREAM_HAIVISION_SRT__
+#define __BITSTREAM_HAIVISION_SRT__
+
+#include <stdint.h> /* uint8_t, uint16_t, etc... */
+#include <stdbool.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define SRT_MAGIC_CODE 0x4a17
+
+#define SRT_HEADER_SIZE 16
+
+/*
+
+ SRT Data Packet
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |0| Packet Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |P P|O|K K|R| Message Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Destination Socket ID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + Data +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+*/
+
+#define SRT_DATA_POSITION_MIDDLE 0x0
+#define SRT_DATA_POSITION_LAST 0x1
+#define SRT_DATA_POSITION_FIRST 0x2
+#define SRT_DATA_POSITION_ONLY 0x3
+
+#define SRT_DATA_ENCRYPTION_CLEAR 0x0
+#define SRT_DATA_ENCRYPTION_EVEN 0x1
+#define SRT_DATA_ENCRYPTION_ODD 0x2
+#define SRT_DATA_ENCRYPTION_CONTROL 0x3
+
+/*
+ SRT Control Packet
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |1| Control Type | Subtype |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type-specific Information |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Destination Socket ID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+- CIF -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + Control Information Field +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+*/
+
+#define SRT_CONTROL_TYPE_HANDSHAKE 0x0
+#define SRT_CONTROL_TYPE_KEEPALIVE 0x1
+#define SRT_CONTROL_TYPE_ACK 0x2
+#define SRT_CONTROL_TYPE_NAK 0x3
+#define SRT_CONTROL_TYPE_SHUTDOWN 0x5
+#define SRT_CONTROL_TYPE_ACKACK 0x6
+#define SRT_CONTROL_TYPE_DROPREQ 0x7
+#define SRT_CONTROL_TYPE_PEERERROR 0x8
+#define SRT_CONTROL_TYPE_USER 0x7fff
+
+static inline void srt_set_packet_control(uint8_t *buf, bool control)
+{
+ buf[0] = !!control << 7;
+}
+
+static inline bool srt_get_packet_control(const uint8_t *buf)
+{
+ return !!(buf[0] & (1 << 7));
+}
+
+static inline void srt_set_data_packet_seq(uint8_t *buf, uint32_t seq)
+{
+ buf[0] |= (seq >> 24) & 0x7f;
+ buf[1] = (seq >> 16) & 0xff;
+ buf[2] = (seq >> 8) & 0xff;
+ buf[3] = seq & 0xff;
+}
+
+static inline uint32_t srt_get_data_packet_seq(const uint8_t *buf)
+{
+ return ((buf[0] & 0x7f) << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+}
+
+static inline void srt_set_data_packet_position(uint8_t *buf, uint8_t position)
+{
+ buf[4] = (buf[4] & 0x3f) | ((position & 0x3) << 6);
+}
+
+static inline uint8_t srt_get_data_packet_position(const uint8_t *buf)
+{
+ return (buf[4] >> 6) & 0x3;
+}
+
+static inline void srt_set_data_packet_order(uint8_t *buf, bool order)
+{
+ buf[4] = (buf[4] & 0xdf) | (!!order << 5);
+}
+
+static inline bool srt_get_data_packet_order(const uint8_t *buf)
+{
+ return !!(buf[4] & 0x20);
+}
+
+static inline void srt_set_data_packet_encryption(uint8_t *buf, uint8_t encryption)
+{
+ buf[4] = (buf[4] & 0xe7) | ((encryption & 0x3) << 3);
+}
+
+static inline uint8_t srt_get_data_packet_encryption(const uint8_t *buf)
+{
+ return (buf[4] >> 3) & 0x3;
+}
+
+static inline void srt_set_data_packet_retransmit(uint8_t *buf, bool retransmit)
+{
+ buf[4] = (buf[4] & 0xfb) | (!!retransmit << 2);
+}
+
+static inline bool srt_get_data_packet_retransmit(const uint8_t *buf)
+{
+ return !!(buf[4] & 0x4);
+}
+
+static inline void srt_set_data_packet_message_number(uint8_t *buf, uint32_t message_number)
+{
+ buf[4] |= (message_number >> 24) & 0x3;
+ buf[5] = (message_number >> 16) & 0xff;
+ buf[6] = (message_number >> 8) & 0xff;
+ buf[7] = message_number & 0xff;
+}
+
+static inline uint32_t srt_get_data_packet_message_number(const uint8_t *buf)
+{
+ return ((buf[4] & 0x3) << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
+}
+
+static inline void srt_set_packet_timestamp(uint8_t *buf, uint32_t timestamp)
+{
+ buf[ 8] = (timestamp >> 24) & 0xff;
+ buf[ 9] = (timestamp >> 16) & 0xff;
+ buf[10] = (timestamp >> 8) & 0xff;
+ buf[11] = timestamp & 0xff;
+}
+
+static inline uint32_t srt_get_packet_timestamp(const uint8_t *buf)
+{
+ return (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
+}
+
+static inline void srt_set_packet_dst_socket_id(uint8_t *buf, uint32_t dst_socket_id)
+{
+ buf[12] = (dst_socket_id >> 24) & 0xff;
+ buf[13] = (dst_socket_id >> 16) & 0xff;
+ buf[14] = (dst_socket_id >> 8) & 0xff;
+ buf[15] = dst_socket_id & 0xff;
+}
+
+static inline uint32_t srt_get_packet_dst_socket_id(const uint8_t *buf)
+{
+ return (buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | buf[15];
+}
+
+static inline void srt_set_control_packet_type(uint8_t *buf, uint16_t type)
+{
+ type &= ~(1 << 15);
+ buf[0] |= type >> 8;
+ buf[1] = type & 0xff;
+}
+
+static inline uint16_t srt_get_control_packet_type(const uint8_t *buf)
+{
+ return ((buf[0] & 0x7f) << 8) | buf[1];
+}
+
+static inline void srt_set_control_packet_subtype(uint8_t *buf, uint16_t subtype)
+{
+ buf[2] = subtype >> 8;
+ buf[3] = subtype & 0xff;
+}
+
+static inline uint16_t srt_get_control_packet_subtype(const uint8_t *buf)
+{
+ return (buf[2] << 8) | buf[3];
+}
+
+static inline void srt_set_control_packet_type_specific(uint8_t *buf, uint32_t type_specific)
+{
+ buf[4] = (type_specific >> 24) & 0xff;
+ buf[5] = (type_specific >> 16) & 0xff;
+ buf[6] = (type_specific >> 8) & 0xff;
+ buf[7] = type_specific & 0xff;
+}
+
+static inline uint32_t srt_get_control_packet_type_specific(const uint8_t *buf)
+{
+ return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
+}
+
+static inline const uint8_t *srt_get_control_packet_cif(const uint8_t *buf)
+{
+ return &buf[SRT_HEADER_SIZE];
+}
+
+/*
+ SRT Handshake Control Information Field
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Encryption Field | Extension Field |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Initial Packet Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Maximum Transmission Unit Size |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Maximum Flow Window Size |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Handshake Type |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | SRT Socket ID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | SYN Cookie |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Peer IP Address +
+ | |
+ + +
+ | |
+ +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ | Extension Type | Extension Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + Extension Contents +
+ | |
+ +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+
+*/
+
+#define SRT_HANDSHAKE_VERSION_MIN 4
+#define SRT_HANDSHAKE_VERSION 5
+
+#define SRT_HANDSHAKE_CIF_SIZE 48
+#define SRT_HANDSHAKE_CIF_EXTENSION_MIN_SIZE 4
+
+#define SRT_HANDSHAKE_CIPHER_NONE 0
+#define SRT_HANDSHAKE_CIPHER_AES_128 2
+#define SRT_HANDSHAKE_CIPHER_AES_192 3
+#define SRT_HANDSHAKE_CIPHER_AES_256 4
+
+#define SRT_HANDSHAKE_TYPE_DONE 0xFFFFFFFD
+#define SRT_HANDSHAKE_TYPE_AGREEMENT 0xFFFFFFFE
+#define SRT_HANDSHAKE_TYPE_CONCLUSION 0xFFFFFFFF
+#define SRT_HANDSHAKE_TYPE_WAVEHAND 0
+#define SRT_HANDSHAKE_TYPE_INDUCTION 1
+#define SRT_HANDSHAKE_TYPE_REJ_UNKNOWN 1000
+#define SRT_HANDSHAKE_TYPE_REJ_SYSTEM 1001
+#define SRT_HANDSHAKE_TYPE_REJ_PEER 1002
+#define SRT_HANDSHAKE_TYPE_REJ_RESOURCE 1003
+#define SRT_HANDSHAKE_TYPE_REJ_ROGUE 1004
+#define SRT_HANDSHAKE_TYPE_REJ_BACKLOG 1005
+#define SRT_HANDSHAKE_TYPE_REJ_IPE 1006
+#define SRT_HANDSHAKE_TYPE_REJ_CLOSE 1007
+#define SRT_HANDSHAKE_TYPE_REJ_VERSION 1008
+#define SRT_HANDSHAKE_TYPE_REJ_RDVCOOKIE 1009
+#define SRT_HANDSHAKE_TYPE_REJ_BADSECRET 1010
+#define SRT_HANDSHAKE_TYPE_REJ_UNSECURE 1011
+#define SRT_HANDSHAKE_TYPE_REJ_MESSAGEAPI 1012
+#define SRT_HANDSHAKE_TYPE_REJ_CONGESTION 1013
+#define SRT_HANDSHAKE_TYPE_REJ_FILTER 1014
+#define SRT_HANDSHAKE_TYPE_REJ_GROUP 1015
+
+static inline void srt_set_handshake_version(uint8_t *cif, uint32_t version)
+{
+ cif[0] = (version >> 24) & 0xff;
+ cif[1] = (version >> 16) & 0xff;
+ cif[2] = (version >> 8) & 0xff;
+ cif[3] = version & 0xff;
+}
+
+static inline uint32_t srt_get_handshake_version(const uint8_t *cif)
+{
+ return (cif[0] << 24) | (cif[1] << 16) | (cif[2] << 8) | cif[3];
+}
+
+static inline void srt_set_handshake_encryption(uint8_t *cif, uint16_t encryption)
+{
+ cif[4] = (encryption >> 8) & 0xff;
+ cif[5] = encryption & 0xff;
+}
+
+static inline uint16_t srt_get_handshake_encryption(const uint8_t *cif)
+{
+ return (cif[4] << 8) | cif[5];
+}
+
+static inline void srt_set_handshake_extension(uint8_t *cif, uint16_t extension)
+{
+ cif[6] = (extension >> 8) & 0xff;
+ cif[7] = extension & 0xff;
+}
+
+static inline uint16_t srt_get_handshake_extension(const uint8_t *cif)
+{
+ return (cif[6] << 8) | cif[7];
+}
+
+static inline void srt_set_handshake_isn(uint8_t *cif, uint32_t isn)
+{
+ cif[8] = (isn >> 24) & 0xff;
+ cif[9] = (isn >> 16) & 0xff;
+ cif[10] = (isn >> 8) & 0xff;
+ cif[11] = isn & 0xff;
+}
+
+static inline uint32_t srt_get_handshake_isn(const uint8_t *cif)
+{
+ return (cif[8] << 24) | (cif[9] << 16) | (cif[10] << 8) | cif[11];
+}
+
+static inline void srt_set_handshake_mtu(uint8_t *cif, uint32_t mtu)
+{
+ cif[12] = (mtu >> 24) & 0xff;
+ cif[13] = (mtu >> 16) & 0xff;
+ cif[14] = (mtu >> 8) & 0xff;
+ cif[15] = mtu & 0xff;
+}
+
+static inline uint32_t srt_get_handshake_mtu(const uint8_t *cif)
+{
+ return (cif[12] << 24) | (cif[13] << 16) | (cif[14] << 8) | cif[15];
+}
+
+static inline void srt_set_handshake_mfw(uint8_t *cif, uint32_t mfw)
+{
+ cif[16] = (mfw >> 24) & 0xff;
+ cif[17] = (mfw >> 16) & 0xff;
+ cif[18] = (mfw >> 8) & 0xff;
+ cif[19] = mfw & 0xff;
+}
+
+static inline uint32_t srt_get_handshake_mfw(const uint8_t *cif)
+{
+ return (cif[16] << 24) | (cif[17] << 16) | (cif[18] << 8) | cif[19];
+}
+
+static inline void srt_set_handshake_type(uint8_t *cif, uint32_t type)
+{
+ cif[20] = (type >> 24) & 0xff;
+ cif[21] = (type >> 16) & 0xff;
+ cif[22] = (type >> 8) & 0xff;
+ cif[23] = type & 0xff;
+}
+
+static inline uint32_t srt_get_handshake_type(const uint8_t *cif)
+{
+ return (cif[20] << 24) | (cif[21] << 16) | (cif[22] << 8) | cif[23];
+}
+
+static inline void srt_set_handshake_socket_id(uint8_t *cif, uint32_t socket_id)
+{
+ cif[24] = (socket_id >> 24) & 0xff;
+ cif[25] = (socket_id >> 16) & 0xff;
+ cif[26] = (socket_id >> 8) & 0xff;
+ cif[27] = socket_id & 0xff;
+}
+
+static inline uint32_t srt_get_handshake_socket_id(const uint8_t *cif)
+{
+ return (cif[24] << 24) | (cif[25] << 16) | (cif[26] << 8) | cif[27];
+}
+
+static inline void srt_set_handshake_syn_cookie(uint8_t *cif, uint32_t syn_cookie)
+{
+ cif[28] = (syn_cookie >> 24) & 0xff;
+ cif[29] = (syn_cookie >> 16) & 0xff;
+ cif[30] = (syn_cookie >> 8) & 0xff;
+ cif[31] = syn_cookie & 0xff;
+}
+
+static inline uint32_t srt_get_handshake_syn_cookie(const uint8_t *cif)
+{
+ return (cif[28] << 24) | (cif[29] << 16) | (cif[30] << 8) | cif[31];
+}
+
+static inline void srt_set_handshake_ip(uint8_t *cif, const struct sockaddr *addr)
+{
+ uint32_t ip;
+
+ switch (addr->sa_family) {
+ case AF_INET: {
+ const struct sockaddr_in *in = (const struct sockaddr_in *)addr;
+ memcpy(&ip, &in->sin_addr.s_addr, 4);
+ cif[32] = (ip >> 24) & 0xff;
+ cif[33] = (ip >> 16) & 0xff;
+ cif[34] = (ip >> 8) & 0xff;
+ cif[35] = ip & 0xff;
+ memset(&cif[36], 0, 12);
+ break;
+ }
+ case AF_INET6: {
+ const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *)addr;
+ for (int i = 0; i < 4; i++) {
+ memcpy(&ip, &in6->sin6_addr.s6_addr32[i], 4);
+ cif[32+4*i] = (ip >> 24) & 0xff;
+ cif[33+4*i] = (ip >> 16) & 0xff;
+ cif[34+4*i] = (ip >> 8) & 0xff;
+ cif[35+4*i] = ip & 0xff;
+ }
+ break;
+ }
+ }
+}
+
+static inline void srt_get_handshake_ip(const uint8_t *cif, struct sockaddr *addr)
+{
+ uint32_t ip0 = (cif[32] << 24) | (cif[33] << 16) | (cif[34] << 8) | (cif[35]);
+ uint32_t ip1 = (cif[36] << 24) | (cif[37] << 16) | (cif[38] << 8) | (cif[39]);
+ uint32_t ip2 = (cif[40] << 24) | (cif[41] << 16) | (cif[42] << 8) | (cif[43]);
+ uint32_t ip3 = (cif[44] << 24) | (cif[45] << 16) | (cif[46] << 8) | (cif[47]);
+
+ if (!ip1 && !ip2 && !ip3) {
+ struct sockaddr_in *in = (struct sockaddr_in *)addr;
+ in->sin_family = AF_INET;
+ memcpy(&in->sin_addr.s_addr, &ip0, 4); /* why ? */
+ } else {
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
+ in6->sin6_family = AF_INET6;
+ memcpy(&in6->sin6_addr.s6_addr32[0], &ip0, 4); /* why ? */
+ memcpy(&in6->sin6_addr.s6_addr32[1], &ip1, 4); /* why ? */
+ memcpy(&in6->sin6_addr.s6_addr32[2], &ip2, 4); /* why ? */
+ memcpy(&in6->sin6_addr.s6_addr32[3], &ip3, 4); /* why ? */
+ }
+}
+
+static inline void srt_set_handshake_extension_type(uint8_t *ext, uint16_t extension_type)
+{
+ ext[0] = (extension_type >> 8) & 0xff;
+ ext[1] = extension_type & 0xff;
+}
+
+static inline uint16_t srt_get_handshake_extension_type(const uint8_t *ext)
+{
+ return (ext[0] << 8) | ext[1];
+}
+
+static inline void srt_set_handshake_extension_len(uint8_t *ext, uint16_t extension_len)
+{
+ ext[2] = (extension_len >> 8) & 0xff;
+ ext[3] = extension_len & 0xff;
+}
+
+static inline uint16_t srt_get_handshake_extension_len(const uint8_t *ext)
+{
+ return (ext[2] << 8) | ext[3];
+}
+
+static inline uint8_t *srt_get_handshake_extension_buf(uint8_t *cif)
+{
+ return &cif[SRT_HANDSHAKE_CIF_SIZE];
+}
+
+static inline bool srt_check_handshake(const uint8_t *cif, size_t n)
+{
+ if (n < SRT_HANDSHAKE_CIF_SIZE)
+ return false;
+
+ uint32_t v = srt_get_handshake_version(cif);
+
+ if (v < SRT_HANDSHAKE_VERSION_MIN)
+ return false;
+
+ if (v > SRT_HANDSHAKE_VERSION)
+ return false;
+
+ n -= SRT_HANDSHAKE_CIF_SIZE;
+
+ uint16_t ext = srt_get_handshake_extension(cif);
+
+ if (v == SRT_HANDSHAKE_VERSION && ext && ext != SRT_MAGIC_CODE) {
+ const uint8_t *ext = srt_get_handshake_extension_buf(cif);
+ while (n) {
+ if (n < SRT_HANDSHAKE_CIF_EXTENSION_MIN_SIZE)
+ return false;
+ n -= SRT_HANDSHAKE_CIF_EXTENSION_MIN_SIZE;
+ uint16_t extension_len = 4 * srt_get_handshake_extension_len(ext);
+ if (n < extension_len)
+ return false;
+ n -= extension_len;
+ ext += SRT_HANDSHAKE_CIF_EXTENSION_MIN_SIZE + extension_len;
+ }
+ }
+
+ return true;
+}
+
+#define SRT_HANDSHAKE_EXT_HSREQ (1 << 0)
+#define SRT_HANDSHAKE_EXT_KMREQ (1 << 1)
+#define SRT_HANDSHAKE_EXT_CONFIG (1 << 2)
+
+#define SRT_HANDSHAKE_EXT_TYPE_HSREQ 1
+#define SRT_HANDSHAKE_EXT_TYPE_HSRSP 2
+#define SRT_HANDSHAKE_EXT_TYPE_KMREQ 3
+#define SRT_HANDSHAKE_EXT_TYPE_KMRSP 4
+#define SRT_HANDSHAKE_EXT_TYPE_SID 5
+#define SRT_HANDSHAKE_EXT_TYPE_CONGESTION 6
+#define SRT_HANDSHAKE_EXT_TYPE_FILTER 7
+#define SRT_HANDSHAKE_EXT_TYPE_GROUP 8
+
+/* HSREQ */
+
+#define SRT_HANDSHAKE_HSREQ_SIZE 12
+
+#define SRT_HANDSHAKE_EXT_FLAG_TSBPDSND (1<<0)
+#define SRT_HANDSHAKE_EXT_FLAG_TSBPDRCV (1<<1)
+#define SRT_HANDSHAKE_EXT_FLAG_CRYPT (1<<2)
+#define SRT_HANDSHAKE_EXT_FLAG_TLPKTDROP (1<<3)
+#define SRT_HANDSHAKE_EXT_FLAG_PERIODICNAK (1<<4)
+#define SRT_HANDSHAKE_EXT_FLAG_REXMITFLG (1<<5)
+#define SRT_HANDSHAKE_EXT_FLAG_STREAM (1<<6)
+#define SRT_HANDSHAKE_EXT_FLAG_PACKET_FILTER (1<<7)
+
+static inline void srt_set_handshake_extension_srt_version(uint8_t *ext, uint16_t major, uint8_t minor, uint8_t patch)
+{
+ uint32_t srt_version = (major << 16) | (minor << 8) | patch;
+ ext[0] = (srt_version >> 24) & 0xff;
+ ext[1] = (srt_version >> 16) & 0xff;
+ ext[2] = (srt_version >> 8) & 0xff;
+ ext[3] = srt_version & 0xff;
+}
+
+static inline void srt_get_handshake_extension_srt_version(const uint8_t *ext, uint16_t *major, uint8_t *minor, uint8_t *patch)
+{
+ uint32_t version = (ext[0] << 24) | (ext[1] << 16) | (ext[2] << 8) | ext[3];
+ *major = version >> 16;
+ *minor = (version >> 8) & 0xff;
+ *patch = version & 0xff;
+}
+
+static inline void srt_set_handshake_extension_srt_flags(uint8_t *ext, uint32_t srt_flags)
+{
+ ext[4] = (srt_flags >> 24) & 0xff;
+ ext[5] = (srt_flags >> 16) & 0xff;
+ ext[6] = (srt_flags >> 8) & 0xff;
+ ext[7] = srt_flags & 0xff;
+}
+
+static inline uint32_t srt_get_handshake_extension_srt_flags(const uint8_t *ext)
+{
+ return (ext[4] << 24) | (ext[5] << 16) | (ext[6] << 8) | ext[7];
+}
+
+static inline void srt_set_handshake_extension_receiver_tsbpd_delay(uint8_t *ext, uint16_t receiver_tsbpd_delay)
+{
+ ext[8] = (receiver_tsbpd_delay >> 8) & 0xff;
+ ext[9] = receiver_tsbpd_delay & 0xff;
+}
+
+static inline uint16_t srt_get_handshake_extension_receiver_tsbpd_delay(const uint8_t *ext)
+{
+ return (ext[8] << 8) | ext[9];
+}
+
+static inline void srt_set_handshake_extension_sender_tsbpd_delay(uint8_t *ext, uint16_t sender_tsbpd_delay)
+{
+ ext[10] = (sender_tsbpd_delay >> 8) & 0xff;
+ ext[11] = sender_tsbpd_delay & 0xff;
+}
+
+static inline uint16_t srt_get_handshake_extension_sender_tsbpd_delay(const uint8_t *ext)
+{
+ return (ext[10] << 8) | ext[11];
+}
+
+/* KMREQ */
+
+#define SRT_KMREQ_COMMON_SIZE 32
+
+#define SRT_KMREQ_CIPHER_NONE 0
+#define SRT_KMREQ_CIPHER_AES 2
+
+static inline uint8_t srt_km_get_kk(const uint8_t *km)
+{
+ return km[3] & 3;
+}
+
+static inline void srt_km_set_kk(uint8_t *km, const uint8_t kk)
+{
+ km[3] = (km[3] & ~3) | kk;
+}
+
+static inline uint8_t srt_km_get_cipher(const uint8_t *km)
+{
+ return km[8];
+}
+
+static inline void srt_km_set_cipher(uint8_t *km, const uint8_t cipher)
+{
+ km[8] = cipher;
+}
+
+static inline uint8_t srt_km_get_klen(const uint8_t *km)
+{
+ return km[15];
+}
+
+static inline void srt_km_set_klen(uint8_t *km, const uint8_t klen)
+{
+ km[15] = klen;
+}
+
+static inline uint8_t *srt_km_get_salt(const uint8_t *km)
+{
+ return &km[16];
+}
+
+static inline void srt_km_set_salt(uint8_t *km, const uint8_t *salt)
+{
+ memcpy(&km[16], salt, 128/8);
+}
+
+static inline uint8_t *srt_km_get_wrap(uint8_t *km)
+{
+ return &km[32];
+}
+
+static inline bool srt_check_km(const uint8_t *km, size_t n)
+{
+ if (n < SRT_KMREQ_COMMON_SIZE)
+ return false;
+
+ if (km[0] & (1 << 7)) // S
+ return false;
+
+ if (((km[0] >> 4) & 7) != 1) // V
+ return false;
+
+ if ((km[0] & 0xf) != 2) // PT == KMmsg
+ return false;
+
+ if ((km[1] != 0x20) || (km[2] != 0x29)) // Sign
+ return false;
+
+ if (km[3] & 0xfc) // Resv1
+ return false;
+
+ uint8_t kk = srt_km_get_kk(km);
+ if (kk == 0) // KK == 00b is invalid
+ return false;
+
+ if (km[4] || km[5] || km[6] || km[7]) // KEKI == 0
+ return false;
+
+ uint8_t cipher = srt_km_get_cipher(km);
+ if (cipher != SRT_KMREQ_CIPHER_NONE && cipher != SRT_KMREQ_CIPHER_AES)
+ return false;
+
+ if (km[9]) // Auth == 0
+ return false;
+
+ if (km[10] != 2) // SE
+ return false;
+
+ if (km[11]) // Resv2
+ return false;
+
+ if (km[12] || km[13]) // Resv3
+ return false;
+
+ if (km[14] != 4) // SLen
+ return false;
+
+ uint8_t klen = srt_km_get_klen(km);
+ if (klen != 4 && klen != 6 && klen != 8)
+ return false;
+ klen *= 4;
+
+ if (n != SRT_KMREQ_COMMON_SIZE + 8 + klen * ((kk == 3) ? 2 : 1))
+ return false;
+
+ return true;
+}
+
+/*
+ SRT ACK Control Information Field
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Last Acknowledged Packet Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | RTT |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | RTT Variance |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Available Buffer Size |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Packets Receiving Rate |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Estimated Link Capacity |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Receiving Rate |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+#define SRT_ACK_CIF_SIZE_1 16 /* last ack, rtt, rtt variance, available buffer size*/
+#define SRT_ACK_CIF_SIZE_2 24 /* packets receiving rate, estimated link capacity */
+#define SRT_ACK_CIF_SIZE_3 28 /* receiving rate */
+#define SRT_ACK_CIF_SIZE_4 32 /* 1.0.2 only, ? */
+
+static inline bool srt_check_ack(const uint8_t *cif, size_t n)
+{
+ if (n != SRT_ACK_CIF_SIZE_1 && n != SRT_ACK_CIF_SIZE_2 &&
+ n != SRT_ACK_CIF_SIZE_3 && n != SRT_ACK_CIF_SIZE_4)
+ return false;
+
+ return true;
+}
+
+static inline void srt_set_ack_last_ack_seq(uint8_t *cif, uint32_t last_ack_seq)
+{
+ cif[0] = (last_ack_seq >> 24) & 0xff;
+ cif[1] = (last_ack_seq >> 16) & 0xff;
+ cif[2] = (last_ack_seq >> 8) & 0xff;
+ cif[3] = last_ack_seq & 0xff;
+}
+
+static inline uint32_t srt_get_ack_last_ack_seq(const uint8_t *cif)
+{
+ return (cif[0] << 24) | (cif[1] << 16) | (cif[2] << 8) | cif[3];
+}
+
+static inline void srt_set_ack_rtt(uint8_t *cif, uint32_t rtt)
+{
+ cif[4] = (rtt >> 24) & 0xff;
+ cif[5] = (rtt >> 16) & 0xff;
+ cif[6] = (rtt >> 8) & 0xff;
+ cif[7] = rtt & 0xff;
+}
+
+static inline uint32_t srt_get_ack_rtt(const uint8_t *cif)
+{
+ return (cif[4] << 24) | (cif[5] << 16) | (cif[6] << 8) | cif[7];
+}
+
+static inline void srt_set_ack_rtt_variance(uint8_t *cif, uint32_t rtt_variance)
+{
+ cif[8] = (rtt_variance >> 24) & 0xff;
+ cif[9] = (rtt_variance >> 16) & 0xff;
+ cif[10] = (rtt_variance >> 8) & 0xff;
+ cif[11] = rtt_variance & 0xff;
+}
+
+static inline uint32_t srt_get_ack_rtt_variance(const uint8_t *cif)
+{
+ return (cif[8] << 24) | (cif[9] << 16) | (cif[10] << 8) | cif[11];
+}
+
+static inline void srt_set_ack_avail_bufsize(uint8_t *cif, uint32_t avail_bufsize)
+{
+ cif[12] = (avail_bufsize >> 24) & 0xff;
+ cif[13] = (avail_bufsize >> 16) & 0xff;
+ cif[14] = (avail_bufsize >> 8) & 0xff;
+ cif[15] = avail_bufsize & 0xff;
+}
+
+static inline uint32_t srt_get_ack_avail_bufsize(const uint8_t *cif)
+{
+ return (cif[12] << 24) | (cif[13] << 16) | (cif[14] << 8) | cif[15];
+}
+
+static inline void srt_set_ack_packets_receiving_rate(uint8_t *cif, uint32_t packets_receiving_rate)
+{
+ cif[16] = (packets_receiving_rate >> 24) & 0xff;
+ cif[17] = (packets_receiving_rate >> 16) & 0xff;
+ cif[18] = (packets_receiving_rate >> 8) & 0xff;
+ cif[19] = packets_receiving_rate & 0xff;
+}
+
+static inline uint32_t srt_get_ack_packets_receiving_rate(const uint8_t *cif)
+{
+ return (cif[16] << 24) | (cif[17] << 16) | (cif[18] << 8) | cif[19];
+}
+
+static inline void srt_set_ack_estimated_link_capacity(uint8_t *cif, uint32_t estimated_link_capacity)
+{
+ cif[20] = (estimated_link_capacity >> 24) & 0xff;
+ cif[21] = (estimated_link_capacity >> 16) & 0xff;
+ cif[22] = (estimated_link_capacity >> 8) & 0xff;
+ cif[23] = estimated_link_capacity & 0xff;
+}
+
+static inline uint32_t srt_get_ack_estimated_link_capacity(const uint8_t *cif)
+{
+ return (cif[20] << 24) | (cif[21] << 16) | (cif[22] << 8) | cif[23];
+}
+
+static inline void srt_set_ack_receiving_rate(uint8_t *cif, uint32_t receiving_rate)
+{
+ cif[24] = (receiving_rate >> 24) & 0xff;
+ cif[25] = (receiving_rate >> 16) & 0xff;
+ cif[26] = (receiving_rate >> 8) & 0xff;
+ cif[27] = receiving_rate & 0xff;
+}
+
+static inline uint32_t srt_get_ack_receiving_rate(const uint8_t *cif)
+{
+ return (cif[24] << 24) | (cif[25] << 16) | (cif[26] << 8) | cif[27];
+}
+
+/*
+ SRT NAK Control Information Field
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |0| Lost packet sequence number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |1| Range of lost packets from sequence number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |0| Up to sequence number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |0| Lost packet sequence number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+static inline bool srt_get_nak_range(const uint8_t **p_cif, size_t *p_cif_size, uint32_t *start_seq, uint32_t *packets)
+{
+ const uint8_t *cif = *p_cif;
+ if (*p_cif_size < 4)
+ return false;
+
+ uint32_t first_seq = (cif[0] << 24) | (cif[1] << 16) | (cif[2] << 8) | cif[3];
+ if (first_seq & (1 << 31)) {
+ if (*p_cif_size < 8)
+ return false;
+
+ first_seq &= ~(1<<31);
+
+ uint32_t last_seq = (cif[4] << 24) | (cif[5] << 16) | (cif[6] << 8) | cif[7];
+ if (last_seq & (1 << 31))
+ return false;
+
+ *p_cif_size -= 8;
+ *p_cif += 8;
+
+ *start_seq = first_seq;
+ *packets = (last_seq - first_seq + 1) & ~(1<<31);
+ } else {
+ *p_cif_size -= 4;
+ *p_cif += 4;
+ *start_seq = first_seq;
+ *packets = 1;
+ }
+
+ return true;
+}
+
+
+/*
+ SRT DROPREQ Control Information Field
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | First Packet Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Last Packet Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+#define SRT_DROPREQ_CIF_SIZE 8
+
+static inline bool srt_check_dropreq(const uint8_t *cif, size_t n)
+{
+ if (n != SRT_DROPREQ_CIF_SIZE)
+ return false;
+
+ return true;
+}
+
+static inline void srt_set_dropreq_first_seq(uint8_t *cif, uint32_t first_seq)
+{
+ cif[0] = (first_seq >> 24) & 0x7f;
+ cif[1] = (first_seq >> 16) & 0xff;
+ cif[2] = (first_seq >> 8) & 0xff;
+ cif[3] = first_seq & 0xff;
+}
+
+static inline uint32_t srt_get_dropreq_first_seq(const uint8_t *cif)
+{
+ return ((cif[0] << 24) & 0x7f) | (cif[1] << 16) | (cif[2] << 8) | cif[3];
+}
+
+static inline void srt_set_dropreq_last_seq(uint8_t *cif, uint32_t last_seq)
+{
+ cif[4] = (last_seq >> 24) & 0x7f;
+ cif[5] = (last_seq >> 16) & 0xff;
+ cif[6] = (last_seq >> 8) & 0xff;
+ cif[7] = last_seq & 0xff;
+}
+
+static inline uint32_t srt_get_dropreq_last_seq(const uint8_t *cif)
+{
+ return ((cif[4] << 24) & 0x7f) | (cif[5] << 16) | (cif[6] << 8) | cif[7];
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
View it on GitLab: https://code.videolan.org/videolan/bitstream/-/commit/757e0e6beaebe869dbf386ae0028a1d2dfef433d
--
View it on GitLab: https://code.videolan.org/videolan/bitstream/-/commit/757e0e6beaebe869dbf386ae0028a1d2dfef433d
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the biTStream-devel
mailing list