3 * Copyright 2015 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <grpc/support/port_platform.h>
21 #include "src/core/lib/gprpp/host_port.h"
25 #include <grpc/support/alloc.h>
26 #include <grpc/support/log.h>
27 #include <grpc/support/string_util.h>
29 #include "src/core/lib/gpr/string.h"
30 #include "src/core/lib/gprpp/string_view.h"
33 int JoinHostPort(UniquePtr<char>* out, const char* host, int port) {
36 if (host[0] != '[' && strchr(host, ':') != nullptr) {
37 /* IPv6 literals must be enclosed in brackets. */
38 ret = gpr_asprintf(&tmp, "[%s]:%d", host, port);
40 /* Ordinary non-bracketed host:port. */
41 ret = gpr_asprintf(&tmp, "%s:%d", host, port);
48 bool DoSplitHostPort(StringView name, StringView* host, StringView* port,
52 /* Parse a bracketed host, typically an IPv6 literal. */
53 const size_t rbracket = name.find(']', 1);
54 if (rbracket == grpc_core::StringView::npos) {
58 if (rbracket == name.size() - 1) {
61 } else if (name[rbracket + 1] == ':') {
63 *port = name.substr(rbracket + 2, name.size() - rbracket - 2);
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. */
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);
85 /* 0 or 2+ colons. Bare hostname or IPv6 litearal. */
94 bool SplitHostPort(StringView name, StringView* host, StringView* port) {
96 return DoSplitHostPort(name, host, port, &unused);
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;
106 const bool ret = DoSplitHostPort(name, &host_view, &port_view, &has_port);
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();
113 *port = port_view.dup();
118 } // namespace grpc_core