• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "platform/base/ip_address.h"
6 
7 #include "gmock/gmock.h"
8 #include "gtest/gtest.h"
9 #include "platform/base/error.h"
10 
11 namespace openscreen {
12 
13 using ::testing::ElementsAreArray;
14 
TEST(IPAddressTest,V4Constructors)15 TEST(IPAddressTest, V4Constructors) {
16   uint8_t bytes[4] = {};
17   IPAddress address1(std::array<uint8_t, 4>{{1, 2, 3, 4}});
18   address1.CopyToV4(bytes);
19   EXPECT_THAT(bytes, ElementsAreArray({1, 2, 3, 4}));
20 
21   uint8_t x[] = {4, 3, 2, 1};
22   IPAddress address2(x);
23   address2.CopyToV4(bytes);
24   EXPECT_THAT(bytes, ElementsAreArray(x));
25 
26   const auto b = address2.bytes();
27   const uint8_t raw_bytes[4]{b[0], b[1], b[2], b[3]};
28   EXPECT_THAT(raw_bytes, ElementsAreArray(x));
29 
30   IPAddress address3(IPAddress::Version::kV4, &x[0]);
31   address3.CopyToV4(bytes);
32   EXPECT_THAT(bytes, ElementsAreArray(x));
33 
34   IPAddress address4(6, 5, 7, 9);
35   address4.CopyToV4(bytes);
36   EXPECT_THAT(bytes, ElementsAreArray({6, 5, 7, 9}));
37 
38   IPAddress address5(address4);
39   address5.CopyToV4(bytes);
40   EXPECT_THAT(bytes, ElementsAreArray({6, 5, 7, 9}));
41 
42   address5 = address1;
43   address5.CopyToV4(bytes);
44   EXPECT_THAT(bytes, ElementsAreArray({1, 2, 3, 4}));
45 }
46 
TEST(IPAddressTest,V4ComparisonAndBoolean)47 TEST(IPAddressTest, V4ComparisonAndBoolean) {
48   IPAddress address1;
49   EXPECT_EQ(address1, address1);
50   EXPECT_FALSE(address1);
51 
52   uint8_t x[] = {4, 3, 2, 1};
53   IPAddress address2(x);
54   EXPECT_NE(address1, address2);
55   EXPECT_TRUE(address2);
56 
57   IPAddress address3(x);
58   EXPECT_EQ(address2, address3);
59   EXPECT_TRUE(address3);
60 
61   address2 = address1;
62   EXPECT_EQ(address1, address2);
63   EXPECT_FALSE(address2);
64 }
65 
TEST(IPAddressTest,V4Parse)66 TEST(IPAddressTest, V4Parse) {
67   uint8_t bytes[4] = {};
68 
69   ErrorOr<IPAddress> address = IPAddress::Parse("192.168.0.1");
70   ASSERT_TRUE(address);
71   address.value().CopyToV4(bytes);
72   EXPECT_THAT(bytes, ElementsAreArray({192, 168, 0, 1}));
73 }
74 
TEST(IPAddressTest,V4ParseFailures)75 TEST(IPAddressTest, V4ParseFailures) {
76   EXPECT_FALSE(IPAddress::Parse("192..0.1"))
77       << "empty value should fail to parse";
78   EXPECT_FALSE(IPAddress::Parse(".192.168.0.1"))
79       << "leading dot should fail to parse";
80   EXPECT_FALSE(IPAddress::Parse(".192.168.1"))
81       << "leading dot should fail to parse";
82   EXPECT_FALSE(IPAddress::Parse("..192.168.0.1"))
83       << "leading dot should fail to parse";
84   EXPECT_FALSE(IPAddress::Parse("..192.1"))
85       << "leading dot should fail to parse";
86   EXPECT_FALSE(IPAddress::Parse("192.168.0.1."))
87       << "trailing dot should fail to parse";
88   EXPECT_FALSE(IPAddress::Parse("192.168.1."))
89       << "trailing dot should fail to parse";
90   EXPECT_FALSE(IPAddress::Parse("192.168.1.."))
91       << "trailing dot should fail to parse";
92   EXPECT_FALSE(IPAddress::Parse("192.168.."))
93       << "trailing dot should fail to parse";
94   EXPECT_FALSE(IPAddress::Parse("192.x3.0.1"))
95       << "non-digit character should fail to parse";
96   EXPECT_FALSE(IPAddress::Parse("192.3.1"))
97       << "too few values should fail to parse";
98   EXPECT_FALSE(IPAddress::Parse("192.3.2.0.1"))
99       << "too many values should fail to parse";
100   EXPECT_FALSE(IPAddress::Parse("1920.3.2.1"))
101       << "value > 255 should fail to parse";
102 }
103 
TEST(IPAddressTest,V6Constructors)104 TEST(IPAddressTest, V6Constructors) {
105   uint8_t bytes[16] = {};
106   IPAddress address1(std::array<uint16_t, 8>{
107       {0x0102, 0x0304, 0x0506, 0x0708, 0x090a, 0x0b0c, 0x0d0e, 0x0f10}});
108   address1.CopyToV6(bytes);
109   EXPECT_THAT(bytes, ElementsAreArray({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
110                                        13, 14, 15, 16}));
111 
112   const uint8_t x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
113   const uint16_t hextets[] = {0x0102, 0x0304, 0x0506, 0x0708,
114                               0x090a, 0x0b0c, 0x0d0e, 0x0f10};
115   IPAddress address2(hextets);
116   address2.CopyToV6(bytes);
117   EXPECT_THAT(bytes, ElementsAreArray(x));
118 
119   IPAddress address3(IPAddress::Version::kV6, &x[0]);
120   address3.CopyToV6(bytes);
121   EXPECT_THAT(bytes, ElementsAreArray(x));
122 
123   IPAddress address4(0x100f, 0x0e0d, 0x0c0b, 0x0a09, 0x0807, 0x0605, 0x0403,
124                      0x0201);
125   address4.CopyToV6(bytes);
126   EXPECT_THAT(bytes, ElementsAreArray({16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
127                                        5, 4, 3, 2, 1}));
128 
129   IPAddress address5(address4);
130   address5.CopyToV6(bytes);
131   EXPECT_THAT(bytes, ElementsAreArray({16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
132                                        5, 4, 3, 2, 1}));
133 }
134 
TEST(IPAddressTest,V6ComparisonAndBoolean)135 TEST(IPAddressTest, V6ComparisonAndBoolean) {
136   IPAddress address1;
137   EXPECT_EQ(address1, address1);
138   EXPECT_FALSE(address1);
139 
140   uint8_t x[] = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
141   IPAddress address2(IPAddress::Version::kV6, x);
142   EXPECT_NE(address1, address2);
143   EXPECT_TRUE(address2);
144 
145   IPAddress address3(IPAddress::Version::kV6, x);
146   EXPECT_EQ(address2, address3);
147   EXPECT_TRUE(address3);
148 
149   address2 = address1;
150   EXPECT_EQ(address1, address2);
151   EXPECT_FALSE(address2);
152 }
153 
TEST(IPAddressTest,V6ParseBasic)154 TEST(IPAddressTest, V6ParseBasic) {
155   uint8_t bytes[16] = {};
156   ErrorOr<IPAddress> address =
157       IPAddress::Parse("abcd:ef01:2345:6789:9876:5432:10FE:DBCA");
158   ASSERT_TRUE(address);
159   address.value().CopyToV6(bytes);
160   EXPECT_THAT(bytes, ElementsAreArray({0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67,
161                                        0x89, 0x98, 0x76, 0x54, 0x32, 0x10, 0xfe,
162                                        0xdb, 0xca}));
163 }
164 
TEST(IPAddressTest,V6ParseDoubleColon)165 TEST(IPAddressTest, V6ParseDoubleColon) {
166   uint8_t bytes[16] = {};
167   ErrorOr<IPAddress> address1 =
168       IPAddress::Parse("abcd:ef01:2345:6789:9876:5432::dbca");
169   ASSERT_TRUE(address1);
170   address1.value().CopyToV6(bytes);
171   EXPECT_THAT(bytes, ElementsAreArray({0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67,
172                                        0x89, 0x98, 0x76, 0x54, 0x32, 0x00, 0x00,
173                                        0xdb, 0xca}));
174   ErrorOr<IPAddress> address2 = IPAddress::Parse("abcd::10fe:dbca");
175   ASSERT_TRUE(address2);
176   address2.value().CopyToV6(bytes);
177   EXPECT_THAT(bytes, ElementsAreArray({0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00,
178                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xfe,
179                                        0xdb, 0xca}));
180 
181   ErrorOr<IPAddress> address3 = IPAddress::Parse("::10fe:dbca");
182   ASSERT_TRUE(address3);
183   address3.value().CopyToV6(bytes);
184   EXPECT_THAT(bytes, ElementsAreArray({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xfe,
186                                        0xdb, 0xca}));
187 
188   ErrorOr<IPAddress> address4 = IPAddress::Parse("10fe:dbca::");
189   ASSERT_TRUE(address4);
190   address4.value().CopyToV6(bytes);
191   EXPECT_THAT(bytes, ElementsAreArray({0x10, 0xfe, 0xdb, 0xca, 0x00, 0x00, 0x00,
192                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193                                        0x00, 0x00}));
194 }
195 
TEST(IPAddressTest,V6SmallValues)196 TEST(IPAddressTest, V6SmallValues) {
197   uint8_t bytes[16] = {};
198   ErrorOr<IPAddress> address1 = IPAddress::Parse("::");
199   ASSERT_TRUE(address1);
200   address1.value().CopyToV6(bytes);
201   EXPECT_THAT(bytes, ElementsAreArray({0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203                                        0x00, 0x00}));
204 
205   ErrorOr<IPAddress> address2 = IPAddress::Parse("::1");
206   ASSERT_TRUE(address2);
207   address2.value().CopyToV6(bytes);
208   EXPECT_THAT(bytes, ElementsAreArray({0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210                                        0x00, 0x01}));
211 
212   ErrorOr<IPAddress> address3 = IPAddress::Parse("::2:1");
213   ASSERT_TRUE(address3);
214   address3.value().CopyToV6(bytes);
215   EXPECT_THAT(bytes, ElementsAreArray({0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
217                                        0x00, 0x01}));
218 }
219 
TEST(IPAddressTest,V6ParseFailures)220 TEST(IPAddressTest, V6ParseFailures) {
221   EXPECT_FALSE(IPAddress::Parse(":abcd::dbca"))
222       << "leading colon should fail to parse";
223   EXPECT_FALSE(IPAddress::Parse("abcd::dbca:"))
224       << "trailing colon should fail to parse";
225   EXPECT_FALSE(IPAddress::Parse("abxd::1234"))
226       << "non-hex digit should fail to parse";
227   EXPECT_FALSE(IPAddress::Parse("abcd:1234"))
228       << "too few values should fail to parse";
229   EXPECT_FALSE(IPAddress::Parse("a:b:c:d:e:f:0:1:2:3:4:5:6:7:8:9:a"))
230       << "too many values should fail to parse";
231   EXPECT_FALSE(IPAddress::Parse("1:2:3:4:5:6:7::8"))
232       << "too many values around double-colon should fail to parse";
233   EXPECT_FALSE(IPAddress::Parse("1:2:3:4:5:6:7:8::"))
234       << "too many values before double-colon should fail to parse";
235   EXPECT_FALSE(IPAddress::Parse("::1:2:3:4:5:6:7:8"))
236       << "too many values after double-colon should fail to parse";
237   EXPECT_FALSE(IPAddress::Parse("abcd1::dbca"))
238       << "value > 0xffff should fail to parse";
239   EXPECT_FALSE(IPAddress::Parse("::abcd::dbca"))
240       << "multiple double colon should fail to parse";
241 
242   EXPECT_FALSE(IPAddress::Parse(":::abcd::dbca"))
243       << "leading triple colon should fail to parse";
244   EXPECT_FALSE(IPAddress::Parse("abcd:::dbca"))
245       << "triple colon should fail to parse";
246   EXPECT_FALSE(IPAddress::Parse("abcd:dbca:::"))
247       << "trailing triple colon should fail to parse";
248 }
249 
TEST(IPAddressTest,V6ParseThreeDigitValue)250 TEST(IPAddressTest, V6ParseThreeDigitValue) {
251   uint8_t bytes[16] = {};
252   ErrorOr<IPAddress> address = IPAddress::Parse("::123");
253   ASSERT_TRUE(address);
254   address.value().CopyToV6(bytes);
255   EXPECT_THAT(bytes, ElementsAreArray({0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257                                        0x01, 0x23}));
258 }
259 
TEST(IPAddressTest,IPEndpointBoolOperator)260 TEST(IPAddressTest, IPEndpointBoolOperator) {
261   IPEndpoint endpoint;
262   ASSERT_FALSE((endpoint));
263   ASSERT_TRUE((IPEndpoint{{192, 168, 0, 1}, 80}));
264   ASSERT_TRUE((IPEndpoint{{192, 168, 0, 1}, 0}));
265   ASSERT_TRUE((IPEndpoint{{}, 80}));
266 }
267 
TEST(IPAddressTest,IPEndpointParse)268 TEST(IPAddressTest, IPEndpointParse) {
269   IPEndpoint expected{IPAddress(std::array<uint8_t, 4>{{1, 2, 3, 4}}), 5678};
270   ErrorOr<IPEndpoint> result = IPEndpoint::Parse("1.2.3.4:5678");
271   ASSERT_TRUE(result.is_value()) << result.error();
272   EXPECT_EQ(expected, result.value());
273 
274   expected = IPEndpoint{
275       IPAddress(std::array<uint16_t, 8>{{0xabcd, 0, 0, 0, 0, 0, 0, 1}}), 99};
276   result = IPEndpoint::Parse("[abcd::1]:99");
277   ASSERT_TRUE(result.is_value()) << result.error();
278   EXPECT_EQ(expected, result.value());
279 
280   expected = IPEndpoint{
281       IPAddress(std::array<uint16_t, 8>{{0, 0, 0, 0, 0, 0, 0, 0}}), 5791};
282   result = IPEndpoint::Parse("[::]:5791");
283   ASSERT_TRUE(result.is_value()) << result.error();
284   EXPECT_EQ(expected, result.value());
285 
286   EXPECT_FALSE(IPEndpoint::Parse(""));              // Empty string.
287   EXPECT_FALSE(IPEndpoint::Parse("beef"));          // Random word.
288   EXPECT_FALSE(IPEndpoint::Parse("localhost:99"));  // We don't do DNS.
289   EXPECT_FALSE(IPEndpoint::Parse(":80"));           // Missing address.
290   EXPECT_FALSE(IPEndpoint::Parse("[]:22"));         // Missing address.
291   EXPECT_FALSE(IPEndpoint::Parse("1.2.3.4"));       // Missing port after IPv4.
292   EXPECT_FALSE(IPEndpoint::Parse("[abcd::1]"));     // Missing port after IPv6.
293   EXPECT_FALSE(IPEndpoint::Parse("abcd::1:8080"));  // Missing square brackets.
294 
295   // No extra whitespace is allowed.
296   EXPECT_FALSE(IPEndpoint::Parse(" 1.2.3.4:5678"));
297   EXPECT_FALSE(IPEndpoint::Parse("1.2.3.4 :5678"));
298   EXPECT_FALSE(IPEndpoint::Parse("1.2.3.4: 5678"));
299   EXPECT_FALSE(IPEndpoint::Parse("1.2.3.4:5678 "));
300   EXPECT_FALSE(IPEndpoint::Parse(" [abcd::1]:99"));
301   EXPECT_FALSE(IPEndpoint::Parse("[abcd::1] :99"));
302   EXPECT_FALSE(IPEndpoint::Parse("[abcd::1]: 99"));
303   EXPECT_FALSE(IPEndpoint::Parse("[abcd::1]:99 "));
304 }
305 
TEST(IPAddressTest,IPAddressComparisons)306 TEST(IPAddressTest, IPAddressComparisons) {
307   const IPAddress kV4Low{192, 168, 0, 1};
308   const IPAddress kV4High{192, 168, 0, 2};
309   const IPAddress kV6Low{0, 0, 0, 0, 0, 0, 0, 1};
310   const IPAddress kV6High{0, 0, 1, 0, 0, 0, 0, 0};
311 
312   EXPECT_TRUE(kV4Low == kV4Low);
313   EXPECT_TRUE(kV4High == kV4High);
314   EXPECT_TRUE(kV6Low == kV6Low);
315   EXPECT_TRUE(kV6High == kV6High);
316   EXPECT_FALSE(kV4Low == kV4High);
317   EXPECT_FALSE(kV4High == kV4Low);
318   EXPECT_FALSE(kV6Low == kV6High);
319   EXPECT_FALSE(kV6High == kV6Low);
320 
321   EXPECT_FALSE(kV4Low != kV4Low);
322   EXPECT_FALSE(kV4High != kV4High);
323   EXPECT_FALSE(kV6Low != kV6Low);
324   EXPECT_FALSE(kV6High != kV6High);
325   EXPECT_TRUE(kV4Low != kV4High);
326   EXPECT_TRUE(kV4High != kV4Low);
327   EXPECT_TRUE(kV6Low != kV6High);
328   EXPECT_TRUE(kV6High != kV6Low);
329 
330   EXPECT_TRUE(kV4Low < kV4High);
331   EXPECT_TRUE(kV4High < kV6Low);
332   EXPECT_TRUE(kV6Low < kV6High);
333   EXPECT_FALSE(kV6High < kV6Low);
334   EXPECT_FALSE(kV6Low < kV4High);
335   EXPECT_FALSE(kV4High < kV4Low);
336 
337   EXPECT_FALSE(kV4Low > kV4High);
338   EXPECT_FALSE(kV4High > kV6Low);
339   EXPECT_FALSE(kV6Low > kV6High);
340   EXPECT_TRUE(kV6High > kV6Low);
341   EXPECT_TRUE(kV6Low > kV4High);
342   EXPECT_TRUE(kV4High > kV4Low);
343 
344   EXPECT_TRUE(kV4Low <= kV4High);
345   EXPECT_TRUE(kV4High <= kV6Low);
346   EXPECT_TRUE(kV6Low <= kV6High);
347   EXPECT_TRUE(kV4Low <= kV4Low);
348   EXPECT_TRUE(kV4High <= kV4High);
349   EXPECT_TRUE(kV6Low <= kV6Low);
350   EXPECT_TRUE(kV6High <= kV6High);
351   EXPECT_FALSE(kV6High <= kV6Low);
352   EXPECT_FALSE(kV6Low <= kV4High);
353   EXPECT_FALSE(kV4High <= kV4Low);
354 
355   EXPECT_FALSE(kV4Low >= kV4High);
356   EXPECT_FALSE(kV4High >= kV6Low);
357   EXPECT_FALSE(kV6Low >= kV6High);
358   EXPECT_TRUE(kV4Low >= kV4Low);
359   EXPECT_TRUE(kV4High >= kV4High);
360   EXPECT_TRUE(kV6Low >= kV6Low);
361   EXPECT_TRUE(kV6High >= kV6High);
362   EXPECT_TRUE(kV6High >= kV6Low);
363   EXPECT_TRUE(kV6Low >= kV4High);
364   EXPECT_TRUE(kV4High >= kV4Low);
365 }
366 
TEST(IPAddressTest,IPEndpointComparisons)367 TEST(IPAddressTest, IPEndpointComparisons) {
368   const IPEndpoint kV4LowHighPort{{192, 168, 0, 1}, 1000};
369   const IPEndpoint kV4LowLowPort{{192, 168, 0, 1}, 1};
370   const IPEndpoint kV4High{{192, 168, 0, 2}, 22};
371   const IPEndpoint kV6Low{{0, 0, 0, 0, 0, 0, 0, 1}, 22};
372   const IPEndpoint kV6High{{0, 0, 1, 0, 0, 0, 0, 0}, 22};
373 
374   EXPECT_TRUE(kV4LowHighPort == kV4LowHighPort);
375   EXPECT_TRUE(kV4High == kV4High);
376   EXPECT_TRUE(kV6Low == kV6Low);
377   EXPECT_TRUE(kV6High == kV6High);
378 
379   EXPECT_TRUE(kV4LowLowPort != kV4LowHighPort);
380   EXPECT_TRUE(kV4LowLowPort != kV4High);
381   EXPECT_TRUE(kV4High != kV6Low);
382   EXPECT_TRUE(kV6Low != kV6High);
383 
384   EXPECT_TRUE(kV4LowLowPort < kV4LowHighPort);
385   EXPECT_TRUE(kV4LowLowPort < kV4High);
386   EXPECT_TRUE(kV4High < kV6Low);
387   EXPECT_TRUE(kV6Low < kV6High);
388 
389   EXPECT_TRUE(kV4LowHighPort > kV4LowLowPort);
390   EXPECT_TRUE(kV4High > kV4LowLowPort);
391   EXPECT_TRUE(kV6Low > kV4High);
392   EXPECT_TRUE(kV6High > kV6Low);
393 
394   EXPECT_TRUE(kV4LowLowPort <= kV4LowHighPort);
395   EXPECT_TRUE(kV4LowLowPort <= kV4High);
396   EXPECT_TRUE(kV4High <= kV6Low);
397   EXPECT_TRUE(kV6Low <= kV6High);
398   EXPECT_TRUE(kV4LowLowPort <= kV4LowHighPort);
399   EXPECT_TRUE(kV4LowLowPort <= kV4High);
400   EXPECT_TRUE(kV4High <= kV6Low);
401   EXPECT_TRUE(kV6Low <= kV6High);
402 
403   EXPECT_FALSE(kV4LowLowPort >= kV4LowHighPort);
404   EXPECT_FALSE(kV4LowLowPort >= kV4High);
405   EXPECT_FALSE(kV4High >= kV6Low);
406   EXPECT_FALSE(kV6Low >= kV6High);
407   EXPECT_TRUE(kV4LowHighPort >= kV4LowLowPort);
408   EXPECT_TRUE(kV4High >= kV4LowLowPort);
409   EXPECT_TRUE(kV6Low >= kV4High);
410   EXPECT_TRUE(kV6High >= kV6Low);
411   EXPECT_TRUE(kV4LowHighPort >= kV4LowLowPort);
412   EXPECT_TRUE(kV4High >= kV4LowLowPort);
413   EXPECT_TRUE(kV6Low >= kV4High);
414   EXPECT_TRUE(kV6High >= kV6Low);
415 }
416 
TEST(IPAddressTest,OstreamOperatorForIPv4)417 TEST(IPAddressTest, OstreamOperatorForIPv4) {
418   std::ostringstream oss;
419   oss << IPAddress{192, 168, 1, 2};
420   EXPECT_EQ("192.168.1.2", oss.str());
421 
422   oss.str("");
423   oss << IPAddress{192, 168, 0, 2};
424   EXPECT_EQ("192.168.0.2", oss.str());
425 
426   oss.str("");
427   oss << IPAddress{23, 45, 67, 89};
428   EXPECT_EQ("23.45.67.89", oss.str());
429 }
430 
431 }  // namespace openscreen
432