forked from Haivision/srt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
apputil.hpp
339 lines (277 loc) · 8.34 KB
/
apputil.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2018 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#ifndef INC_SRT_APPCOMMON_H
#define INC_SRT_APPCOMMON_H
#include <string>
#include <map>
#include <set>
#include <vector>
#include <memory>
#include "netinet_any.h"
#include "utilities.h"
#if _WIN32
// Keep this below commented out.
// This is for a case when you need cpp debugging on Windows.
//#ifdef _WINSOCKAPI_
//#error "You include <winsock.h> somewhere, remove it. It causes conflicts"
//#endif
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
// WIN32 API does not have sleep() and usleep(), Although MINGW does.
#ifdef __MINGW32__
#include <unistd.h>
#else
extern "C" inline int sleep(int seconds) { Sleep(seconds * 1000); return 0; }
#endif
inline bool SysInitializeNetwork()
{
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
return WSAStartup(wVersionRequested, &wsaData) == 0;
}
inline void SysCleanupNetwork()
{
WSACleanup();
}
#else
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
// Fixes Android build on NDK r16b and earlier.
#if defined(__ANDROID__) && (__ANDROID__ == 1)
#include <android/ndk-version.h>
#if !defined(__NDK_MAJOR__) || (__NDK_MAJOR__ <= 16)
struct ip_mreq_sourceFIXED {
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
struct in_addr imr_sourceaddr;
};
#define ip_mreq_source ip_mreq_sourceFIXED
#endif
#endif
// Nothing needs to be done on POSIX; this is a Windows problem.
inline bool SysInitializeNetwork() {return true;}
inline void SysCleanupNetwork() {}
#endif
#ifdef _WIN32
inline int SysError() { return ::GetLastError(); }
const int SysAGAIN = WSAEWOULDBLOCK;
#else
inline int SysError() { return errno; }
const int SysAGAIN = EAGAIN;
#endif
srt::sockaddr_any CreateAddr(const std::string& name, unsigned short port = 0, int pref_family = AF_UNSPEC);
std::string Join(const std::vector<std::string>& in, std::string sep);
template <class VarType, class ValType>
struct OnReturnSetter
{
VarType& var;
ValType value;
OnReturnSetter(VarType& target, ValType v): var(target), value(v) {}
~OnReturnSetter() { var = value; }
};
template <class VarType, class ValType>
OnReturnSetter<VarType, ValType> OnReturnSet(VarType& target, ValType v)
{ return OnReturnSetter<VarType, ValType>(target, v); }
// ---- OPTIONS MODULE
inline bool CheckTrue(const std::vector<std::string>& in)
{
if (in.empty())
return true;
const std::set<std::string> false_vals = { "0", "no", "off", "false" };
if (false_vals.count(in[0]))
return false;
return true;
//if (in[0] != "false" && in[0] != "off")
// return true;
//return false;
}
template<class Number>
static inline Number StrToNumber(const std::string& )
{
typename Number::incorrect_version wrong = Number::incorrect_version;
return Number();
}
#define STON(type, function) \
template<> inline type StrToNumber(const std::string& s) { return function (s, 0, 0); }
STON(int, stoi);
STON(unsigned long, stoul);
STON(unsigned int, stoul);
STON(long long, stoll);
STON(unsigned long long, stoull);
#undef STON
typedef std::map<std::string, std::vector<std::string>> options_t;
struct OutList
{
typedef std::vector<std::string> type;
static type process(const options_t::mapped_type& i) { return i; }
};
struct OutString
{
typedef std::string type;
static type process(const options_t::mapped_type& i) { return Join(i, " "); }
};
struct NumberAutoConvert
{
std::string value;
NumberAutoConvert(): NumberAutoConvert("") {}
NumberAutoConvert(const std::string& arg): NumberAutoConvert(arg.c_str()) {}
NumberAutoConvert(const char* arg): value(arg)
{
if (value.empty())
value = "0"; // Must convert to a default 0 number
}
template<class Number>
operator Number()
{
return StrToNumber<Number>(value);
}
};
struct OutNumber
{
typedef NumberAutoConvert type;
static type process(const options_t::mapped_type& i)
{
// Numbers can't be joined, use the "last overrides" rule.
if (i.empty())
return {"0"};
return type { i.back() };
}
};
template <class Number>
struct OutNumberAs
{
typedef Number type;
static type process(const options_t::mapped_type& i)
{
return OutNumber::process(i);
}
};
struct OutBool
{
typedef bool type;
static type process(const options_t::mapped_type& i) { return CheckTrue(i); }
};
struct OptionName;
struct OptionScheme
{
const OptionName* pid;
enum Args { ARG_NONE, ARG_ONE, ARG_VAR } type;
OptionScheme(const OptionScheme&) = default;
OptionScheme(OptionScheme&& src)
: pid(src.pid)
, type(src.type)
{
}
OptionScheme(const OptionName& id, Args tp);
const std::set<std::string>& names() const;
};
struct OptionName
{
std::string helptext;
std::string main_name;
std::set<std::string> names;
template <class... Args>
OptionName(std::string ht, std::string first, Args... rest)
: helptext(ht), main_name(first),
names {first, rest...}
{
}
template <class... Args>
OptionName(std::vector<OptionScheme>& sc, OptionScheme::Args type,
std::string ht, std::string first, Args... rest)
: helptext(ht), main_name(first),
names {first, rest...}
{
sc.push_back(OptionScheme(*this, type));
}
template <class... Args>
OptionName(std::vector<OptionScheme>& sc,
std::string ht, std::string first, Args... rest)
: helptext(ht), main_name(first),
names {first, rest...}
{
OptionScheme::Args type = DetermineTypeFromHelpText(ht);
sc.push_back(OptionScheme(*this, type));
}
OptionName(std::initializer_list<std::string> args): main_name(*args.begin()), names(args) {}
operator std::set<std::string>() { return names; }
operator const std::set<std::string>() const { return names; }
private:
static OptionScheme::Args DetermineTypeFromHelpText(const std::string& helptext);
};
inline OptionScheme::OptionScheme(const OptionName& id, Args tp): pid(&id), type(tp) {}
inline const std::set<std::string>& OptionScheme::names() const { return pid->names; }
template <class OutType, class OutValue> inline
typename OutType::type Option(const options_t&, OutValue deflt=OutValue()) { return deflt; }
template <class OutType, class OutValue, class... Args> inline
typename OutType::type Option(const options_t& options, OutValue deflt, std::string key, Args... further_keys)
{
auto i = options.find(key);
if ( i == options.end() )
return Option<OutType>(options, deflt, further_keys...);
return OutType::process(i->second);
}
template<typename TrapType>
struct OptionTrapType
{
static TrapType pass(TrapType v) { return v; }
};
template<>
struct OptionTrapType<const char*>
{
static std::string pass(const char* v) { return v; }
};
template <class OutType, class OutValue> inline
typename OutType::type Option(const options_t& options, OutValue deflt, const OptionName& oname)
{
(void)OptionTrapType<OutValue>::pass(deflt);
for (auto key: oname.names)
{
auto i = options.find(key);
if ( i != options.end() )
{
return OutType::process(i->second);
}
}
return deflt;
}
template <class OutType> inline
typename OutType::type Option(const options_t& options, const OptionName& oname)
{
typedef typename OutType::type out_t;
for (auto key: oname.names)
{
auto i = options.find(key);
if ( i != options.end() )
{
return OutType::process(i->second);
}
}
return out_t();
}
inline bool OptionPresent(const options_t& options, const std::set<std::string>& keys)
{
for (auto key: keys)
{
auto i = options.find(key);
if ( i != options.end() )
return true;
}
return false;
}
options_t ProcessOptions(char* const* argv, int argc, std::vector<OptionScheme> scheme);
std::string OptionHelpItem(const OptionName& o);
const char* SRTClockTypeStr();
void PrintLibVersion();
#endif // INC_SRT_APPCOMMON_H