OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / wire / netaddress.go
1 // Copyright (c) 2013-2015 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
4
5 package wire
6
7 import (
8         "encoding/binary"
9         "io"
10         "net"
11         "time"
12 )
13
14 // maxNetAddressPayload returns the max payload size for a bitcoin NetAddress
15 // based on the protocol version.
16 func maxNetAddressPayload(pver uint32) uint32 {
17         // Services 8 bytes + ip 16 bytes + port 2 bytes.
18         plen := uint32(26)
19
20         // NetAddressTimeVersion added a timestamp field.
21         if pver >= NetAddressTimeVersion {
22                 // Timestamp 4 bytes.
23                 plen += 4
24         }
25
26         return plen
27 }
28
29 // NetAddress defines information about a peer on the network including the time
30 // it was last seen, the services it supports, its IP address, and port.
31 type NetAddress struct {
32         // Last time the address was seen.  This is, unfortunately, encoded as a
33         // uint32 on the wire and therefore is limited to 2106.  This field is
34         // not present in the bitcoin version message (MsgVersion) nor was it
35         // added until protocol version >= NetAddressTimeVersion.
36         Timestamp time.Time
37
38         // Bitfield which identifies the services supported by the address.
39         Services ServiceFlag
40
41         // IP address of the peer.
42         IP net.IP
43
44         // Port the peer is using.  This is encoded in big endian on the wire
45         // which differs from most everything else.
46         Port uint16
47 }
48
49 // HasService returns whether the specified service is supported by the address.
50 func (na *NetAddress) HasService(service ServiceFlag) bool {
51         return na.Services&service == service
52 }
53
54 // AddService adds service as a supported service by the peer generating the
55 // message.
56 func (na *NetAddress) AddService(service ServiceFlag) {
57         na.Services |= service
58 }
59
60 // NewNetAddressIPPort returns a new NetAddress using the provided IP, port, and
61 // supported services with defaults for the remaining fields.
62 func NewNetAddressIPPort(ip net.IP, port uint16, services ServiceFlag) *NetAddress {
63         return NewNetAddressTimestamp(time.Now(), services, ip, port)
64 }
65
66 // NewNetAddressTimestamp returns a new NetAddress using the provided
67 // timestamp, IP, port, and supported services. The timestamp is rounded to
68 // single second precision.
69 func NewNetAddressTimestamp(
70         timestamp time.Time, services ServiceFlag, ip net.IP, port uint16) *NetAddress {
71         // Limit the timestamp to one second precision since the protocol
72         // doesn't support better.
73         na := NetAddress{
74                 Timestamp: time.Unix(timestamp.Unix(), 0),
75                 Services:  services,
76                 IP:        ip,
77                 Port:      port,
78         }
79         return &na
80 }
81
82 // NewNetAddress returns a new NetAddress using the provided TCP address and
83 // supported services with defaults for the remaining fields.
84 func NewNetAddress(addr *net.TCPAddr, services ServiceFlag) *NetAddress {
85         return NewNetAddressIPPort(addr.IP, uint16(addr.Port), services)
86 }
87
88 // readNetAddress reads an encoded NetAddress from r depending on the protocol
89 // version and whether or not the timestamp is included per ts.  Some messages
90 // like version do not include the timestamp.
91 func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error {
92         var ip [16]byte
93
94         // NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will
95         // stop working somewhere around 2106.  Also timestamp wasn't added until
96         // protocol version >= NetAddressTimeVersion
97         if ts && pver >= NetAddressTimeVersion {
98                 err := readElement(r, (*uint32Time)(&na.Timestamp))
99                 if err != nil {
100                         return err
101                 }
102         }
103
104         err := readElements(r, &na.Services, &ip)
105         if err != nil {
106                 return err
107         }
108         // Sigh.  Bitcoin protocol mixes little and big endian.
109         port, err := binarySerializer.Uint16(r, bigEndian)
110         if err != nil {
111                 return err
112         }
113
114         *na = NetAddress{
115                 Timestamp: na.Timestamp,
116                 Services:  na.Services,
117                 IP:        net.IP(ip[:]),
118                 Port:      port,
119         }
120         return nil
121 }
122
123 // writeNetAddress serializes a NetAddress to w depending on the protocol
124 // version and whether or not the timestamp is included per ts.  Some messages
125 // like version do not include the timestamp.
126 func writeNetAddress(w io.Writer, pver uint32, na *NetAddress, ts bool) error {
127         // NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will
128         // stop working somewhere around 2106.  Also timestamp wasn't added until
129         // until protocol version >= NetAddressTimeVersion.
130         if ts && pver >= NetAddressTimeVersion {
131                 err := writeElement(w, uint32(na.Timestamp.Unix()))
132                 if err != nil {
133                         return err
134                 }
135         }
136
137         // Ensure to always write 16 bytes even if the ip is nil.
138         var ip [16]byte
139         if na.IP != nil {
140                 copy(ip[:], na.IP.To16())
141         }
142         err := writeElements(w, na.Services, ip)
143         if err != nil {
144                 return err
145         }
146
147         // Sigh.  Bitcoin protocol mixes little and big endian.
148         return binary.Write(w, bigEndian, na.Port)
149 }