OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / vendor / github.com / multiformats / go-multiaddr / transcoders.go
1 package multiaddr
2
3 import (
4         "bytes"
5         "encoding/base32"
6         "encoding/base64"
7         "encoding/binary"
8         "fmt"
9         "net"
10         "strconv"
11         "strings"
12
13         mh "github.com/multiformats/go-multihash"
14 )
15
16 type Transcoder interface {
17         StringToBytes(string) ([]byte, error)
18         BytesToString([]byte) (string, error)
19         ValidateBytes([]byte) error
20 }
21
22 func NewTranscoderFromFunctions(
23         s2b func(string) ([]byte, error),
24         b2s func([]byte) (string, error),
25         val func([]byte) error,
26 ) Transcoder {
27         return twrp{s2b, b2s, val}
28 }
29
30 type twrp struct {
31         strtobyte func(string) ([]byte, error)
32         bytetostr func([]byte) (string, error)
33         validbyte func([]byte) error
34 }
35
36 func (t twrp) StringToBytes(s string) ([]byte, error) {
37         return t.strtobyte(s)
38 }
39 func (t twrp) BytesToString(b []byte) (string, error) {
40         return t.bytetostr(b)
41 }
42
43 func (t twrp) ValidateBytes(b []byte) error {
44         if t.validbyte == nil {
45                 return nil
46         }
47         return t.validbyte(b)
48 }
49
50 var TranscoderIP4 = NewTranscoderFromFunctions(ip4StB, ip4BtS, nil)
51 var TranscoderIP6 = NewTranscoderFromFunctions(ip6StB, ip6BtS, nil)
52 var TranscoderIP6Zone = NewTranscoderFromFunctions(ip6zoneStB, ip6zoneBtS, ip6zoneVal)
53
54 func ip4StB(s string) ([]byte, error) {
55         i := net.ParseIP(s).To4()
56         if i == nil {
57                 return nil, fmt.Errorf("failed to parse ip4 addr: %s", s)
58         }
59         return i, nil
60 }
61
62 func ip6zoneStB(s string) ([]byte, error) {
63         if len(s) == 0 {
64                 return nil, fmt.Errorf("empty ip6zone")
65         }
66         return []byte(s), nil
67 }
68
69 func ip6zoneBtS(b []byte) (string, error) {
70         if len(b) == 0 {
71                 return "", fmt.Errorf("invalid length (should be > 0)")
72         }
73         return string(b), nil
74 }
75
76 func ip6zoneVal(b []byte) error {
77         if len(b) == 0 {
78                 return fmt.Errorf("invalid length (should be > 0)")
79         }
80         // Not supported as this would break multiaddrs.
81         if bytes.IndexByte(b, '/') >= 0 {
82                 return fmt.Errorf("IPv6 zone ID contains '/': %s", string(b))
83         }
84         return nil
85 }
86
87 func ip6StB(s string) ([]byte, error) {
88         i := net.ParseIP(s).To16()
89         if i == nil {
90                 return nil, fmt.Errorf("failed to parse ip6 addr: %s", s)
91         }
92         return i, nil
93 }
94
95 func ip6BtS(b []byte) (string, error) {
96         ip := net.IP(b)
97         if ip4 := ip.To4(); ip4 != nil {
98                 // Go fails to prepend the `::ffff:` part.
99                 return "::ffff:" + ip4.String(), nil
100         }
101         return ip.String(), nil
102 }
103
104 func ip4BtS(b []byte) (string, error) {
105         return net.IP(b).String(), nil
106 }
107
108 var TranscoderPort = NewTranscoderFromFunctions(portStB, portBtS, nil)
109
110 func portStB(s string) ([]byte, error) {
111         i, err := strconv.Atoi(s)
112         if err != nil {
113                 return nil, fmt.Errorf("failed to parse port addr: %s", err)
114         }
115         if i >= 65536 {
116                 return nil, fmt.Errorf("failed to parse port addr: %s", "greater than 65536")
117         }
118         b := make([]byte, 2)
119         binary.BigEndian.PutUint16(b, uint16(i))
120         return b, nil
121 }
122
123 func portBtS(b []byte) (string, error) {
124         i := binary.BigEndian.Uint16(b)
125         return strconv.Itoa(int(i)), nil
126 }
127
128 var TranscoderOnion = NewTranscoderFromFunctions(onionStB, onionBtS, nil)
129
130 func onionStB(s string) ([]byte, error) {
131         addr := strings.Split(s, ":")
132         if len(addr) != 2 {
133                 return nil, fmt.Errorf("failed to parse onion addr: %s does not contain a port number.", s)
134         }
135
136         // onion address without the ".onion" substring
137         if len(addr[0]) != 16 {
138                 return nil, fmt.Errorf("failed to parse onion addr: %s not a Tor onion address.", s)
139         }
140         onionHostBytes, err := base32.StdEncoding.DecodeString(strings.ToUpper(addr[0]))
141         if err != nil {
142                 return nil, fmt.Errorf("failed to decode base32 onion addr: %s %s", s, err)
143         }
144
145         // onion port number
146         i, err := strconv.Atoi(addr[1])
147         if err != nil {
148                 return nil, fmt.Errorf("failed to parse onion addr: %s", err)
149         }
150         if i >= 65536 {
151                 return nil, fmt.Errorf("failed to parse onion addr: %s", "port greater than 65536")
152         }
153         if i < 1 {
154                 return nil, fmt.Errorf("failed to parse onion addr: %s", "port less than 1")
155         }
156
157         onionPortBytes := make([]byte, 2)
158         binary.BigEndian.PutUint16(onionPortBytes, uint16(i))
159         bytes := []byte{}
160         bytes = append(bytes, onionHostBytes...)
161         bytes = append(bytes, onionPortBytes...)
162         return bytes, nil
163 }
164
165 func onionBtS(b []byte) (string, error) {
166         addr := strings.ToLower(base32.StdEncoding.EncodeToString(b[0:10]))
167         port := binary.BigEndian.Uint16(b[10:12])
168         return addr + ":" + strconv.Itoa(int(port)), nil
169 }
170
171 var TranscoderOnion3 = NewTranscoderFromFunctions(onion3StB, onion3BtS, nil)
172
173 func onion3StB(s string) ([]byte, error) {
174         addr := strings.Split(s, ":")
175         if len(addr) != 2 {
176                 return nil, fmt.Errorf("failed to parse onion addr: %s does not contain a port number.", s)
177         }
178
179         // onion address without the ".onion" substring
180         if len(addr[0]) != 56 {
181                 return nil, fmt.Errorf("failed to parse onion addr: %s not a Tor onionv3 address. len == %d", s, len(addr[0]))
182         }
183         onionHostBytes, err := base32.StdEncoding.DecodeString(strings.ToUpper(addr[0]))
184         if err != nil {
185                 return nil, fmt.Errorf("failed to decode base32 onion addr: %s %s", s, err)
186         }
187
188         // onion port number
189         i, err := strconv.Atoi(addr[1])
190         if err != nil {
191                 return nil, fmt.Errorf("failed to parse onion addr: %s", err)
192         }
193         if i >= 65536 {
194                 return nil, fmt.Errorf("failed to parse onion addr: %s", "port greater than 65536")
195         }
196         if i < 1 {
197                 return nil, fmt.Errorf("failed to parse onion addr: %s", "port less than 1")
198         }
199
200         onionPortBytes := make([]byte, 2)
201         binary.BigEndian.PutUint16(onionPortBytes, uint16(i))
202         bytes := []byte{}
203         bytes = append(bytes, onionHostBytes[0:35]...)
204         bytes = append(bytes, onionPortBytes...)
205         return bytes, nil
206 }
207
208 func onion3BtS(b []byte) (string, error) {
209         addr := strings.ToLower(base32.StdEncoding.EncodeToString(b[0:35]))
210         port := binary.BigEndian.Uint16(b[35:37])
211         str := addr + ":" + strconv.Itoa(int(port))
212         return str, nil
213 }
214
215 var TranscoderGarlic64 = NewTranscoderFromFunctions(garlic64StB, garlic64BtS, garlicValidate)
216
217 // i2p uses an alternate character set for base64 addresses. This returns an appropriate encoder.
218 var garlicBase64Encoding = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~")
219
220 func garlic64StB(s string) ([]byte, error) {
221         // i2p base64 address
222         if len(s) < 516 || len(s) > 616 {
223                 return nil, fmt.Errorf("failed to parse garlic addr: %s not an i2p base64 address. len: %d\n", s, len(s))
224         }
225         garlicHostBytes, err := garlicBase64Encoding.DecodeString(s)
226         if err != nil {
227                 return nil, fmt.Errorf("failed to decode base64 i2p addr: %s %s", s, err)
228         }
229
230         return garlicHostBytes, nil
231 }
232
233 func garlic64BtS(b []byte) (string, error) {
234         if len(b) < 386 {
235                 return "", fmt.Errorf("failed to validate garlic addr: %s not an i2p base64 address. len: %d\n", b, len(b))
236         }
237         addr := garlicBase64Encoding.EncodeToString(b)
238         return addr, nil
239 }
240
241 func garlicValidate(b []byte) error {
242         if len(b) < 386 {
243                 return fmt.Errorf("failed to validate garlic addr: %s not an i2p base64 address. len: %d\n", b, len(b))
244         }
245         return nil
246 }
247
248 var TranscoderP2P = NewTranscoderFromFunctions(p2pStB, p2pBtS, p2pVal)
249
250 func p2pStB(s string) ([]byte, error) {
251         // the address is a varint prefixed multihash string representation
252         m, err := mh.FromB58String(s)
253         if err != nil {
254                 return nil, fmt.Errorf("failed to parse p2p addr: %s %s", s, err)
255         }
256         return m, nil
257 }
258
259 func p2pVal(b []byte) error {
260         _, err := mh.Cast(b)
261         return err
262 }
263
264 func p2pBtS(b []byte) (string, error) {
265         m, err := mh.Cast(b)
266         if err != nil {
267                 return "", err
268         }
269         return m.B58String(), nil
270 }
271
272 var TranscoderUnix = NewTranscoderFromFunctions(unixStB, unixBtS, nil)
273
274 func unixStB(s string) ([]byte, error) {
275         return []byte(s), nil
276 }
277
278 func unixBtS(b []byte) (string, error) {
279         return string(b), nil
280 }