msg_hello.go (6017B)
1 // This file is part of gnunet-go, a GNUnet-implementation in Golang. 2 // Copyright (C) 2019-2022 Bernd Fix >Y< 3 // 4 // gnunet-go is free software: you can redistribute it and/or modify it 5 // under the terms of the GNU Affero General Public License as published 6 // by the Free Software Foundation, either version 3 of the License, 7 // or (at your option) any later version. 8 // 9 // gnunet-go is distributed in the hope that it will be useful, but 10 // WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 // Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 // 17 // SPDX-License-Identifier: AGPL3.0-or-later 18 19 package message 20 21 import ( 22 "bytes" 23 "encoding/binary" 24 "fmt" 25 "gnunet/enums" 26 "gnunet/util" 27 "io" 28 "time" 29 30 "github.com/bfix/gospel/logger" 31 ) 32 33 //---------------------------------------------------------------------- 34 35 // HelloAddress represents a (generic) peer address with expiration date: 36 type HelloAddress struct { 37 transport string // Name of transport 38 addrSize uint16 // Size of address entry 39 expires util.AbsoluteTime // Expiry date 40 address []byte // Address specification 41 } 42 43 // NewHelloAddress create a new HELLO address from the given address 44 func NewHelloAddress(a *util.Address) *HelloAddress { 45 // use default expiration time, but adjust it if address expires earlier 46 exp := util.NewAbsoluteTime(time.Now().Add(HelloAddressExpiration)) 47 if exp.Compare(a.Expire) > 0 { 48 exp = a.Expire 49 } 50 // convert address 51 addr := &HelloAddress{ 52 transport: a.Netw, 53 addrSize: uint16(len(a.Address)), 54 expires: exp, 55 address: make([]byte, len(a.Address)), 56 } 57 copy(addr.address, a.Address) 58 return addr 59 } 60 61 // ParseHelloAddress from reader 62 func ParseHelloAddr(rdr io.Reader) (a *HelloAddress, err error) { 63 // parse \0-terminated transport 64 var ( 65 transport []byte 66 buf = make([]byte, 1) 67 ) 68 for { 69 if _, err = rdr.Read(buf); err != nil { 70 return 71 } 72 if buf[0] == 0 { 73 break 74 } 75 transport = append(transport, buf[0]) 76 } 77 // parse address size 78 var asize uint16 79 if err = binary.Read(rdr, binary.BigEndian, &asize); err != nil { 80 return 81 } 82 // parse expiration time 83 var exp uint64 84 if err = binary.Read(rdr, binary.BigEndian, &exp); err != nil { 85 return 86 } 87 // get address data 88 adata := make([]byte, asize) 89 if _, err = rdr.Read(adata); err != nil { 90 return 91 } 92 // assemble HELLO address 93 a = &HelloAddress{ 94 transport: string(transport), 95 addrSize: asize, 96 expires: util.AbsoluteTime{Val: exp}, 97 address: adata, 98 } 99 return 100 } 101 102 // Wrap a HelloAddress into a uitl.Address 103 func (a *HelloAddress) Wrap() (addr *util.Address) { 104 addr = util.NewAddress(a.transport, string(a.address)) 105 addr.Expire = a.expires 106 return 107 } 108 109 // String returns a human-readable representation of the message. 110 func (a *HelloAddress) String() string { 111 return fmt.Sprintf("Address{%s,expire=%s}", 112 util.URI(a.transport, a.address), a.expires) 113 } 114 115 // Bytes returns the binary representation of a HelloAddress 116 func (a *HelloAddress) Bytes() []byte { 117 buf := new(bytes.Buffer) 118 _, err := buf.Write([]byte(a.transport)) 119 if err == nil { 120 if err = buf.WriteByte(0); err == nil { 121 if err = binary.Write(buf, binary.BigEndian, a.addrSize); err == nil { 122 if err = binary.Write(buf, binary.BigEndian, a.expires.Val); err != nil { 123 _, err = buf.Write(a.address) 124 } 125 } 126 } 127 } 128 if err != nil { 129 logger.Printf(logger.ERROR, "[HelloAddress] failed: %s", err.Error()) 130 } 131 return buf.Bytes() 132 } 133 134 //---------------------------------------------------------------------- 135 // HELLO 136 // 137 // A HELLO message is used to exchange information about transports with 138 // other peers. This struct is always followed by the actual network 139 // addresses of type "HelloAddress" 140 //---------------------------------------------------------------------- 141 142 // HelloMsg is a message send by peers to announce their presence 143 type HelloMsg struct { 144 MsgHeader 145 FriendsOnly uint32 `order:"big"` // Do not gossip this HELLO message 146 Peer *util.PeerID `` // peer identifier for addresses 147 AddrList []byte `size:"*"` // List of end-point addresses (HelloAddress) 148 149 // transient state 150 addresses []*HelloAddress // list of converted addresses 151 } 152 153 // Init called after unmarshalling a message to setup internal state 154 func (m *HelloMsg) Init() (err error) { 155 // check for initialized state 156 if m.addresses != nil { 157 return nil 158 } 159 // convert addresses 160 m.addresses = make([]*HelloAddress, 0) 161 rdr := bytes.NewReader(m.AddrList) 162 var addr *HelloAddress 163 for { 164 // parse address from stream 165 if addr, err = ParseHelloAddr(rdr); err != nil { 166 // end of stream: no more addresses 167 if err == io.EOF { 168 err = nil 169 } 170 return 171 } 172 m.addresses = append(m.addresses, addr) 173 } 174 } 175 176 // NewHelloMsg creates a new HELLO msg for a given peer. 177 func NewHelloMsg(peer *util.PeerID) *HelloMsg { 178 // allocate peer id if none is specified 179 if peer == nil { 180 peer = util.NewPeerID(nil) 181 } 182 // return empty HelloMessage 183 return &HelloMsg{ 184 MsgHeader: MsgHeader{40, enums.MSG_HELLO}, 185 FriendsOnly: 0, // not used here 186 Peer: peer, // associated peer 187 AddrList: make([]byte, 0), // list of addresses 188 } 189 } 190 191 // Addresses returns the list of HelloAddress 192 func (m *HelloMsg) Addresses() (list []*HelloAddress, err error) { 193 if m.addresses == nil { 194 return 195 } 196 return m.addresses, nil 197 } 198 199 // String returns a human-readable representation of the message. 200 func (m *HelloMsg) String() string { 201 return fmt.Sprintf("HelloMsg{%s: addrs=%d}", m.Peer, len(m.AddrList)) 202 } 203 204 // SetAddresses adds addresses to the HELLO message. 205 func (m *HelloMsg) SetAddresses(list []*HelloAddress) { 206 wrt := new(bytes.Buffer) 207 for _, addr := range list { 208 n, _ := wrt.Write(addr.Bytes()) 209 m.MsgSize += uint16(n) 210 } 211 m.AddrList = wrt.Bytes() 212 }