Shaka Packager SDK
udp_options.cc
1 // Copyright 2016 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/file/udp_options.h"
8 
9 #include <gflags/gflags.h>
10 
11 #include "packager/base/strings/string_number_conversions.h"
12 #include "packager/base/strings/string_split.h"
13 
14 DEFINE_string(udp_interface_address,
15  "",
16  "IP address of the interface over which to receive UDP unicast"
17  " or multicast streams");
18 
19 namespace shaka {
20 
21 namespace {
22 
23 enum FieldType {
24  kUnknownField = 0,
25  kBufferSizeField,
26  kInterfaceAddressField,
27  kMulticastSourceField,
28  kReuseField,
29  kTimeoutField,
30 };
31 
32 struct FieldNameToTypeMapping {
33  const char* field_name;
34  FieldType field_type;
35 };
36 
37 const FieldNameToTypeMapping kFieldNameTypeMappings[] = {
38  {"buffer_size", kBufferSizeField},
39  {"interface", kInterfaceAddressField},
40  {"reuse", kReuseField},
41  {"source", kMulticastSourceField},
42  {"timeout", kTimeoutField},
43 };
44 
45 FieldType GetFieldType(const std::string& field_name) {
46  for (size_t idx = 0; idx < arraysize(kFieldNameTypeMappings); ++idx) {
47  if (field_name == kFieldNameTypeMappings[idx].field_name)
48  return kFieldNameTypeMappings[idx].field_type;
49  }
50  return kUnknownField;
51 }
52 
53 bool StringToAddressAndPort(base::StringPiece addr_and_port,
54  std::string* addr,
55  uint16_t* port) {
56  DCHECK(addr);
57  DCHECK(port);
58 
59  const size_t colon_pos = addr_and_port.find(':');
60  if (colon_pos == base::StringPiece::npos) {
61  return false;
62  }
63  *addr = addr_and_port.substr(0, colon_pos).as_string();
64  unsigned port_value;
65  if (!base::StringToUint(addr_and_port.substr(colon_pos + 1), &port_value) ||
66  (port_value > 65535)) {
67  return false;
68  }
69  *port = port_value;
70  return true;
71 }
72 
73 } // namespace
74 
75 std::unique_ptr<UdpOptions> UdpOptions::ParseFromString(
76  base::StringPiece udp_url) {
77  std::unique_ptr<UdpOptions> options(new UdpOptions);
78 
79  const size_t question_mark_pos = udp_url.find('?');
80  base::StringPiece address_str = udp_url.substr(0, question_mark_pos);
81 
82  if (question_mark_pos != base::StringPiece::npos) {
83  base::StringPiece options_str = udp_url.substr(question_mark_pos + 1);
84 
85  base::StringPairs pairs;
86  if (!base::SplitStringIntoKeyValuePairs(options_str, '=', '&', &pairs)) {
87  LOG(ERROR) << "Invalid udp options name/value pairs " << options_str;
88  return nullptr;
89  }
90  for (const auto& pair : pairs) {
91  switch (GetFieldType(pair.first)) {
92  case kBufferSizeField:
93  if (!base::StringToInt(pair.second, &options->buffer_size_)) {
94  LOG(ERROR) << "Invalid udp option for buffer_size field "
95  << pair.second;
96  return nullptr;
97  }
98  break;
99  case kInterfaceAddressField:
100  options->interface_address_ = pair.second;
101  break;
102  case kMulticastSourceField:
103  options->source_address_ = pair.second;
104  options->is_source_specific_multicast_ = true;
105  break;
106  case kReuseField: {
107  int reuse_value = 0;
108  if (!base::StringToInt(pair.second, &reuse_value)) {
109  LOG(ERROR) << "Invalid udp option for reuse field " << pair.second;
110  return nullptr;
111  }
112  options->reuse_ = reuse_value > 0;
113  break;
114  }
115  case kTimeoutField:
116  if (!base::StringToUint(pair.second, &options->timeout_us_)) {
117  LOG(ERROR) << "Invalid udp option for timeout field "
118  << pair.second;
119  return nullptr;
120  }
121  break;
122  default:
123  LOG(ERROR) << "Unknown field in udp options (\"" << pair.first
124  << "\").";
125  return nullptr;
126  }
127  }
128  }
129 
130  if (!FLAGS_udp_interface_address.empty()) {
131  LOG(WARNING) << "--udp_interface_address is deprecated. Consider switching "
132  "to udp options instead, something like "
133  "udp:://ip:port?interface=interface_ip.";
134  options->interface_address_ = FLAGS_udp_interface_address;
135  }
136 
137  if (!StringToAddressAndPort(address_str, &options->address_,
138  &options->port_)) {
139  LOG(ERROR) << "Malformed address:port UDP url " << address_str;
140  return nullptr;
141  }
142  return options;
143 }
144 
145 } // namespace shaka
shaka
All the methods that are virtual are virtual for mocking.
Definition: gflags_hex_bytes.cc:11
shaka::UdpOptions
Options parsed from UDP url string of the form: udp://ip:port[?options].
Definition: udp_options.h:15
shaka::UdpOptions::ParseFromString
static std::unique_ptr< UdpOptions > ParseFromString(base::StringPiece udp_url)
Definition: udp_options.cc:75