github.com/ethersphere/bee/v2@v2.2.0/pkg/p2p/p2p.go (about) 1 // Copyright 2020 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package p2p provides the peer-to-peer abstractions used 6 // across different protocols in Bee. 7 package p2p 8 9 import ( 10 "context" 11 "errors" 12 "fmt" 13 "io" 14 "time" 15 16 "github.com/ethersphere/bee/v2/pkg/bzz" 17 "github.com/ethersphere/bee/v2/pkg/swarm" 18 "github.com/libp2p/go-libp2p/core/network" 19 ma "github.com/multiformats/go-multiaddr" 20 ) 21 22 // ReachabilityStatus represents the node reachability status. 23 type ReachabilityStatus network.Reachability 24 25 // String implements the fmt.Stringer interface. 26 func (rs ReachabilityStatus) String() string { 27 return network.Reachability(rs).String() 28 } 29 30 const ( 31 ReachabilityStatusUnknown = ReachabilityStatus(network.ReachabilityUnknown) 32 ReachabilityStatusPublic = ReachabilityStatus(network.ReachabilityPublic) 33 ReachabilityStatusPrivate = ReachabilityStatus(network.ReachabilityPrivate) 34 ) 35 36 // NetworkStatus represents the network availability status. 37 type NetworkStatus int 38 39 // String implements the fmt.Stringer interface. 40 func (ns NetworkStatus) String() string { 41 str := [...]string{ 42 NetworkStatusUnknown: "Unknown", 43 NetworkStatusAvailable: "Available", 44 NetworkStatusUnavailable: "Unavailable", 45 } 46 if ns < 0 || int(ns) >= len(str) { 47 return "(unrecognized)" 48 } 49 return str[ns] 50 } 51 52 const ( 53 NetworkStatusUnknown NetworkStatus = 0 54 NetworkStatusAvailable NetworkStatus = 1 55 NetworkStatusUnavailable NetworkStatus = 2 56 ) 57 58 var ErrNetworkUnavailable = errors.New("network unavailable") 59 60 // Service provides methods to handle p2p Peers and Protocols. 61 type Service interface { 62 AddProtocol(ProtocolSpec) error 63 // Connect to a peer but do not notify topology about the established connection. 64 Connect(ctx context.Context, addr ma.Multiaddr) (address *bzz.Address, err error) 65 Disconnecter 66 Peers() []Peer 67 Blocklisted(swarm.Address) (bool, error) 68 BlocklistedPeers() ([]BlockListedPeer, error) 69 Addresses() ([]ma.Multiaddr, error) 70 SetPickyNotifier(PickyNotifier) 71 Halter 72 NetworkStatuser 73 } 74 75 // NetworkStatuser handles bookkeeping of the network availability status. 76 type NetworkStatuser interface { 77 // NetworkStatus returns current network availability status. 78 NetworkStatus() NetworkStatus 79 } 80 81 type Disconnecter interface { 82 Disconnect(overlay swarm.Address, reason string) error 83 Blocklister 84 } 85 86 type Blocklister interface { 87 NetworkStatuser 88 89 // Blocklist will disconnect a peer and put it on a blocklist (blocking in & out connections) for provided duration 90 // Duration 0 is treated as an infinite duration. 91 Blocklist(overlay swarm.Address, duration time.Duration, reason string) error 92 } 93 94 type Halter interface { 95 // Halt new incoming connections while shutting down 96 Halt() 97 } 98 99 // PickyNotifier can decide whether a peer should be picked 100 type PickyNotifier interface { 101 Picker 102 Notifier 103 ReachabilityUpdater 104 ReachableNotifier 105 } 106 107 type Picker interface { 108 Pick(Peer) bool 109 } 110 111 type ReachableNotifier interface { 112 Reachable(swarm.Address, ReachabilityStatus) 113 } 114 115 type Reacher interface { 116 Connected(swarm.Address, ma.Multiaddr) 117 Disconnected(swarm.Address) 118 Close() error 119 } 120 121 type ReachabilityUpdater interface { 122 UpdateReachability(ReachabilityStatus) 123 } 124 125 type Notifier interface { 126 Connected(context.Context, Peer, bool) error 127 Disconnected(Peer) 128 Announce(ctx context.Context, peer swarm.Address, fullnode bool) error 129 AnnounceTo(ctx context.Context, addressee, peer swarm.Address, fullnode bool) error 130 } 131 132 // DebugService extends the Service with method used for debugging. 133 type DebugService interface { 134 Service 135 SetWelcomeMessage(val string) error 136 GetWelcomeMessage() string 137 } 138 139 // Streamer is able to create a new Stream. 140 type Streamer interface { 141 NewStream(ctx context.Context, address swarm.Address, h Headers, protocol, version, stream string) (Stream, error) 142 } 143 144 type StreamerDisconnecter interface { 145 Streamer 146 Disconnecter 147 } 148 149 // Pinger interface is used to ping a underlay address which is not yet known to the bee node. 150 // It uses libp2p's default ping protocol. This is different from the PingPong protocol as this 151 // is meant to be used before we know a particular underlay and we can consider it useful 152 type Pinger interface { 153 Ping(ctx context.Context, addr ma.Multiaddr) (rtt time.Duration, err error) 154 } 155 156 type StreamerPinger interface { 157 Streamer 158 Pinger 159 } 160 161 // Stream represent a bidirectional data Stream. 162 type Stream interface { 163 io.ReadWriter 164 io.Closer 165 ResponseHeaders() Headers 166 Headers() Headers 167 FullClose() error 168 Reset() error 169 } 170 171 // ProtocolSpec defines a collection of Stream specifications with handlers. 172 type ProtocolSpec struct { 173 Name string 174 Version string 175 StreamSpecs []StreamSpec 176 ConnectIn func(context.Context, Peer) error 177 ConnectOut func(context.Context, Peer) error 178 DisconnectIn func(Peer) error 179 DisconnectOut func(Peer) error 180 } 181 182 // StreamSpec defines a Stream handling within the protocol. 183 type StreamSpec struct { 184 Name string 185 Handler HandlerFunc 186 Headler HeadlerFunc 187 } 188 189 // Peer holds information about a Peer. 190 type Peer struct { 191 Address swarm.Address 192 FullNode bool 193 EthereumAddress []byte 194 } 195 196 // BlockListedPeer holds information about a Peer that is blocked. 197 type BlockListedPeer struct { 198 Peer 199 Reason string 200 Duration time.Duration 201 } 202 203 // HandlerFunc handles a received Stream from a Peer. 204 type HandlerFunc func(context.Context, Peer, Stream) error 205 206 // HandlerMiddleware decorates a HandlerFunc by returning a new one. 207 type HandlerMiddleware func(HandlerFunc) HandlerFunc 208 209 // HeadlerFunc is returning response headers based on the received request 210 // headers. 211 type HeadlerFunc func(Headers, swarm.Address) Headers 212 213 // Headers represents a collection of p2p header key value pairs. 214 type Headers map[string][]byte 215 216 // Common header names. 217 const ( 218 HeaderNameTracingSpanContext = "tracing-span-context" 219 ) 220 221 // NewSwarmStreamName constructs a libp2p compatible stream name out of 222 // protocol name and version and stream name. 223 func NewSwarmStreamName(protocol, version, stream string) string { 224 return "/swarm/" + protocol + "/" + version + "/" + stream 225 } 226 227 type ChunkDeliveryError struct { 228 msg string 229 } 230 231 // Error implements the error interface. 232 func (e *ChunkDeliveryError) Error() string { 233 return fmt.Sprintf("delivery of chunk failed: %s", e.msg) 234 } 235 236 // NewChunkDeliveryError is a convenience constructor for ChunkDeliveryError. 237 func NewChunkDeliveryError(msg string) error { 238 return &ChunkDeliveryError{msg: msg} 239 }