handshake.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /*
  2. * SRT - Secure, Reliable, Transport
  3. * Copyright (c) 2018 Haivision Systems Inc.
  4. *
  5. * This Source Code Form is subject to the terms of the Mozilla Public
  6. * License, v. 2.0. If a copy of the MPL was not distributed with this
  7. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  8. *
  9. */
  10. /*****************************************************************************
  11. Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
  12. All rights reserved.
  13. Redistribution and use in source and binary forms, with or without
  14. modification, are permitted provided that the following conditions are
  15. met:
  16. * Redistributions of source code must retain the above
  17. copyright notice, this list of conditions and the
  18. following disclaimer.
  19. * Redistributions in binary form must reproduce the
  20. above copyright notice, this list of conditions
  21. and the following disclaimer in the documentation
  22. and/or other materials provided with the distribution.
  23. * Neither the name of the University of Illinois
  24. nor the names of its contributors may be used to
  25. endorse or promote products derived from this
  26. software without specific prior written permission.
  27. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  28. IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  29. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  30. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  31. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  32. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  33. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  34. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  35. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  36. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  37. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *****************************************************************************/
  39. #ifndef INC_SRT_HANDSHAKE_H
  40. #define INC_SRT_HANDSHAKE_H
  41. #include <vector>
  42. #include "crypto.h"
  43. #include "utilities.h"
  44. namespace srt
  45. {
  46. typedef Bits<31, 16> HS_CMDSPEC_CMD;
  47. typedef Bits<15, 0> HS_CMDSPEC_SIZE;
  48. // NOTE: Some of these flags represent CAPABILITIES, that is,
  49. // as long as these flags are defined, they must be always set
  50. // (unless they are deprecated).
  51. enum SrtOptions
  52. {
  53. SRT_OPT_TSBPDSND = BIT(0), /* Timestamp-based Packet delivery real-time data sender */
  54. SRT_OPT_TSBPDRCV = BIT(1), /* Timestamp-based Packet delivery real-time data receiver */
  55. SRT_OPT_HAICRYPT = BIT(2), /* CAPABILITY: HaiCrypt AES-128/192/256-CTR */
  56. SRT_OPT_TLPKTDROP = BIT(3), /* Drop real-time data packets too late to be processed in time */
  57. SRT_OPT_NAKREPORT = BIT(4), /* Periodic NAK report */
  58. SRT_OPT_REXMITFLG = BIT(5), // CAPABILITY: One bit in payload packet msgno is "retransmitted" flag
  59. // (this flag can be reused for something else, when pre-1.2.0 versions are all abandoned)
  60. SRT_OPT_STREAM = BIT(6), // STREAM MODE (not MESSAGE mode)
  61. SRT_OPT_FILTERCAP = BIT(7), // CAPABILITY: Packet filter supported
  62. };
  63. inline int SrtVersionCapabilities()
  64. {
  65. // NOTE: SRT_OPT_REXMITFLG is not included here because
  66. // SRT is prepared to handle also peers that don't have this
  67. // capability, so a listener responding to a peer that doesn't
  68. // support it should NOT set this flag.
  69. //
  70. // This state will remain until this backward compatibility is
  71. // decided to be broken, in which case this flag will be always
  72. // set, and clients that do not support this capability will be
  73. // rejected.
  74. return SRT_OPT_HAICRYPT | SRT_OPT_FILTERCAP;
  75. }
  76. std::string SrtFlagString(int32_t flags);
  77. const int SRT_CMD_REJECT = 0, // REJECT is only a symbol for return type
  78. SRT_CMD_HSREQ = 1,
  79. SRT_CMD_HSRSP = 2,
  80. SRT_CMD_KMREQ = 3,
  81. SRT_CMD_KMRSP = 4,
  82. SRT_CMD_SID = 5,
  83. SRT_CMD_CONGESTION = 6,
  84. SRT_CMD_FILTER = 7,
  85. SRT_CMD_GROUP = 8,
  86. SRT_CMD_NONE = -1; // for cases when {no pong for ping is required} | {no extension block found}
  87. enum SrtDataStruct
  88. {
  89. SRT_HS_VERSION = 0,
  90. SRT_HS_FLAGS,
  91. SRT_HS_LATENCY,
  92. // Keep it always last
  93. SRT_HS_E_SIZE
  94. };
  95. // For HSv5 the lo and hi part is used for particular side's latency
  96. typedef Bits<31, 16> SRT_HS_LATENCY_RCV;
  97. typedef Bits<15, 0> SRT_HS_LATENCY_SND;
  98. // For HSv4 only the lower part is used.
  99. typedef Bits<15, 0> SRT_HS_LATENCY_LEG;
  100. struct SrtHandshakeExtension
  101. {
  102. int16_t type;
  103. std::vector<uint32_t> contents;
  104. SrtHandshakeExtension(int16_t cmd): type(cmd) {}
  105. };
  106. // Implemented in core.cpp, so far
  107. void SrtExtractHandshakeExtensions(const char* bufbegin, size_t size,
  108. std::vector<SrtHandshakeExtension>& w_output);
  109. struct SrtHSRequest: public SrtHandshakeExtension
  110. {
  111. typedef Bits<31, 16> SRT_HSTYPE_ENCFLAGS;
  112. typedef Bits<15, 0> SRT_HSTYPE_HSFLAGS;
  113. // For translating PBKEYLEN into crypto flags
  114. // This value is 16, 24, 32; after cutting off
  115. // the leftmost 3 bits, it is 2, 3, 4.
  116. typedef Bits<5, 3> SRT_PBKEYLEN_BITS;
  117. // This value fits ins SRT_HSTYPE_HSFLAGS.
  118. // .... HAIVISIOn
  119. static const int32_t SRT_MAGIC_CODE = 0x4A17;
  120. static int32_t wrapFlags(bool withmagic, int crypto_keylen)
  121. {
  122. int32_t base = withmagic ? SRT_MAGIC_CODE : 0;
  123. return base | SRT_HSTYPE_ENCFLAGS::wrap( SRT_PBKEYLEN_BITS::unwrap(crypto_keylen) );
  124. }
  125. // Group handshake extension layout
  126. // 0 1 2 3
  127. // 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
  128. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  129. // | Group ID |
  130. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  131. // | Group Type | Group's Flags | Group's Weight |
  132. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  133. typedef Bits<31, 24> HS_GROUP_TYPE;
  134. typedef Bits<23, 16> HS_GROUP_FLAGS;
  135. typedef Bits<15, 0> HS_GROUP_WEIGHT;
  136. private:
  137. friend class CHandShake;
  138. static const size_t SRT_HS_SIZE = 4*sizeof(uint32_t); // 4 existing fields
  139. static const size_t SRT_EXT_HS_SIZE = 2*sizeof(uint32_t) + SRT_HS_SIZE; // SRT magic and SRT HS type, used only in UDT HS ext
  140. typedef Bits<15, 0> SRT_TSBPD_DELAY;
  141. uint32_t m_iSrtVersion;
  142. uint32_t m_iSrtFlags;
  143. uint32_t m_iSrtTsbpd;
  144. uint32_t m_iSrtReserved;
  145. public:
  146. SrtHSRequest(): SrtHandshakeExtension(SRT_CMD_HSREQ), m_iSrtVersion(), m_iSrtFlags(), m_iSrtTsbpd(), m_iSrtReserved() {}
  147. void setVersion(uint32_t v) { m_iSrtVersion = v; }
  148. uint32_t version() const { return m_iSrtVersion; }
  149. void setFlag(SrtOptions opt) { m_iSrtFlags |= uint32_t(opt); }
  150. void clearFlag(SrtOptions opt) { m_iSrtFlags &= ~opt; }
  151. uint32_t flags() const { return m_iSrtFlags; }
  152. void setTsbPdDelay(uint16_t delay) { m_iSrtTsbpd |= SRT_TSBPD_DELAY::wrap(delay); }
  153. // Unknown what the 1-16 bits have to be used for.
  154. uint16_t tsbPdDelay() const
  155. {
  156. return SRT_TSBPD_DELAY::unwrap(m_iSrtTsbpd);
  157. }
  158. size_t size() const { return SRT_EXT_HS_SIZE; }
  159. bool serialize(char* p, size_t size) const;
  160. bool deserialize(const char* mem, size_t size);
  161. };
  162. struct SrtKMRequest: public SrtHandshakeExtension
  163. {
  164. uint32_t m_iKmState;
  165. char m_aKey[1]; // dynamic size
  166. };
  167. ////////////////////////////////////////////////////////////////////////////////
  168. enum UDTRequestType
  169. {
  170. URQ_INDUCTION_TYPES = 0, // XXX used to check in one place. Consdr rm.
  171. URQ_INDUCTION = 1, // First part for client-server connection
  172. URQ_WAVEAHAND = 0, // First part for rendezvous connection
  173. URQ_CONCLUSION = -1, // Second part of handshake negotiation
  174. URQ_AGREEMENT = -2, // Extra (last) step for rendezvous only
  175. URQ_DONE = -3, // Special value used only in state-switching, to state that nothing should be sent in response
  176. // Note: the client-server connection uses:
  177. // --> INDUCTION (empty)
  178. // <-- INDUCTION (cookie)
  179. // --> CONCLUSION (cookie)
  180. // <-- CONCLUSION (ok)
  181. // The rendezvous HSv4 (legacy):
  182. // --> WAVEAHAND (effective only if peer is also connecting)
  183. // <-- CONCLUSION (empty) (consider yourself connected upon reception)
  184. // --> AGREEMENT (sent as a response for conclusion, requires no response)
  185. // The rendezvous HSv5 (using SRT extensions):
  186. // --> WAVEAHAND (with cookie)
  187. // --- (selecting INITIATOR/RESPONDER by cookie contest - comparing one another's cookie)
  188. // <-- CONCLUSION (without extensions, if RESPONDER, with extensions, if INITIATOR)
  189. // --> CONCLUSION (with response extensions, if RESPONDER)
  190. // <-- AGREEMENT (sent exclusively by INITIATOR upon reception of CONCLUSIOn with response extensions)
  191. // This marks the beginning of values that are error codes.
  192. URQ_FAILURE_TYPES = 1000,
  193. // NOTE: codes above 1000 are reserved for failure codes for
  194. // rejection reason, as per `SRT_REJECT_REASON` enum. The
  195. // actual rejection code is the value of the request type
  196. // minus URQ_FAILURE_TYPES.
  197. // This is in order to return standard error codes for server
  198. // data retrieval failures.
  199. URQ_SERVER_FAILURE_TYPES = URQ_FAILURE_TYPES + SRT_REJC_PREDEFINED,
  200. // This is for a completely user-defined reject reasons.
  201. URQ_USER_FAILURE_TYPES = URQ_FAILURE_TYPES + SRT_REJC_USERDEFINED
  202. };
  203. inline UDTRequestType URQFailure(int reason)
  204. {
  205. return UDTRequestType(URQ_FAILURE_TYPES + int(reason));
  206. }
  207. inline int RejectReasonForURQ(UDTRequestType req)
  208. {
  209. if (req < URQ_FAILURE_TYPES)
  210. return SRT_REJ_UNKNOWN;
  211. int reason = req - URQ_FAILURE_TYPES;
  212. if (reason < SRT_REJC_PREDEFINED && reason >= SRT_REJ_E_SIZE)
  213. return SRT_REJ_UNKNOWN;
  214. return reason;
  215. }
  216. // DEPRECATED values. Use URQFailure(SRT_REJECT_REASON).
  217. const UDTRequestType URQ_ERROR_REJECT SRT_ATR_DEPRECATED = (UDTRequestType)1002; // == 1000 + SRT_REJ_PEER
  218. const UDTRequestType URQ_ERROR_INVALID SRT_ATR_DEPRECATED = (UDTRequestType)1004; // == 1000 + SRT_REJ_ROGUE
  219. // XXX Change all uses of that field to UDTRequestType when possible
  220. #if ENABLE_LOGGING
  221. std::string RequestTypeStr(UDTRequestType);
  222. #else
  223. inline std::string RequestTypeStr(UDTRequestType) { return ""; }
  224. #endif
  225. class CHandShake
  226. {
  227. public:
  228. CHandShake();
  229. int store_to(char* buf, size_t& size);
  230. int load_from(const char* buf, size_t size);
  231. public:
  232. // This is the size of SERIALIZED handshake.
  233. // Might be defined as simply sizeof(CHandShake), but the
  234. // enum values would have to be forced as int32_t, which is only
  235. // available in C++11. Theoretically they are all 32-bit, but
  236. // such a statement is not reliable and not portable.
  237. static const size_t m_iContentSize = 48; // Size of hand shake data
  238. // Extension flags
  239. static const int32_t HS_EXT_HSREQ = BIT(0);
  240. static const int32_t HS_EXT_KMREQ = BIT(1);
  241. static const int32_t HS_EXT_CONFIG = BIT(2);
  242. static std::string ExtensionFlagStr(int32_t fl);
  243. // Applicable only when m_iVersion == HS_VERSION_SRT1
  244. int32_t flags() { return m_iType; }
  245. public:
  246. int32_t m_iVersion; // UDT version (HS_VERSION_* symbols)
  247. int32_t m_iType; // UDT4: socket type (only UDT_DGRAM is valid); SRT1: extension flags
  248. int32_t m_iISN; // random initial sequence number
  249. int32_t m_iMSS; // maximum segment size
  250. int32_t m_iFlightFlagSize; // flow control window size
  251. UDTRequestType m_iReqType; // handshake stage
  252. int32_t m_iID; // SRT socket ID of HS sender
  253. int32_t m_iCookie; // cookie
  254. uint32_t m_piPeerIP[4]; // The IP address that the peer's UDP port is bound to
  255. bool m_extension;
  256. bool valid();
  257. std::string show();
  258. // The rendezvous state machine used in HSv5 only (in HSv4 everything is happening the old way).
  259. //
  260. // The WAVING state is the very initial state of the rendezvous connection and restored after the
  261. // connection is closed.
  262. // The ATTENTION and FINE are two alternative states that are transited to from WAVING. The possible
  263. // situations are:
  264. // - "serial arrangement": one party transits to ATTENTION and the other party transits to FINE
  265. // - "parallel arrangement" both parties transit to ATTENTION
  266. //
  267. // Parallel arrangement is a "virtually impossible" case, in which both parties must send the first
  268. // URQ_WAVEAHAND message in a perfect time synchronization, when they are started at exactly the same
  269. // time, on machines with exactly the same performance and all things preceding the message sending
  270. // have taken perfectly identical amount of time. This isn't anyhow possible otherwise because if
  271. // the clients have started at different times, the one who started first sends a message and the
  272. // system of the receiver buffers this message even before the client binds the port for enough long
  273. // time so that it outlasts also the possible second, repeated waveahand.
  274. enum RendezvousState
  275. {
  276. RDV_INVALID, //< This socket wasn't prepared for rendezvous process. Reject any events.
  277. RDV_WAVING, //< Initial state for rendezvous. No contact seen from the peer.
  278. RDV_ATTENTION, //< When received URQ_WAVEAHAND. [WAVING]:URQ_WAVEAHAND --> [ATTENTION].
  279. RDV_FINE, //< When received URQ_CONCLUSION. [WAVING]:URQ_CONCLUSION --> [FINE].
  280. RDV_INITIATED, //< When received URQ_CONCLUSION+HSREQ extension in ATTENTION state.
  281. RDV_CONNECTED //< Final connected state. [ATTENTION]:URQ_CONCLUSION --> [CONNECTED] <-- [FINE]:URQ_AGREEMENT.
  282. };
  283. #if ENABLE_LOGGING
  284. static std::string RdvStateStr(RendezvousState s);
  285. #else
  286. static std::string RdvStateStr(RendezvousState) { return ""; }
  287. #endif
  288. };
  289. } // namespace srt
  290. #endif