Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / src / core / lib / gprpp / host_port.cc
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/gprpp/host_port.h"
22
23 #include <string.h>
24
25 #include <grpc/support/alloc.h>
26 #include <grpc/support/log.h>
27 #include <grpc/support/string_util.h>
28
29 #include "src/core/lib/gpr/string.h"
30 #include "src/core/lib/gprpp/string_view.h"
31
32 namespace grpc_core {
33 int JoinHostPort(UniquePtr<char>* out, const char* host, int port) {
34   char* tmp;
35   int ret;
36   if (host[0] != '[' && strchr(host, ':') != nullptr) {
37     /* IPv6 literals must be enclosed in brackets. */
38     ret = gpr_asprintf(&tmp, "[%s]:%d", host, port);
39   } else {
40     /* Ordinary non-bracketed host:port. */
41     ret = gpr_asprintf(&tmp, "%s:%d", host, port);
42   }
43   out->reset(tmp);
44   return ret;
45 }
46
47 namespace {
48 bool DoSplitHostPort(StringView name, StringView* host, StringView* port,
49                      bool* has_port) {
50   *has_port = false;
51   if (name[0] == '[') {
52     /* Parse a bracketed host, typically an IPv6 literal. */
53     const size_t rbracket = name.find(']', 1);
54     if (rbracket == grpc_core::StringView::npos) {
55       /* Unmatched [ */
56       return false;
57     }
58     if (rbracket == name.size() - 1) {
59       /* ]<end> */
60       port->clear();
61     } else if (name[rbracket + 1] == ':') {
62       /* ]:<port?> */
63       *port = name.substr(rbracket + 2, name.size() - rbracket - 2);
64       *has_port = true;
65     } else {
66       /* ]<invalid> */
67       return false;
68     }
69     *host = name.substr(1, rbracket - 1);
70     if (host->find(':') == grpc_core::StringView::npos) {
71       /* Require all bracketed hosts to contain a colon, because a hostname or
72          IPv4 address should never use brackets. */
73       host->clear();
74       return false;
75     }
76   } else {
77     size_t colon = name.find(':');
78     if (colon != grpc_core::StringView::npos &&
79         name.find(':', colon + 1) == grpc_core::StringView::npos) {
80       /* Exactly 1 colon.  Split into host:port. */
81       *host = name.substr(0, colon);
82       *port = name.substr(colon + 1, name.size() - colon - 1);
83       *has_port = true;
84     } else {
85       /* 0 or 2+ colons.  Bare hostname or IPv6 litearal. */
86       *host = name;
87       port->clear();
88     }
89   }
90   return true;
91 }
92 }  // namespace
93
94 bool SplitHostPort(StringView name, StringView* host, StringView* port) {
95   bool unused;
96   return DoSplitHostPort(name, host, port, &unused);
97 }
98
99 bool SplitHostPort(StringView name, UniquePtr<char>* host,
100                    UniquePtr<char>* port) {
101   GPR_DEBUG_ASSERT(host != nullptr && *host == nullptr);
102   GPR_DEBUG_ASSERT(port != nullptr && *port == nullptr);
103   StringView host_view;
104   StringView port_view;
105   bool has_port;
106   const bool ret = DoSplitHostPort(name, &host_view, &port_view, &has_port);
107   if (ret) {
108     // We always set the host, but port is set only when DoSplitHostPort find a
109     // port in the string, to remain backward compatible with the old
110     // gpr_split_host_port API.
111     *host = host_view.dup();
112     if (has_port) {
113       *port = port_view.dup();
114     }
115   }
116   return ret;
117 }
118 }  // namespace grpc_core