github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/vntp2p/peer.go (about) 1 // Copyright 2019 The go-vnt Authors 2 // This file is part of the go-vnt library. 3 // 4 // The go-vnt library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-vnt library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-vnt library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vntp2p 18 19 import ( 20 // "crypto/ecdsa" 21 // "crypto/elliptic" 22 "bufio" 23 "crypto/ecdsa" 24 "encoding/json" 25 "net" 26 "sync" 27 "sync/atomic" 28 29 inet "github.com/libp2p/go-libp2p-net" 30 libp2p "github.com/libp2p/go-libp2p-peer" 31 ma "github.com/multiformats/go-multiaddr" 32 manet "github.com/multiformats/go-multiaddr-net" 33 "github.com/vntchain/go-vnt/event" 34 "github.com/vntchain/go-vnt/log" 35 ) 36 37 type PeerEventType string 38 39 const ( 40 // PeerEventTypeAdd is the type of event emitted when a peer is added 41 // to a p2p.Server 42 PeerEventTypeAdd PeerEventType = "add" 43 44 // PeerEventTypeDrop is the type of event emitted when a peer is 45 // dropped from a p2p.Server 46 PeerEventTypeDrop PeerEventType = "drop" 47 48 // PeerEventTypeMsgSend is the type of event emitted when a 49 // message is successfully sent to a peer 50 PeerEventTypeMsgSend PeerEventType = "msgsend" 51 52 // PeerEventTypeMsgRecv is the type of event emitted when a 53 // message is received from a peer 54 PeerEventTypeMsgRecv PeerEventType = "msgrecv" 55 ) 56 57 // PeerEvent is an event emitted when peers are either added or dropped from 58 // a p2p.Server or when a message is sent or received on a peer connection 59 type PeerEvent struct { 60 Type PeerEventType `json:"type"` 61 Peer libp2p.ID `json:"peer"` 62 Error string `json:"error,omitempty"` 63 Protocol string `json:"protocol,omitempty"` 64 MsgCode *uint64 `json:"msg_code,omitempty"` 65 MsgSize *uint32 `json:"msg_size,omitempty"` 66 } 67 68 type PeerInfo struct { 69 ID string `json:"id"` // Unique node identifier (also the encryption key) 70 Name string `json:"name"` // Name of the node, including client type, version, OS, custom data 71 Caps []string `json:"caps"` // Sum-protocols advertised by this particular peer 72 Network struct { 73 LocalAddress string `json:"localAddress"` // Local endpoint of the TCP data connection 74 RemoteAddress string `json:"remoteAddress"` // Remote endpoint of the TCP data connection 75 Inbound bool `json:"inbound"` 76 Trusted bool `json:"trusted"` 77 Static bool `json:"static"` 78 } `json:"network"` 79 Protocols map[string]interface{} `json:"protocols"` // Sub-protocol specific metadata fields 80 } 81 82 type Peer struct { 83 rw inet.Stream // libp2p stream 84 reseted int32 // Whether stream reseted 85 log log.Logger 86 events *event.Feed 87 err chan error 88 msgers map[string]*VNTMsger // protocolName - vntMessenger 89 server *Server 90 wg sync.WaitGroup 91 } 92 93 func newPeer(s *Stream, server *Server) *Peer { 94 m := make(map[string]*VNTMsger) 95 for i := range s.Protocols { 96 proto := s.Protocols[i] 97 vntMessenger := &VNTMsger{ 98 protocol: proto, 99 in: make(chan Msg), 100 err: make(chan error, 100), 101 w: s.stream, 102 } 103 m[proto.Name] = vntMessenger 104 } 105 106 p := &Peer{ 107 rw: s.stream, 108 log: log.New("peer", s.stream.Conn().RemotePeer().ToString()), 109 err: make(chan error), 110 reseted: 0, 111 msgers: m, 112 server: server, 113 } 114 for _, msger := range p.msgers { 115 msger.peer = p 116 } 117 118 return p 119 } 120 121 // Drop this peer forever because of protocol mismatch 122 func (p *Peer) Drop() { 123 log.Trace("Drop peer forever", "pid", p.RemoteID()) 124 p.rw.Conn().Close() 125 blacklist.write(p.RemoteID()) 126 } 127 128 // LocalID return local PeerID for upper application 129 func (p *Peer) LocalID() libp2p.ID { 130 return p.rw.Conn().LocalPeer() 131 } 132 133 // RemoteID return remote PeerID for upper application 134 func (p *Peer) RemoteID() libp2p.ID { 135 return p.rw.Conn().RemotePeer() 136 } 137 138 func (p *Peer) Log() log.Logger { 139 return p.log 140 } 141 142 func (p *Peer) LocalAddr() net.Addr { 143 lma := p.rw.Conn().LocalMultiaddr() 144 return parseMultiaddr(lma) 145 } 146 147 func (p *Peer) RemoteAddr() net.Addr { 148 rma := p.rw.Conn().RemoteMultiaddr() 149 return parseMultiaddr(rma) 150 } 151 152 func parseMultiaddr(maddr ma.Multiaddr) net.Addr { 153 network, host, err := manet.DialArgs(maddr) 154 if err != nil { 155 log.Error("parseMultiaddr()", "dialArgs error", err) 156 return nil 157 } 158 159 switch network { 160 case "tcp", "tcp4", "tcp6": 161 na, err := net.ResolveTCPAddr(network, host) 162 if err != nil { 163 log.Error("parseMultiaddr()", "resolveTCPAddr error", err) 164 return nil 165 } 166 return na 167 case "udp", "udp4", "udp6": 168 na, err := net.ResolveUDPAddr(network, host) 169 if err != nil { 170 log.Error("parseMultiaddr()", "ResolveUDPAddr error", err) 171 return nil 172 } 173 return na 174 case "ip", "ip4", "ip6": 175 na, err := net.ResolveIPAddr(network, host) 176 if err != nil { 177 log.Error("parseMultiaddr()", "ResolveIPAddr error", err) 178 return nil 179 } 180 return na 181 } 182 log.Error("parseMultiaddr()", "network not supported", network) 183 return nil 184 } 185 186 func (p *Peer) Disconnect(reason DiscReason) { 187 // test for it 188 // p.rw.Conn().Close() 189 // p.rw.Close() 190 191 p.log.Debug("Disconnect", "reason", reason) 192 p.Reset() 193 } 194 195 // Reset Close both direction. Use this to tell the remote side to hang up and go away. 196 // But only reset once. 197 func (p *Peer) Reset() { 198 if !atomic.CompareAndSwapInt32(&p.reseted, 0, 1) { 199 return 200 } 201 202 if err := p.rw.Reset(); err != nil { 203 p.log.Debug("Reset peer connection", "error", err.Error()) 204 } else { 205 p.log.Debug("Reset peer connection success") 206 } 207 } 208 209 func (p *Peer) Info() *PeerInfo { 210 info := &PeerInfo{ 211 ID: p.RemoteID().String(), 212 } 213 info.Network.LocalAddress = p.rw.Conn().LocalMultiaddr().String() 214 info.Network.RemoteAddress = p.rw.Conn().RemoteMultiaddr().String() 215 216 // 此处暂时不处理状态 217 // info.Network.Static = p.rw.Conn().RemotePeer() 218 // info.Network.Trusted = 219 // info.Network.Inbound = 220 221 return info 222 } 223 224 func (p *Peer) run() (remoteRequested bool, err error) { 225 for _, msger := range p.msgers { 226 proto := msger.protocol 227 m := msger 228 p.wg.Add(1) 229 go func() { 230 err := proto.Run(p, m) 231 p.log.Debug("Run protocol error", "protocol", proto.Name, "error", err) 232 233 p.sendError(err) 234 p.wg.Done() 235 }() 236 } 237 238 err = <-p.err 239 remoteRequested = true 240 p.Reset() 241 p.log.Debug("P2P remote peer request close, but we need to wait for other protocol", "peer", p.RemoteID()) 242 p.wg.Wait() 243 p.log.Debug("P2P wait complete!", "peer", p.RemoteID()) 244 245 return remoteRequested, err 246 } 247 248 // sendError 为Peer的协议开了多个goroutine,可能多个协议都返回错误, 249 // 退出只接收一次错误就可以,所以采用非阻塞发送错误 250 func (p *Peer) sendError(err error) { 251 select { 252 case p.err <- err: 253 default: 254 } 255 } 256 257 type Stream struct { 258 stream inet.Stream 259 Protocols []Protocol 260 } 261 262 //临时测试使用 263 func WritePackage(rw *bufio.ReadWriter, code uint64, data []byte) ([]byte, error) { 264 //msg := &Msg{Code: code, Data: data, Size: uint32(len(data))} 265 msg := &Msg{} 266 // logg.Printf("Msg: %v", msg) 267 return json.Marshal(msg) 268 } 269 270 func PubkeyID(pub *ecdsa.PublicKey) libp2p.ID { 271 // var id NodeID 272 // pbytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y) 273 // if len(pbytes)-1 != len(id) { 274 // panic(fmt.Errorf("need %d bit pubkey, got %d bits", (len(id)+1)*8, len(pbytes))) 275 // } 276 // copy(id[:], pbytes[1:]) 277 // return id 278 id, err := libp2p.IDFromPublicKey(pub) 279 if err != nil { 280 panic("wrong publick key") 281 } 282 return id 283 }