7 #include <packager/file/udp_options.h>
11 #include <absl/flags/flag.h>
12 #include <absl/log/check.h>
13 #include <absl/log/log.h>
14 #include <absl/strings/numbers.h>
15 #include <absl/strings/str_split.h>
17 #include <packager/kv_pairs/kv_pairs.h>
19 ABSL_FLAG(std::string,
20 udp_interface_address,
22 "IP address of the interface over which to receive UDP unicast"
23 " or multicast streams");
32 kInterfaceAddressField,
33 kMulticastSourceField,
38 struct FieldNameToTypeMapping {
39 const char* field_name;
43 const FieldNameToTypeMapping kFieldNameTypeMappings[] = {
44 {
"buffer_size", kBufferSizeField},
45 {
"interface", kInterfaceAddressField},
46 {
"reuse", kReuseField},
47 {
"source", kMulticastSourceField},
48 {
"timeout", kTimeoutField},
51 FieldType GetFieldType(
const std::string& field_name) {
52 for (
size_t idx = 0; idx < std::size(kFieldNameTypeMappings); ++idx) {
53 if (field_name == kFieldNameTypeMappings[idx].field_name)
54 return kFieldNameTypeMappings[idx].field_type;
59 bool StringToAddressAndPort(std::string_view addr_and_port,
65 const size_t colon_pos = addr_and_port.find(
':');
66 if (colon_pos == std::string_view::npos) {
69 *addr = addr_and_port.substr(0, colon_pos);
74 if (!absl::SimpleAtoi(addr_and_port.substr(colon_pos + 1), &port_value) ||
75 (port_value > 65535)) {
78 *port =
static_cast<uint16_t
>(port_value);
85 std::string_view udp_url) {
86 std::unique_ptr<UdpOptions> options(
new UdpOptions);
88 const size_t question_mark_pos = udp_url.find(
'?');
89 std::string_view address_str = udp_url.substr(0, question_mark_pos);
91 if (question_mark_pos != std::string_view::npos) {
92 std::string_view options_str = udp_url.substr(question_mark_pos + 1);
93 std::vector<KVPair> kv_pairs = SplitStringIntoKeyValuePairs(options_str);
95 for (
const auto& pair : kv_pairs) {
96 switch (GetFieldType(pair.first)) {
97 case kBufferSizeField:
98 if (!absl::SimpleAtoi(pair.second, &options->buffer_size_)) {
99 LOG(ERROR) <<
"Invalid udp option for buffer_size field "
104 case kInterfaceAddressField:
105 options->interface_address_ = pair.second;
107 case kMulticastSourceField:
108 options->source_address_ = pair.second;
109 options->is_source_specific_multicast_ =
true;
113 if (!absl::SimpleAtoi(pair.second, &reuse_value)) {
114 LOG(ERROR) <<
"Invalid udp option for reuse field " << pair.second;
117 options->reuse_ = reuse_value > 0;
121 if (!absl::SimpleAtoi(pair.second, &options->timeout_us_)) {
122 LOG(ERROR) <<
"Invalid udp option for timeout field "
128 LOG(ERROR) <<
"Unknown field in udp options (\"" << pair.first
135 if (!absl::GetFlag(FLAGS_udp_interface_address).empty()) {
136 LOG(WARNING) <<
"--udp_interface_address is deprecated. Consider switching "
137 "to udp options instead, something like "
138 "udp:://ip:port?interface=interface_ip.";
139 options->interface_address_ = absl::GetFlag(FLAGS_udp_interface_address);
142 if (!StringToAddressAndPort(address_str, &options->address_,
144 LOG(ERROR) <<
"Malformed address:port UDP url " << address_str;
Options parsed from UDP url string of the form: udp://ip:port[?options].
static std::unique_ptr< UdpOptions > ParseFromString(std::string_view udp_url)
All the methods that are virtual are virtual for mocking.