1
2
3
4
5
6
7 package net
8
9 import (
10 "os"
11 )
12
13 var supportsIPv6, supportsIPv4map = probeIPv6Stack()
14
15 func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) {
16 if filter == anyaddr {
17
18
19
20
21
22 addr = firstSupportedAddr(ipv4only, addrs)
23 if addr == nil {
24 addr = firstSupportedAddr(anyaddr, addrs)
25 }
26 } else {
27 addr = firstSupportedAddr(filter, addrs)
28 }
29 return
30 }
31
32 func firstSupportedAddr(filter func(IP) IP, addrs []string) IP {
33 for _, s := range addrs {
34 if addr := filter(ParseIP(s)); addr != nil {
35 return addr
36 }
37 }
38 return nil
39 }
40
41 func anyaddr(x IP) IP {
42 if x4 := x.To4(); x4 != nil {
43 return x4
44 }
45 if supportsIPv6 {
46 return x
47 }
48 return nil
49 }
50
51 func ipv4only(x IP) IP { return x.To4() }
52
53 func ipv6only(x IP) IP {
54
55
56 if len(x) == IPv6len && x.To4() == nil && supportsIPv6 {
57 return x
58 }
59 return nil
60 }
61
62 type InvalidAddrError string
63
64 func (e InvalidAddrError) String() string { return string(e) }
65 func (e InvalidAddrError) Timeout() bool { return false }
66 func (e InvalidAddrError) Temporary() bool { return false }
67
68
69
70
71 func SplitHostPort(hostport string) (host, port string, err os.Error) {
72
73 i := last(hostport, ':')
74 if i < 0 {
75 err = &AddrError{"missing port in address", hostport}
76 return
77 }
78
79 host, port = hostport[0:i], hostport[i+1:]
80
81
82 if len(host) > 0 && host[0] == '[' && host[len(host)-1] == ']' {
83 host = host[1 : len(host)-1]
84 } else {
85
86 if byteIndex(host, ':') >= 0 {
87 err = &AddrError{"too many colons in address", hostport}
88 return
89 }
90 }
91 return
92 }
93
94
95
96 func JoinHostPort(host, port string) string {
97
98 if byteIndex(host, ':') >= 0 {
99 return "[" + host + "]:" + port
100 }
101 return host + ":" + port
102 }
103
104
105 func hostPortToIP(net, hostport string) (ip IP, iport int, err os.Error) {
106 var (
107 addr IP
108 p, i int
109 ok bool
110 )
111 host, port, err := SplitHostPort(hostport)
112 if err != nil {
113 goto Error
114 }
115
116 if host != "" {
117
118 addr = ParseIP(host)
119 if addr == nil {
120 filter := anyaddr
121 if net != "" && net[len(net)-1] == '4' {
122 filter = ipv4only
123 }
124 if net != "" && net[len(net)-1] == '6' {
125 filter = ipv6only
126 }
127
128 addrs, err1 := LookupHost(host)
129 if err1 != nil {
130 err = err1
131 goto Error
132 }
133 addr = firstFavoriteAddr(filter, addrs)
134 if addr == nil {
135
136 err = &AddrError{"LookupHost returned no suitable address", addrs[0]}
137 goto Error
138 }
139 }
140 }
141
142 p, i, ok = dtoi(port, 0)
143 if !ok || i != len(port) {
144 p, err = LookupPort(net, port)
145 if err != nil {
146 goto Error
147 }
148 }
149 if p < 0 || p > 0xFFFF {
150 err = &AddrError{"invalid port", port}
151 goto Error
152 }
153
154 return addr, p, nil
155
156 Error:
157 return nil, 0, err
158 }