func NewEntryRecord(na *wire.NetAddress) *EntryRecord { record := &EntryRecord{ addr: util.ParseNetAddress(na), stamp: na.Timestamp, services: uint64(na.Services), } return record }
func NewVersionRecord(msg *wire.MsgVersion, ra *net.TCPAddr, la *net.TCPAddr) *VersionRecord { vr := &VersionRecord{ Record: Record{ stamp: time.Now(), ra: ra, la: la, cmd: msg.Command(), }, version: msg.ProtocolVersion, services: uint64(msg.Services), sent: msg.Timestamp, raddr: util.ParseNetAddress(&msg.AddrYou), laddr: util.ParseNetAddress(&msg.AddrMe), agent: msg.UserAgent, block: msg.LastBlock, relay: !msg.DisableRelayTx, nonce: msg.Nonce, } return vr }
// processMessage does basic processing of the message to be in conformity // with the bitcoin protocol and then forwards it to the respective filters func (p *Peer) processMessage(msg wire.Message) { ra, ok1 := p.conn.RemoteAddr().(*net.TCPAddr) la, ok2 := p.conn.LocalAddr().(*net.TCPAddr) if ok1 && ok2 { record := convertor.Message(msg, ra, la) for _, rec := range p.recs { rec.Process(record) } } // if we have not yet received a version message and we receive any other // message, the peer is breaking the protocol and we disconnect if atomic.LoadUint32(&p.rcvd) == 0 { _, ok := msg.(*wire.MsgVersion) if !ok { p.log.Debug("%v: out of order non-version message", p) p.Stop() return } } // we read a message from the queue, process it depending on type switch m := msg.(type) { // version message is valid if we have not received one yet // we also try to avoid out-of-date protocol peers and connections to self case *wire.MsgVersion: if atomic.SwapUint32(&p.rcvd, 1) == 1 { p.log.Debug("%v: out of order version message", p) p.Stop() return } if m.Nonce == p.nonce { p.log.Debug("%v: detected connection to self", p) p.Stop() return } if uint32(m.ProtocolVersion) < wire.MultipleAddressVersion { p.log.Debug("%v: connected to obsolete peer", p) p.Stop() return } // synchronize our protocol version to lowest supported one version := atomic.LoadUint32(&p.version) version = util.MinUint32(version, uint32(m.ProtocolVersion)) atomic.StoreUint32(&p.version, version) // send the verack message p.pushVerAck() // if we have not sent our version yet, do so // if we have, the handshake is now complete if atomic.SwapUint32(&p.sent, 1) != 1 { p.pushVersion() } else { p.mgr.Ready(p) } // verack messages only matter if we are waiting to finish handshake // if we have both received and sent version, it is complete case *wire.MsgVerAck: if atomic.LoadUint32(&p.sent) == 1 && atomic.LoadUint32(&p.rcvd) == 1 { p.mgr.Ready(p) } // only send a pong message if the protocol version expects it case *wire.MsgPing: if p.version >= wire.BIP0031Version { p.pushPong(m.Nonce) } case *wire.MsgPong: case *wire.MsgGetAddr: // if we get an address message, add the addresses to the repository case *wire.MsgAddr: for _, na := range m.AddrList { addr := util.ParseNetAddress(na) p.repo.Discovered(addr) } // if we get an inventory message, ask for the inventory case *wire.MsgInv: p.pushGetData(m) case *wire.MsgGetHeaders: case *wire.MsgHeaders: case *wire.MsgGetBlocks: // if we receive a block message, mark the block hash as known case *wire.MsgBlock: p.tracker.AddBlock(m.BlockSha()) case *wire.MsgGetData: // if we receive a transaction message, mark the transaction hash as known case *wire.MsgTx: p.tracker.AddTx(m.TxSha()) case *wire.MsgAlert: default: } }