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 /*****************************************************************************
12 Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
13 All rights reserved.
14
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions are
17 met:
18
19 * Redistributions of source code must retain the above
20 copyright notice, this list of conditions and the
21 following disclaimer.
22
23 * Redistributions in binary form must reproduce the
24 above copyright notice, this list of conditions
25 and the following disclaimer in the documentation
26 and/or other materials provided with the distribution.
27
28 * Neither the name of the University of Illinois
29 nor the names of its contributors may be used to
30 endorse or promote products derived from this
31 software without specific prior written permission.
32
33 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
34 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
35 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
36 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
37 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
38 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
39 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
41 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
42 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
43 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 *****************************************************************************/
45
46 /*****************************************************************************
47 written by
48 Haivision Systems Inc.
49 *****************************************************************************/
50
51 #ifndef INC_SRT_SOCKETCONFIG_H
52 #define INC_SRT_SOCKETCONFIG_H
53
54 #include "platform_sys.h"
55 #ifdef SRT_ENABLE_BINDTODEVICE
56 #include <linux/if.h>
57 #endif
58 #include <string>
59 #include "haicrypt.h"
60 #include "congctl.h"
61 #include "packet.h"
62 #include "handshake.h"
63 #include "logger_defs.h"
64 #include "packetfilter.h"
65
66 // SRT Version constants
67 #define SRT_VERSION_UNK 0
68 #define SRT_VERSION_MAJ1 0x010000 /* Version 1 major */
69 #define SRT_VERSION_MAJ(v) (0xFF0000 & (v)) /* Major number ensuring backward compatibility */
70 #define SRT_VERSION_MIN(v) (0x00FF00 & (v))
71 #define SRT_VERSION_PCH(v) (0x0000FF & (v))
72
73 // NOTE: SRT_VERSION is primarily defined in the build file.
74 extern const int32_t SRT_DEF_VERSION;
75
76 struct CSrtMuxerConfig
77 {
78 static const int DEF_UDP_BUFFER_SIZE = 65536;
79
80 int iIpTTL;
81 int iIpToS;
82 int iIpV6Only; // IPV6_V6ONLY option (-1 if not set)
83 bool bReuseAddr; // reuse an exiting port or not, for UDP multiplexer
84
85 #ifdef SRT_ENABLE_BINDTODEVICE
86 std::string sBindToDevice;
87 #endif
88 int iUDPSndBufSize; // UDP sending buffer size
89 int iUDPRcvBufSize; // UDP receiving buffer size
90
91 bool operator==(const CSrtMuxerConfig& other) const
92 {
93 #define CEQUAL(field) (field == other.field)
94 return CEQUAL(iIpTTL)
95 && CEQUAL(iIpToS)
96 && CEQUAL(iIpV6Only)
97 && CEQUAL(bReuseAddr)
98 #ifdef SRT_ENABLE_BINDTODEVICE
99 && CEQUAL(sBindToDevice)
100 #endif
101 && CEQUAL(iUDPSndBufSize)
102 && CEQUAL(iUDPRcvBufSize);
103 #undef CEQUAL
104 }
105
CSrtMuxerConfigCSrtMuxerConfig106 CSrtMuxerConfig()
107 : iIpTTL(-1) /* IPv4 TTL or IPv6 HOPs [1..255] (-1:undefined) */
108 , iIpToS(-1) /* IPv4 Type of Service or IPv6 Traffic Class [0x00..0xff] (-1:undefined) */
109 , iIpV6Only(-1)
110 , bReuseAddr(true) // This is default in SRT
111 , iUDPSndBufSize(DEF_UDP_BUFFER_SIZE)
112 , iUDPRcvBufSize(DEF_UDP_BUFFER_SIZE)
113 {
114 }
115 };
116
117 struct CSrtConfig;
118
119 template <size_t SIZE>
120 class StringStorage
121 {
122 char stor[SIZE + 1];
123 uint16_t len;
124
125 // NOTE: default copying allowed.
126
127 public:
StringStorage()128 StringStorage()
129 : len(0)
130 {
131 memset(stor, 0, sizeof stor);
132 }
133
set(const char * s,size_t length)134 bool set(const char* s, size_t length)
135 {
136 if (length > SIZE)
137 return false;
138
139 memcpy(stor, s, length);
140 stor[length] = 0;
141 len = (int) length;
142 return true;
143 }
144
set(const std::string & s)145 bool set(const std::string& s)
146 {
147 return set(s.c_str(), s.size());
148 }
149
str()150 std::string str() const
151 {
152 return len == 0 ? std::string() : std::string(stor);
153 }
154
c_str()155 const char* c_str() const
156 {
157 return stor;
158 }
159
size()160 size_t size() const { return size_t(len); }
empty()161 bool empty() const { return len == 0; }
162 };
163
164 struct CSrtConfig: CSrtMuxerConfig
165 {
166 typedef srt::sync::steady_clock::time_point time_point;
167 typedef srt::sync::steady_clock::duration duration;
168
169 static const int
170 DEF_MSS = 1500,
171 DEF_FLIGHT_SIZE = 25600,
172 DEF_BUFFER_SIZE = 8192, //Rcv buffer MUST NOT be bigger than Flight Flag size
173 DEF_LINGER_S = 3*60, // 3 minutes
174 DEF_CONNTIMEO_S = 3; // 3 seconds
175
176 static const int COMM_RESPONSE_TIMEOUT_MS = 5 * 1000; // 5 seconds
177 static const uint32_t COMM_DEF_STABILITY_TIMEOUT_US = 80 * 1000;
178
179 // Mimimum recv flight flag size is 32 packets
180 static const int DEF_MIN_FLIGHT_PKT = 32;
181 static const size_t MAX_SID_LENGTH = 512;
182 static const size_t MAX_PFILTER_LENGTH = 64;
183 static const size_t MAX_CONG_LENGTH = 16;
184
185 int iMSS; // Maximum Segment Size, in bytes
186 size_t zExpPayloadSize; // Expected average payload size (user option)
187
188 // Options
189 bool bSynSending; // Sending syncronization mode
190 bool bSynRecving; // Receiving syncronization mode
191 int iFlightFlagSize; // Maximum number of packets in flight from the peer side
192 int iSndBufSize; // Maximum UDT sender buffer size
193 int iRcvBufSize; // Maximum UDT receiver buffer size
194 linger Linger; // Linger information on close
195 bool bRendezvous; // Rendezvous connection mode
196
197 duration tdConnTimeOut; // connect timeout in milliseconds
198 bool bDriftTracer;
199 int iSndTimeOut; // sending timeout in milliseconds
200 int iRcvTimeOut; // receiving timeout in milliseconds
201 int64_t llMaxBW; // maximum data transfer rate (threshold)
202
203 // These fields keep the options for encryption
204 // (SRTO_PASSPHRASE, SRTO_PBKEYLEN). Crypto object is
205 // created later and takes values from these.
206 HaiCrypt_Secret CryptoSecret;
207 int iSndCryptoKeyLen;
208
209 // XXX Consider removing. The bDataSender stays here
210 // in order to maintain the HS side selection in HSv4.
211 bool bDataSender;
212
213 bool bMessageAPI;
214 bool bTSBPD; // Whether AGENT will do TSBPD Rx (whether peer does, is not agent's problem)
215 int iRcvLatency; // Agent's Rx latency
216 int iPeerLatency; // Peer's Rx latency for the traffic made by Agent's Tx.
217 bool bTLPktDrop; // Whether Agent WILL DO TLPKTDROP on Rx.
218 int iSndDropDelay; // Extra delay when deciding to snd-drop for TLPKTDROP, -1 to off
219 bool bEnforcedEnc; // Off by default. When on, any connection other than nopw-nopw & pw1-pw1 is rejected.
220 int iGroupConnect; // 1 - allow group connections
221 int iPeerIdleTimeout; // Timeout for hearing anything from the peer.
222 uint32_t uStabilityTimeout;
223 int iRetransmitAlgo;
224
225 int64_t llInputBW; // Input stream rate (bytes/sec). 0: use internally estimated input bandwidth
226 int64_t llMinInputBW; // Minimum input stream rate estimate (bytes/sec)
227 int iOverheadBW; // Percent above input stream rate (applies if llMaxBW == 0)
228 bool bRcvNakReport; // Enable Receiver Periodic NAK Reports
229 int iMaxReorderTolerance; //< Maximum allowed value for dynamic reorder tolerance
230
231 // For the use of CCryptoControl
232 // HaiCrypt configuration
233 unsigned int uKmRefreshRatePkt;
234 unsigned int uKmPreAnnouncePkt;
235
236 uint32_t uSrtVersion;
237 uint32_t uMinimumPeerSrtVersion;
238
239 StringStorage<MAX_CONG_LENGTH> sCongestion;
240 StringStorage<MAX_PFILTER_LENGTH> sPacketFilterConfig;
241 StringStorage<MAX_SID_LENGTH> sStreamName;
242
243 // Shortcuts and utilities
flightCapacityCSrtConfig244 int32_t flightCapacity()
245 {
246 return std::min(iRcvBufSize, iFlightFlagSize);
247 }
248
CSrtConfigCSrtConfig249 CSrtConfig()
250 : iMSS(DEF_MSS)
251 , zExpPayloadSize(SRT_LIVE_DEF_PLSIZE)
252 , bSynSending(true)
253 , bSynRecving(true)
254 , iFlightFlagSize(DEF_FLIGHT_SIZE)
255 , iSndBufSize(DEF_BUFFER_SIZE)
256 , iRcvBufSize(DEF_BUFFER_SIZE)
257 , bRendezvous(false)
258 , tdConnTimeOut(srt::sync::seconds_from(DEF_CONNTIMEO_S))
259 , bDriftTracer(true)
260 , iSndTimeOut(-1)
261 , iRcvTimeOut(-1)
262 , llMaxBW(-1)
263 , bDataSender(false)
264 , bMessageAPI(true)
265 , bTSBPD(true)
266 , iRcvLatency(SRT_LIVE_DEF_LATENCY_MS)
267 , iPeerLatency(0)
268 , bTLPktDrop(true)
269 , iSndDropDelay(0)
270 , bEnforcedEnc(true)
271 , iGroupConnect(0)
272 , iPeerIdleTimeout(COMM_RESPONSE_TIMEOUT_MS)
273 , uStabilityTimeout(COMM_DEF_STABILITY_TIMEOUT_US)
274 , iRetransmitAlgo(1)
275 , llInputBW(0)
276 , llMinInputBW(0)
277 , iOverheadBW(25)
278 , bRcvNakReport(true)
279 , iMaxReorderTolerance(0) // Sensible optimal value is 10, 0 preserves old behavior
280 , uKmRefreshRatePkt(0)
281 , uKmPreAnnouncePkt(0)
282 , uSrtVersion(SRT_DEF_VERSION)
283 , uMinimumPeerSrtVersion(SRT_VERSION_MAJ1)
284
285 {
286 // Default UDT configurations
287 iUDPRcvBufSize = iRcvBufSize * iMSS;
288
289 // Linger: LIVE mode defaults, please refer to `SRTO_TRANSTYPE` option
290 // for other modes.
291 Linger.l_onoff = 0;
292 Linger.l_linger = 0;
293 CryptoSecret.len = 0;
294 iSndCryptoKeyLen = 0;
295
296 // Default congestion is "live".
297 // Available builtin congestions: "file".
298 // Others can be registerred.
299 sCongestion.set("live", 4);
300 }
301
~CSrtConfigCSrtConfig302 ~CSrtConfig()
303 {
304 // Wipeout critical data
305 memset(&CryptoSecret, 0, sizeof(CryptoSecret));
306 }
307
308 int set(SRT_SOCKOPT optName, const void* val, int size);
309 };
310
311
312 #if ENABLE_EXPERIMENTAL_BONDING
313
314 struct SRT_SocketOptionObject
315 {
316 struct SingleOption
317 {
318 uint16_t option;
319 uint16_t length;
320 unsigned char storage[1]; // NOTE: Variable length object!
321 };
322
323
324 std::vector<SingleOption*> options;
325
SRT_SocketOptionObjectSRT_SocketOptionObject326 SRT_SocketOptionObject() {}
327
~SRT_SocketOptionObjectSRT_SocketOptionObject328 ~SRT_SocketOptionObject()
329 {
330 for (size_t i = 0; i < options.size(); ++i)
331 {
332 // Convert back
333 unsigned char* mem = reinterpret_cast<unsigned char*>(options[i]);
334 delete[] mem;
335 }
336 }
337
338 bool add(SRT_SOCKOPT optname, const void* optval, size_t optlen);
339 };
340 #endif
341
342 template <typename T>
cast_optval(const void * optval)343 inline T cast_optval(const void* optval)
344 {
345 return *reinterpret_cast<const T*>(optval);
346 }
347
348 template <typename T>
cast_optval(const void * optval,int optlen)349 inline T cast_optval(const void* optval, int optlen)
350 {
351 if (optlen > 0 && optlen != sizeof(T))
352 throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
353
354 return cast_optval<T>(optval);
355 }
356
357 // This function is to make it possible for both C and C++
358 // API to accept both bool and int types for boolean options.
359 // (it's not that C couldn't use <stdbool.h>, it's that people
360 // often forget to use correct type).
361 template <>
cast_optval(const void * optval,int optlen)362 inline bool cast_optval(const void* optval, int optlen)
363 {
364 if (optlen == sizeof(bool))
365 {
366 return *reinterpret_cast<const bool*>(optval);
367 }
368
369 if (optlen == sizeof(int))
370 {
371 // 0!= is a windows warning-killer int-to-bool conversion
372 return 0 != *reinterpret_cast<const int*>(optval);
373 }
374 return false;
375 }
376
377 #endif
378