You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

444 lines
10 KiB

  1. package p2p
  2. import (
  3. "fmt"
  4. "net"
  5. "sync/atomic"
  6. "time"
  7. crypto "github.com/tendermint/tendermint/crypto"
  8. cmn "github.com/tendermint/tendermint/libs/common"
  9. "github.com/tendermint/tendermint/libs/log"
  10. "github.com/tendermint/tendermint/config"
  11. tmconn "github.com/tendermint/tendermint/p2p/conn"
  12. )
  13. var testIPSuffix uint32
  14. // Peer is an interface representing a peer connected on a reactor.
  15. type Peer interface {
  16. cmn.Service
  17. ID() ID // peer's cryptographic ID
  18. RemoteIP() net.IP // remote IP of the connection
  19. IsOutbound() bool // did we dial the peer
  20. IsPersistent() bool // do we redial this peer when we disconnect
  21. NodeInfo() NodeInfo // peer's info
  22. Status() tmconn.ConnectionStatus
  23. OriginalAddr() *NetAddress
  24. Send(byte, []byte) bool
  25. TrySend(byte, []byte) bool
  26. Set(string, interface{})
  27. Get(string) interface{}
  28. }
  29. //----------------------------------------------------------
  30. // peerConn contains the raw connection and its config.
  31. type peerConn struct {
  32. outbound bool
  33. persistent bool
  34. config *config.P2PConfig
  35. conn net.Conn // source connection
  36. ip net.IP
  37. originalAddr *NetAddress // nil for inbound connections
  38. }
  39. // ID only exists for SecretConnection.
  40. // NOTE: Will panic if conn is not *SecretConnection.
  41. func (pc peerConn) ID() ID {
  42. return PubKeyToID(pc.conn.(*tmconn.SecretConnection).RemotePubKey())
  43. }
  44. // Return the IP from the connection RemoteAddr
  45. func (pc peerConn) RemoteIP() net.IP {
  46. if pc.ip != nil {
  47. return pc.ip
  48. }
  49. // In test cases a conn could not be present at all or be an in-memory
  50. // implementation where we want to return a fake ip.
  51. if pc.conn == nil || pc.conn.RemoteAddr().String() == "pipe" {
  52. pc.ip = net.IP{172, 16, 0, byte(atomic.AddUint32(&testIPSuffix, 1))}
  53. return pc.ip
  54. }
  55. host, _, err := net.SplitHostPort(pc.conn.RemoteAddr().String())
  56. if err != nil {
  57. panic(err)
  58. }
  59. ips, err := net.LookupIP(host)
  60. if err != nil {
  61. panic(err)
  62. }
  63. pc.ip = ips[0]
  64. return pc.ip
  65. }
  66. // peer implements Peer.
  67. //
  68. // Before using a peer, you will need to perform a handshake on connection.
  69. type peer struct {
  70. cmn.BaseService
  71. // raw peerConn and the multiplex connection
  72. peerConn
  73. mconn *tmconn.MConnection
  74. // peer's node info and the channel it knows about
  75. // channels = nodeInfo.Channels
  76. // cached to avoid copying nodeInfo in hasChannel
  77. nodeInfo NodeInfo
  78. channels []byte
  79. // User data
  80. Data *cmn.CMap
  81. }
  82. func newPeer(
  83. pc peerConn,
  84. mConfig tmconn.MConnConfig,
  85. nodeInfo NodeInfo,
  86. reactorsByCh map[byte]Reactor,
  87. chDescs []*tmconn.ChannelDescriptor,
  88. onPeerError func(Peer, interface{}),
  89. ) *peer {
  90. p := &peer{
  91. peerConn: pc,
  92. nodeInfo: nodeInfo,
  93. channels: nodeInfo.Channels,
  94. Data: cmn.NewCMap(),
  95. }
  96. p.mconn = createMConnection(
  97. pc.conn,
  98. p,
  99. reactorsByCh,
  100. chDescs,
  101. onPeerError,
  102. mConfig,
  103. )
  104. p.BaseService = *cmn.NewBaseService(nil, "Peer", p)
  105. return p
  106. }
  107. func newOutboundPeerConn(
  108. addr *NetAddress,
  109. config *config.P2PConfig,
  110. persistent bool,
  111. ourNodePrivKey crypto.PrivKey,
  112. ) (peerConn, error) {
  113. conn, err := dial(addr, config)
  114. if err != nil {
  115. return peerConn{}, cmn.ErrorWrap(err, "Error creating peer")
  116. }
  117. pc, err := newPeerConn(conn, config, true, persistent, ourNodePrivKey, addr)
  118. if err != nil {
  119. if cerr := conn.Close(); cerr != nil {
  120. return peerConn{}, cmn.ErrorWrap(err, cerr.Error())
  121. }
  122. return peerConn{}, err
  123. }
  124. // ensure dialed ID matches connection ID
  125. if addr.ID != pc.ID() {
  126. if cerr := conn.Close(); cerr != nil {
  127. return peerConn{}, cmn.ErrorWrap(err, cerr.Error())
  128. }
  129. return peerConn{}, ErrSwitchAuthenticationFailure{addr, pc.ID()}
  130. }
  131. return pc, nil
  132. }
  133. func newInboundPeerConn(
  134. conn net.Conn,
  135. config *config.P2PConfig,
  136. ourNodePrivKey crypto.PrivKey,
  137. ) (peerConn, error) {
  138. // TODO: issue PoW challenge
  139. return newPeerConn(conn, config, false, false, ourNodePrivKey, nil)
  140. }
  141. func newPeerConn(
  142. rawConn net.Conn,
  143. cfg *config.P2PConfig,
  144. outbound, persistent bool,
  145. ourNodePrivKey crypto.PrivKey,
  146. originalAddr *NetAddress,
  147. ) (pc peerConn, err error) {
  148. conn := rawConn
  149. // Fuzz connection
  150. if cfg.TestFuzz {
  151. // so we have time to do peer handshakes and get set up
  152. conn = FuzzConnAfterFromConfig(conn, 10*time.Second, cfg.TestFuzzConfig)
  153. }
  154. // Set deadline for secret handshake
  155. dl := time.Now().Add(cfg.HandshakeTimeout)
  156. if err := conn.SetDeadline(dl); err != nil {
  157. return pc, cmn.ErrorWrap(
  158. err,
  159. "Error setting deadline while encrypting connection",
  160. )
  161. }
  162. // Encrypt connection
  163. conn, err = tmconn.MakeSecretConnection(conn, ourNodePrivKey)
  164. if err != nil {
  165. return pc, cmn.ErrorWrap(err, "Error creating peer")
  166. }
  167. // Only the information we already have
  168. return peerConn{
  169. config: cfg,
  170. outbound: outbound,
  171. persistent: persistent,
  172. conn: conn,
  173. originalAddr: originalAddr,
  174. }, nil
  175. }
  176. //---------------------------------------------------
  177. // Implements cmn.Service
  178. // SetLogger implements BaseService.
  179. func (p *peer) SetLogger(l log.Logger) {
  180. p.Logger = l
  181. p.mconn.SetLogger(l)
  182. }
  183. // OnStart implements BaseService.
  184. func (p *peer) OnStart() error {
  185. if err := p.BaseService.OnStart(); err != nil {
  186. return err
  187. }
  188. err := p.mconn.Start()
  189. return err
  190. }
  191. // OnStop implements BaseService.
  192. func (p *peer) OnStop() {
  193. p.BaseService.OnStop()
  194. p.mconn.Stop() // stop everything and close the conn
  195. }
  196. //---------------------------------------------------
  197. // Implements Peer
  198. // ID returns the peer's ID - the hex encoded hash of its pubkey.
  199. func (p *peer) ID() ID {
  200. return p.nodeInfo.ID
  201. }
  202. // IsOutbound returns true if the connection is outbound, false otherwise.
  203. func (p *peer) IsOutbound() bool {
  204. return p.peerConn.outbound
  205. }
  206. // IsPersistent returns true if the peer is persitent, false otherwise.
  207. func (p *peer) IsPersistent() bool {
  208. return p.peerConn.persistent
  209. }
  210. // NodeInfo returns a copy of the peer's NodeInfo.
  211. func (p *peer) NodeInfo() NodeInfo {
  212. return p.nodeInfo
  213. }
  214. // OriginalAddr returns the original address, which was used to connect with
  215. // the peer. Returns nil for inbound peers.
  216. func (p *peer) OriginalAddr() *NetAddress {
  217. if p.peerConn.outbound {
  218. return p.peerConn.originalAddr
  219. }
  220. return nil
  221. }
  222. // Status returns the peer's ConnectionStatus.
  223. func (p *peer) Status() tmconn.ConnectionStatus {
  224. return p.mconn.Status()
  225. }
  226. // Send msg bytes to the channel identified by chID byte. Returns false if the
  227. // send queue is full after timeout, specified by MConnection.
  228. func (p *peer) Send(chID byte, msgBytes []byte) bool {
  229. if !p.IsRunning() {
  230. // see Switch#Broadcast, where we fetch the list of peers and loop over
  231. // them - while we're looping, one peer may be removed and stopped.
  232. return false
  233. } else if !p.hasChannel(chID) {
  234. return false
  235. }
  236. return p.mconn.Send(chID, msgBytes)
  237. }
  238. // TrySend msg bytes to the channel identified by chID byte. Immediately returns
  239. // false if the send queue is full.
  240. func (p *peer) TrySend(chID byte, msgBytes []byte) bool {
  241. if !p.IsRunning() {
  242. return false
  243. } else if !p.hasChannel(chID) {
  244. return false
  245. }
  246. return p.mconn.TrySend(chID, msgBytes)
  247. }
  248. // Get the data for a given key.
  249. func (p *peer) Get(key string) interface{} {
  250. return p.Data.Get(key)
  251. }
  252. // Set sets the data for the given key.
  253. func (p *peer) Set(key string, data interface{}) {
  254. p.Data.Set(key, data)
  255. }
  256. // hasChannel returns true if the peer reported
  257. // knowing about the given chID.
  258. func (p *peer) hasChannel(chID byte) bool {
  259. for _, ch := range p.channels {
  260. if ch == chID {
  261. return true
  262. }
  263. }
  264. // NOTE: probably will want to remove this
  265. // but could be helpful while the feature is new
  266. p.Logger.Debug(
  267. "Unknown channel for peer",
  268. "channel",
  269. chID,
  270. "channels",
  271. p.channels,
  272. )
  273. return false
  274. }
  275. //---------------------------------------------------
  276. // methods used by the Switch
  277. // CloseConn should be called by the Switch if the peer was created but never
  278. // started.
  279. func (pc *peerConn) CloseConn() {
  280. pc.conn.Close() // nolint: errcheck
  281. }
  282. // HandshakeTimeout performs the Tendermint P2P handshake between a given node
  283. // and the peer by exchanging their NodeInfo. It sets the received nodeInfo on
  284. // the peer.
  285. // NOTE: blocking
  286. func (pc *peerConn) HandshakeTimeout(
  287. ourNodeInfo NodeInfo,
  288. timeout time.Duration,
  289. ) (peerNodeInfo NodeInfo, err error) {
  290. // Set deadline for handshake so we don't block forever on conn.ReadFull
  291. if err := pc.conn.SetDeadline(time.Now().Add(timeout)); err != nil {
  292. return peerNodeInfo, cmn.ErrorWrap(err, "Error setting deadline")
  293. }
  294. var trs, _ = cmn.Parallel(
  295. func(_ int) (val interface{}, err error, abort bool) {
  296. _, err = cdc.MarshalBinaryWriter(pc.conn, ourNodeInfo)
  297. return
  298. },
  299. func(_ int) (val interface{}, err error, abort bool) {
  300. _, err = cdc.UnmarshalBinaryReader(
  301. pc.conn,
  302. &peerNodeInfo,
  303. int64(MaxNodeInfoSize()),
  304. )
  305. return
  306. },
  307. )
  308. if err := trs.FirstError(); err != nil {
  309. return peerNodeInfo, cmn.ErrorWrap(err, "Error during handshake")
  310. }
  311. // Remove deadline
  312. if err := pc.conn.SetDeadline(time.Time{}); err != nil {
  313. return peerNodeInfo, cmn.ErrorWrap(err, "Error removing deadline")
  314. }
  315. return peerNodeInfo, nil
  316. }
  317. // Addr returns peer's remote network address.
  318. func (p *peer) Addr() net.Addr {
  319. return p.peerConn.conn.RemoteAddr()
  320. }
  321. // CanSend returns true if the send queue is not full, false otherwise.
  322. func (p *peer) CanSend(chID byte) bool {
  323. if !p.IsRunning() {
  324. return false
  325. }
  326. return p.mconn.CanSend(chID)
  327. }
  328. // String representation.
  329. func (p *peer) String() string {
  330. if p.outbound {
  331. return fmt.Sprintf("Peer{%v %v out}", p.mconn, p.ID())
  332. }
  333. return fmt.Sprintf("Peer{%v %v in}", p.mconn, p.ID())
  334. }
  335. //------------------------------------------------------------------
  336. // helper funcs
  337. func dial(addr *NetAddress, cfg *config.P2PConfig) (net.Conn, error) {
  338. if cfg.TestDialFail {
  339. return nil, fmt.Errorf("dial err (peerConfig.DialFail == true)")
  340. }
  341. conn, err := addr.DialTimeout(cfg.DialTimeout)
  342. if err != nil {
  343. return nil, err
  344. }
  345. return conn, nil
  346. }
  347. func createMConnection(
  348. conn net.Conn,
  349. p *peer,
  350. reactorsByCh map[byte]Reactor,
  351. chDescs []*tmconn.ChannelDescriptor,
  352. onPeerError func(Peer, interface{}),
  353. config tmconn.MConnConfig,
  354. ) *tmconn.MConnection {
  355. onReceive := func(chID byte, msgBytes []byte) {
  356. reactor := reactorsByCh[chID]
  357. if reactor == nil {
  358. // Note that its ok to panic here as it's caught in the conn._recover,
  359. // which does onPeerError.
  360. panic(fmt.Sprintf("Unknown channel %X", chID))
  361. }
  362. reactor.Receive(chID, p, msgBytes)
  363. }
  364. onError := func(r interface{}) {
  365. onPeerError(p, r)
  366. }
  367. return tmconn.NewMConnectionWithConfig(
  368. conn,
  369. chDescs,
  370. onReceive,
  371. onError,
  372. config,
  373. )
  374. }