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