diff options
Diffstat (limited to 'src/gnunet/util/address.go')
-rw-r--r-- | src/gnunet/util/address.go | 141 |
1 files changed, 123 insertions, 18 deletions
diff --git a/src/gnunet/util/address.go b/src/gnunet/util/address.go index d272742..106e671 100644 --- a/src/gnunet/util/address.go +++ b/src/gnunet/util/address.go | |||
@@ -19,44 +19,81 @@ | |||
19 | package util | 19 | package util |
20 | 20 | ||
21 | import ( | 21 | import ( |
22 | "encoding/hex" | 22 | "bytes" |
23 | "fmt" | 23 | "fmt" |
24 | "net" | 24 | "net" |
25 | "strings" | ||
25 | ) | 26 | ) |
26 | 27 | ||
27 | // Address specifies how a peer is reachable on the network. | 28 | // Address specifies how a peer is reachable on the network. |
28 | type Address struct { | 29 | type Address struct { |
29 | Transport string // transport protocol | 30 | Netw string `` // network protocol |
30 | Options uint32 `order:"big"` // address options | 31 | Options uint32 `order:"big"` // address options |
31 | Address []byte `size:"*"` // address data (protocol-dependent) | 32 | Expires AbsoluteTime `` // expiration date for address |
33 | Address []byte `size:"*"` // address data (protocol-dependent) | ||
32 | } | 34 | } |
33 | 35 | ||
34 | // NewAddress returns a new Address for the given transport and specs | 36 | // NewAddress returns a new Address for the given transport and specs |
35 | func NewAddress(transport string, addr []byte) *Address { | 37 | func NewAddress(transport string, addr []byte) *Address { |
36 | a := &Address{ | 38 | return &Address{ |
37 | Transport: transport, | 39 | Netw: transport, |
38 | Options: 0, | 40 | Options: 0, |
39 | Address: make([]byte, len(addr)), | 41 | Address: Clone(addr), |
42 | Expires: AbsoluteTimeNever(), | ||
40 | } | 43 | } |
41 | copy(a.Address, addr) | ||
42 | return a | ||
43 | } | 44 | } |
44 | 45 | ||
46 | func NewAddressWrap(addr net.Addr) *Address { | ||
47 | return &Address{ | ||
48 | Netw: addr.Network(), | ||
49 | Options: 0, | ||
50 | Address: []byte(addr.String()), | ||
51 | Expires: AbsoluteTimeNever(), | ||
52 | } | ||
53 | } | ||
54 | |||
55 | // ParseAddress translates a GNUnet address string like | ||
56 | // "r5n+ip+udp://1.2.3.4:6789" or "gnunet+tcp://12.3.4.5/". | ||
57 | // It can also handle standard strings like "udp:127.0.0.1:6735". | ||
58 | func ParseAddress(s string) (addr *Address, err error) { | ||
59 | p := strings.SplitN(s, ":", 2) | ||
60 | if len(p) != 2 { | ||
61 | err = fmt.Errorf("invalid address format: '%s'", s) | ||
62 | return | ||
63 | } | ||
64 | addr = NewAddress(p[0], []byte(strings.Trim(p[1], "/"))) | ||
65 | return | ||
66 | } | ||
67 | |||
68 | // Equals return true if two addresses match. | ||
69 | func (a *Address) Equals(b *Address) bool { | ||
70 | return a.Netw == b.Netw && | ||
71 | a.Options == b.Options && | ||
72 | bytes.Equal(a.Address, b.Address) | ||
73 | } | ||
74 | |||
75 | // StringAll returns a human-readable representation of an address. | ||
76 | func (a *Address) StringAll() string { | ||
77 | return a.Netw + "://" + string(a.Address) | ||
78 | } | ||
79 | |||
80 | // implement net.Addr interface methods: | ||
81 | |||
45 | // String returns a human-readable representation of an address. | 82 | // String returns a human-readable representation of an address. |
46 | func (a *Address) String() string { | 83 | func (a *Address) String() string { |
47 | return fmt.Sprintf("Address{%s}", AddressString(a.Transport, a.Address)) | 84 | return string(a.Address) |
85 | } | ||
86 | |||
87 | // Network returns the protocol specifier. | ||
88 | func (a *Address) Network() string { | ||
89 | return a.Netw | ||
48 | } | 90 | } |
49 | 91 | ||
50 | //---------------------------------------------------------------------- | 92 | //---------------------------------------------------------------------- |
51 | 93 | ||
52 | // AddressString returns a string representaion of an address. | 94 | // AddressString returns a string representaion of an address. |
53 | func AddressString(transport string, addr []byte) string { | 95 | func AddressString(network string, addr []byte) string { |
54 | if transport == "tcp" || transport == "udp" { | 96 | return network + "://" + string(addr) |
55 | alen := len(addr) | ||
56 | port := uint(addr[alen-2])*256 + uint(addr[alen-1]) | ||
57 | return fmt.Sprintf("%s:%s:%d", transport, net.IP(addr[:alen-2]).String(), port) | ||
58 | } | ||
59 | return fmt.Sprintf("%s:%s", transport, hex.EncodeToString(addr)) | ||
60 | } | 97 | } |
61 | 98 | ||
62 | //---------------------------------------------------------------------- | 99 | //---------------------------------------------------------------------- |
@@ -76,3 +113,71 @@ func NewIPAddress(host []byte, port uint16) *IPAddress { | |||
76 | copy(ip.Host, host) | 113 | copy(ip.Host, host) |
77 | return ip | 114 | return ip |
78 | } | 115 | } |
116 | |||
117 | //---------------------------------------------------------------------- | ||
118 | |||
119 | // PeerAddrList is a list of addresses per peer ID. | ||
120 | type PeerAddrList struct { | ||
121 | list *Map[string, []*Address] | ||
122 | } | ||
123 | |||
124 | // NewPeerAddrList returns a new and empty address list. | ||
125 | func NewPeerAddrList() *PeerAddrList { | ||
126 | return &PeerAddrList{ | ||
127 | list: NewMap[string, []*Address](), | ||
128 | } | ||
129 | } | ||
130 | |||
131 | // Add address for peer. The returned mode is 0=not added, 1=new peer, | ||
132 | // 2=new address | ||
133 | func (a *PeerAddrList) Add(id string, addr *Address) (mode int) { | ||
134 | // check for expired address. | ||
135 | mode = 0 | ||
136 | if !addr.Expires.Expired() { | ||
137 | // run add operation | ||
138 | a.list.Process(func() error { | ||
139 | list, ok := a.list.Get(id) | ||
140 | if !ok { | ||
141 | list = make([]*Address, 0) | ||
142 | mode = 1 | ||
143 | } else { | ||
144 | for _, a := range list { | ||
145 | if a.Equals(addr) { | ||
146 | return nil | ||
147 | } | ||
148 | } | ||
149 | mode = 2 | ||
150 | } | ||
151 | list = append(list, addr) | ||
152 | a.list.Put(id, list) | ||
153 | return nil | ||
154 | }) | ||
155 | } | ||
156 | return | ||
157 | } | ||
158 | |||
159 | // Get address for peer | ||
160 | func (a *PeerAddrList) Get(id string, transport string) *Address { | ||
161 | list, ok := a.list.Get(id) | ||
162 | if ok { | ||
163 | for _, addr := range list { | ||
164 | // check for expired address. | ||
165 | if addr.Expires.Expired() { | ||
166 | // skip expired | ||
167 | continue | ||
168 | } | ||
169 | // check for matching protocol | ||
170 | if len(transport) > 0 && transport != addr.Netw { | ||
171 | // skip other transports | ||
172 | continue | ||
173 | } | ||
174 | return addr | ||
175 | } | ||
176 | } | ||
177 | return nil | ||
178 | } | ||
179 | |||
180 | // Delete a list entry by key. | ||
181 | func (a *PeerAddrList) Delete(id string) { | ||
182 | a.list.Delete(id) | ||
183 | } | ||