aboutsummaryrefslogtreecommitdiff
path: root/src/gnunet/util/address.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/gnunet/util/address.go')
-rw-r--r--src/gnunet/util/address.go141
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 @@
19package util 19package util
20 20
21import ( 21import (
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.
28type Address struct { 29type 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
35func NewAddress(transport string, addr []byte) *Address { 37func 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
46func 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".
58func 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.
69func (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.
76func (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.
46func (a *Address) String() string { 83func (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.
88func (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.
53func AddressString(transport string, addr []byte) string { 95func 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.
120type PeerAddrList struct {
121 list *Map[string, []*Address]
122}
123
124// NewPeerAddrList returns a new and empty address list.
125func 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
133func (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
160func (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.
181func (a *PeerAddrList) Delete(id string) {
182 a.list.Delete(id)
183}