/* * 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 #include #include #include #include #include "netinet_any.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 somewhere, remove it. It causes conflicts" //#endif #include #include #include // WIN32 API does not have sleep() and usleep(), Although MINGW does. #ifdef __MINGW32__ #include #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 #include #include #include #include // Nothing needs to be done on POSIX; this is a Windows problem. inline bool SysInitializeNetwork() {return true;} inline void SysCleanupNetwork() {} #endif #include "srt.h" // Required for stats module #ifdef _WIN32 inline int SysError() { return ::GetLastError(); } #else inline int SysError() { return errno; } #endif sockaddr_any CreateAddr(const std::string& name, unsigned short port = 0, int pref_family = AF_UNSPEC); std::string Join(const std::vector& in, std::string sep); inline bool CheckTrue(const std::vector& in) { if (in.empty()) return true; const std::set 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 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> options_t; struct OutList { typedef std::vector 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 operator Number() { return StrToNumber(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 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& names(); }; struct OptionName { std::string helptext; std::string main_name; std::set names; template OptionName(std::string ht, std::string first, Args... rest) : helptext(ht), main_name(first), names {first, rest...} { } template OptionName(std::vector& 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 OptionName(std::vector& 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 args): main_name(*args.begin()), names(args) {} operator std::set() { return names; } operator const std::set() 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& OptionScheme::names() { return pid->names; } template inline typename OutType::type Option(const options_t&, OutValue deflt=OutValue()) { return deflt; } template 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(options, deflt, further_keys...); return OutType::process(i->second); } template struct OptionTrapType { static TrapType pass(TrapType v) { return v; } }; template<> struct OptionTrapType { static std::string pass(const char* v) { return v; } }; template inline typename OutType::type Option(const options_t& options, OutValue deflt, const OptionName& oname) { (void)OptionTrapType::pass(deflt); for (auto key: oname.names) { auto i = options.find(key); if ( i != options.end() ) { return OutType::process(i->second); } } return deflt; } template 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& 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 scheme); std::string OptionHelpItem(const OptionName& o); // Statistics module enum SrtStatsPrintFormat { SRTSTATS_PROFMAT_INVALID = -1, SRTSTATS_PROFMAT_2COLS = 0, SRTSTATS_PROFMAT_JSON, SRTSTATS_PROFMAT_CSV }; SrtStatsPrintFormat ParsePrintFormat(std::string pf); class SrtStatsWriter { public: virtual std::string WriteStats(int sid, const CBytePerfMon& mon) = 0; virtual std::string WriteBandwidth(double mbpsBandwidth) = 0; virtual ~SrtStatsWriter() { }; }; std::shared_ptr SrtStatsWriterFactory(SrtStatsPrintFormat printformat); #endif // INC_SRT_APPCOMMON_H