98 строки
2,8 КиБ
Go
98 строки
2,8 КиБ
Go
// The following is copied from Go 1.16 official implementation.
|
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package net
|
|
|
|
import "internal/bytealg"
|
|
|
|
// SplitHostPort splits a network address of the form "host:port",
|
|
// "host%zone:port", "[host]:port" or "[host%zone]:port" into host or
|
|
// host%zone and port.
|
|
//
|
|
// A literal IPv6 address in hostport must be enclosed in square
|
|
// brackets, as in "[::1]:80", "[::1%lo0]:80".
|
|
//
|
|
// See func Dial for a description of the hostport parameter, and host
|
|
// and port results.
|
|
func SplitHostPort(hostport string) (host, port string, err error) {
|
|
const (
|
|
missingPort = "missing port in address"
|
|
tooManyColons = "too many colons in address"
|
|
)
|
|
addrErr := func(addr, why string) (host, port string, err error) {
|
|
return "", "", &AddrError{Err: why, Addr: addr}
|
|
}
|
|
j, k := 0, 0
|
|
|
|
// The port starts after the last colon.
|
|
i := last(hostport, ':')
|
|
if i < 0 {
|
|
return addrErr(hostport, missingPort)
|
|
}
|
|
|
|
if hostport[0] == '[' {
|
|
// Expect the first ']' just before the last ':'.
|
|
end := bytealg.IndexByteString(hostport, ']')
|
|
if end < 0 {
|
|
return addrErr(hostport, "missing ']' in address")
|
|
}
|
|
switch end + 1 {
|
|
case len(hostport):
|
|
// There can't be a ':' behind the ']' now.
|
|
return addrErr(hostport, missingPort)
|
|
case i:
|
|
// The expected result.
|
|
default:
|
|
// Either ']' isn't followed by a colon, or it is
|
|
// followed by a colon that is not the last one.
|
|
if hostport[end+1] == ':' {
|
|
return addrErr(hostport, tooManyColons)
|
|
}
|
|
return addrErr(hostport, missingPort)
|
|
}
|
|
host = hostport[1:end]
|
|
j, k = 1, end+1 // there can't be a '[' resp. ']' before these positions
|
|
} else {
|
|
host = hostport[:i]
|
|
if bytealg.IndexByteString(host, ':') >= 0 {
|
|
return addrErr(hostport, tooManyColons)
|
|
}
|
|
}
|
|
if bytealg.IndexByteString(hostport[j:], '[') >= 0 {
|
|
return addrErr(hostport, "unexpected '[' in address")
|
|
}
|
|
if bytealg.IndexByteString(hostport[k:], ']') >= 0 {
|
|
return addrErr(hostport, "unexpected ']' in address")
|
|
}
|
|
|
|
port = hostport[i+1:]
|
|
return host, port, nil
|
|
}
|
|
|
|
func splitHostZone(s string) (host, zone string) {
|
|
// The IPv6 scoped addressing zone identifier starts after the
|
|
// last percent sign.
|
|
if i := last(s, '%'); i > 0 {
|
|
host, zone = s[:i], s[i+1:]
|
|
} else {
|
|
host = s
|
|
}
|
|
return
|
|
}
|
|
|
|
// JoinHostPort combines host and port into a network address of the
|
|
// form "host:port". If host contains a colon, as found in literal
|
|
// IPv6 addresses, then JoinHostPort returns "[host]:port".
|
|
//
|
|
// See func Dial for a description of the host and port parameters.
|
|
func JoinHostPort(host, port string) string {
|
|
// We assume that host is a literal IPv6 address if host has
|
|
// colons.
|
|
if bytealg.IndexByteString(host, ':') >= 0 {
|
|
return "[" + host + "]:" + port
|
|
}
|
|
return host + ":" + port
|
|
}
|