25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

372 satır
15KB

  1. #ifndef ZLMEDIAKIT_SRT_PACKET_H
  2. #define ZLMEDIAKIT_SRT_PACKET_H
  3. #include <stdint.h>
  4. #include <vector>
  5. #include "Network/Buffer.h"
  6. #include "Network/sockutil.h"
  7. #include "Util/logger.h"
  8. #include "Common.hpp"
  9. #include "HSExt.hpp"
  10. namespace SRT {
  11. using namespace toolkit;
  12. static const size_t HDR_SIZE = 16; // packet header size = SRT_PH_E_SIZE * sizeof(uint32_t)
  13. // Can also be calculated as: sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct udphdr).
  14. static const size_t UDP_HDR_SIZE = 28; // 20 bytes IPv4 + 8 bytes of UDP { u16 sport, dport, len, csum }.
  15. static const size_t SRT_DATA_HDR_SIZE = UDP_HDR_SIZE + HDR_SIZE;
  16. // Maximum transmission unit size. 1500 in case of Ethernet II (RFC 1191).
  17. static const size_t ETH_MAX_MTU_SIZE = 1500;
  18. // Maximum payload size of an SRT packet.
  19. static const size_t SRT_MAX_PAYLOAD_SIZE = ETH_MAX_MTU_SIZE - SRT_DATA_HDR_SIZE;
  20. /*
  21. 0 1 2 3
  22. 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
  23. +-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+
  24. |0| Packet Sequence Number |
  25. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  26. |P P|O|K K|R| Message Number |
  27. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  28. | Timestamp |
  29. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  30. | Destination Socket ID |
  31. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  32. | |
  33. + Data +
  34. | |
  35. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  36. Figure 3: Data packet structure
  37. reference https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-packet-structure
  38. */
  39. class DataPacket : public Buffer {
  40. public:
  41. using Ptr = std::shared_ptr<DataPacket>;
  42. DataPacket() = default;
  43. ~DataPacket() = default;
  44. static const size_t HEADER_SIZE = 16;
  45. static bool isDataPacket(uint8_t *buf, size_t len);
  46. static uint32_t getSocketID(uint8_t *buf, size_t len);
  47. bool loadFromData(uint8_t *buf, size_t len);
  48. bool storeToData(uint8_t *buf, size_t len);
  49. bool storeToHeader();
  50. ///////Buffer override///////
  51. char *data() const override;
  52. size_t size() const override;
  53. char *payloadData();
  54. size_t payloadSize();
  55. uint8_t f;
  56. uint32_t packet_seq_number;
  57. uint8_t PP;
  58. uint8_t O;
  59. uint8_t KK;
  60. uint8_t R;
  61. uint32_t msg_number;
  62. uint32_t timestamp;
  63. uint32_t dst_socket_id;
  64. private:
  65. BufferRaw::Ptr _data;
  66. };
  67. /*
  68. 0 1 2 3
  69. 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
  70. +-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+
  71. |1| Control Type | Subtype |
  72. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  73. | Type-specific Information |
  74. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  75. | Timestamp |
  76. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  77. | Destination Socket ID |
  78. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+- CIF -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  79. | |
  80. + Control Information Field +
  81. | |
  82. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  83. Figure 4: Control packet structure
  84. reference https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-control-packets
  85. */
  86. class ControlPacket : public Buffer {
  87. public:
  88. using Ptr = std::shared_ptr<ControlPacket>;
  89. static const size_t HEADER_SIZE = 16;
  90. static bool isControlPacket(uint8_t *buf, size_t len);
  91. static uint16_t getControlType(uint8_t *buf, size_t len);
  92. static uint32_t getSocketID(uint8_t *buf, size_t len);
  93. ControlPacket() = default;
  94. virtual ~ControlPacket() = default;
  95. virtual bool loadFromData(uint8_t *buf, size_t len) = 0;
  96. virtual bool storeToData() = 0;
  97. bool loadHeader();
  98. bool storeToHeader();
  99. ///////Buffer override///////
  100. char *data() const override;
  101. size_t size() const override;
  102. enum {
  103. HANDSHAKE = 0x0000,
  104. KEEPALIVE = 0x0001,
  105. ACK = 0x0002,
  106. NAK = 0x0003,
  107. CONGESTIONWARNING = 0x0004,
  108. SHUTDOWN = 0x0005,
  109. ACKACK = 0x0006,
  110. DROPREQ = 0x0007,
  111. PEERERROR = 0x0008,
  112. USERDEFINEDTYPE = 0x7FFF
  113. };
  114. uint16_t sub_type;
  115. uint16_t control_type;
  116. uint8_t f;
  117. uint8_t type_specific_info[4];
  118. uint32_t timestamp;
  119. uint32_t dst_socket_id;
  120. protected:
  121. BufferRaw::Ptr _data;
  122. };
  123. /**
  124. 0 1 2 3
  125. 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
  126. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  127. | Version |
  128. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  129. | Encryption Field | Extension Field |
  130. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  131. | Initial Packet Sequence Number |
  132. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  133. | Maximum Transmission Unit Size |
  134. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  135. | Maximum Flow Window Size |
  136. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  137. | Handshake Type |
  138. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  139. | SRT Socket ID |
  140. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  141. | SYN Cookie |
  142. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  143. | |
  144. + +
  145. | |
  146. + Peer IP Address +
  147. | |
  148. + +
  149. | |
  150. +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  151. | Extension Type | Extension Length |
  152. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  153. | |
  154. + Extension Contents +
  155. | |
  156. +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  157. Figure 5: Handshake packet structure
  158. https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-handshake
  159. */
  160. class HandshakePacket : public ControlPacket {
  161. public:
  162. using Ptr = std::shared_ptr<HandshakePacket>;
  163. enum { NO_ENCRYPTION = 0, AES_128 = 1, AES_196 = 2, AES_256 = 3 };
  164. static const size_t HS_CONTENT_MIN_SIZE = 48;
  165. enum {
  166. HS_TYPE_DONE = 0xFFFFFFFD,
  167. HS_TYPE_AGREEMENT = 0xFFFFFFFE,
  168. HS_TYPE_CONCLUSION = 0xFFFFFFFF,
  169. HS_TYPE_WAVEHAND = 0x00000000,
  170. HS_TYPE_INDUCTION = 0x00000001
  171. };
  172. enum { HS_EXT_FILED_HSREQ = 0x00000001, HS_EXT_FILED_KMREQ = 0x00000002, HS_EXT_FILED_CONFIG = 0x00000004 };
  173. HandshakePacket() = default;
  174. ~HandshakePacket() = default;
  175. static bool isHandshakePacket(uint8_t *buf, size_t len);
  176. static uint32_t getHandshakeType(uint8_t *buf, size_t len);
  177. static uint32_t getSynCookie(uint8_t *buf, size_t len);
  178. static uint32_t
  179. generateSynCookie(struct sockaddr_storage *addr, TimePoint ts, uint32_t current_cookie = 0, int correction = 0);
  180. std::string dump();
  181. void assignPeerIP(struct sockaddr_storage *addr);
  182. ///////ControlPacket override///////
  183. bool loadFromData(uint8_t *buf, size_t len) override;
  184. bool storeToData() override;
  185. uint32_t version;
  186. uint16_t encryption_field;
  187. uint16_t extension_field;
  188. uint32_t initial_packet_sequence_number;
  189. uint32_t mtu;
  190. uint32_t max_flow_window_size;
  191. uint32_t handshake_type;
  192. uint32_t srt_socket_id;
  193. uint32_t syn_cookie;
  194. uint8_t peer_ip_addr[16];
  195. std::vector<HSExt::Ptr> ext_list;
  196. private:
  197. bool loadExtMessage(uint8_t *buf, size_t len);
  198. bool storeExtMessage();
  199. size_t getExtSize();
  200. };
  201. /*
  202. 0 1 2 3
  203. 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
  204. +-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+
  205. |1| Control Type | Reserved |
  206. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  207. | Type-specific Information |
  208. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  209. | Timestamp |
  210. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  211. | Destination Socket ID |
  212. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  213. Figure 12: Keep-Alive control packet
  214. https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-keep-alive
  215. */
  216. class KeepLivePacket : public ControlPacket {
  217. public:
  218. using Ptr = std::shared_ptr<KeepLivePacket>;
  219. KeepLivePacket() = default;
  220. ~KeepLivePacket() = default;
  221. ///////ControlPacket override///////
  222. bool loadFromData(uint8_t *buf, size_t len) override;
  223. bool storeToData() override;
  224. };
  225. /*
  226. An SRT NAK packet is formatted as follows:
  227. 0 1 2 3
  228. 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
  229. +-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+
  230. |1| Control Type | Reserved |
  231. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  232. | Type-specific Information |
  233. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  234. | Timestamp |
  235. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  236. | Destination Socket ID |
  237. +-+-+-+-+-+-+-+-+-+-+-+- CIF (Loss List) -+-+-+-+-+-+-+-+-+-+-+-+
  238. |0| Lost packet sequence number |
  239. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  240. |1| Range of lost packets from sequence number |
  241. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  242. |0| Up to sequence number |
  243. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  244. |0| Lost packet sequence number |
  245. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  246. Figure 14: NAK control packet
  247. https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-nak-control-packet
  248. */
  249. class NAKPacket : public ControlPacket {
  250. public:
  251. using Ptr = std::shared_ptr<NAKPacket>;
  252. using LostPair = std::pair<uint32_t, uint32_t>;
  253. NAKPacket() = default;
  254. ~NAKPacket() = default;
  255. std::string dump();
  256. ///////ControlPacket override///////
  257. bool loadFromData(uint8_t *buf, size_t len) override;
  258. bool storeToData() override;
  259. std::list<LostPair> lost_list;
  260. static size_t getCIFSize(std::list<LostPair> &lost);
  261. };
  262. /*
  263. 0 1 2 3
  264. 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
  265. +-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+
  266. |1| Control Type = 7 | Reserved = 0 |
  267. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  268. | Message Number |
  269. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  270. | Timestamp |
  271. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  272. | Destination Socket ID |
  273. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  274. | First Packet Sequence Number |
  275. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  276. | Last Packet Sequence Number |
  277. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  278. Figure 18: Drop Request control packet
  279. https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-message-drop-request
  280. */
  281. class MsgDropReqPacket : public ControlPacket {
  282. public:
  283. using Ptr = std::shared_ptr<MsgDropReqPacket>;
  284. MsgDropReqPacket() = default;
  285. ~MsgDropReqPacket() = default;
  286. ///////ControlPacket override///////
  287. bool loadFromData(uint8_t *buf, size_t len) override;
  288. bool storeToData() override;
  289. uint32_t first_pkt_seq_num;
  290. uint32_t last_pkt_seq_num;
  291. };
  292. /*
  293. 0 1 2 3
  294. 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
  295. +-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+
  296. |1| Control Type | Reserved |
  297. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  298. | Type-specific Information |
  299. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  300. | Timestamp |
  301. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  302. | Destination Socket ID |
  303. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  304. Figure 16: Shutdown control packet
  305. https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-shutdown
  306. */
  307. class ShutDownPacket : public ControlPacket {
  308. public:
  309. using Ptr = std::shared_ptr<ShutDownPacket>;
  310. ShutDownPacket() = default;
  311. ~ShutDownPacket() = default;
  312. ///////ControlPacket override///////
  313. bool loadFromData(uint8_t *buf, size_t len) override {
  314. if (len < HEADER_SIZE) {
  315. WarnL << "data size" << len << " less " << HEADER_SIZE;
  316. return false;
  317. }
  318. _data = BufferRaw::create();
  319. _data->assign((char *)buf, len);
  320. return loadHeader();
  321. }
  322. bool storeToData() override {
  323. control_type = ControlPacket::SHUTDOWN;
  324. sub_type = 0;
  325. _data = BufferRaw::create();
  326. _data->setCapacity(HEADER_SIZE);
  327. _data->setSize(HEADER_SIZE);
  328. return storeToHeader();
  329. }
  330. };
  331. } // namespace SRT
  332. #endif // ZLMEDIAKIT_SRT_PACKET_H