// GetData retrieves requests objects with the specified hashes from the // peer node that sent us ver. It returns the number of objects // successfully received and an error if n < len(hashes). func (nd *Node) GetData(ver *payload.Version, hashes [][]byte) (n int, err error) { conn, err := net.DialTimeout("tcp", ver.FromAddr.Addr(), defaultTimeout) if err != nil { return n, err } defer conn.Close() pay, err := payload.GetDataEncode(ver.Protocol(), hashes) if err != nil { panic(err) } m := msg.New(msg.Cgetdata, pay) conn.Write(m.Encode()) for i := 0; i < len(hashes); i++ { m, err := msg.Decode(conn) if err != nil { return n, err } switch m.Cmd() { case msg.Cversion, msg.Cverack, msg.Caddr, msg.Cinv, msg.Cgetdata: return n, fmt.Errorf("getdata resp contains invalid msg type %v", m.Cmd()) } nd.ObjectsIn <- m n++ } return n, nil }
func (n *Node) sendInvAndAddr(conn net.Conn, proto uint32) { pay, err := payload.AddrEncode(proto, n.MyPeers...) if err != nil { panic(err) } am := msg.New(msg.Caddr, pay) if _, err := conn.Write(am.Encode()); err != nil { panic(err) } pay, err = payload.InventoryEncode(proto, n.invList()) if err != nil { panic(err) } im := msg.New(msg.Cinv, pay) if _, err := conn.Write(im.Encode()); err != nil { panic(err) } }
func (n *Node) verOutVerackIn(conn net.Conn, to *payload.AddressInfo, proto uint32) { vcopy := *n.MyVer vcopy.Timestamp = time.Now() vcopy.ToAddr = to pay, err := vcopy.Encode(proto) if err != nil { panic(err) } m := msg.New(msg.Cversion, pay) if _, err := conn.Write(m.Encode()); err != nil { panic(err) } msg.Must(msg.ReadKind(conn, msg.Cverack)) }
func (n *Node) versionExchange(addr *payload.AddressInfo) { resp := &VerDat{} defer func() { n.VerIn <- resp }() defer func() { if r := recover(); r != nil { resp.Err = fmt.Errorf("[ERR] version exchange did not complete (%v)", r) n.Log.Print(resp.Err) } }() n.Log.Printf("[INFO] version exchange with %v", addr.Addr()) conn, err := net.DialTimeout("tcp", addr.Addr(), defaultTimeout) if err != nil { panic(err) } defer conn.Close() n.verOutVerackIn(conn, addr, payload.ProtocolVersion) // wait for version message and send verack m := msg.Must(msg.ReadKind(conn, msg.Cversion)) resp.Ver, err = payload.VersionDecode(m.Payload()) if err != nil { panic(err) } if _, err := conn.Write(msg.New(msg.Cverack, []byte{}).Encode()); err != nil { panic(err) } n.sendInvAndAddr(conn, resp.Ver.Protocol()) // wait for addr and inv messages m = msg.Must(msg.ReadKind(conn, msg.Caddr)) resp.Peers, err = payload.AddrDecode(resp.Ver.Protocol(), m.Payload()) if err != nil { panic(err) } m = msg.Must(msg.ReadKind(conn, msg.Cinv)) resp.Inv, err = payload.InventoryDecode(resp.Ver.Protocol(), m.Payload()) if err != nil { panic(err) } n.Log.Printf("[INFO] version exchange with %v successful", addr.Addr()) }
func (n *Node) versionSequence(m *msg.Msg, conn net.Conn) { resp := &VerDat{} defer func() { if r := recover(); r != nil { resp.Err = fmt.Errorf("[ERR] version sequence did not complete (%v)", r) n.Log.Print(resp.Err) } }() var err error n.Log.Printf("[INFO] version sequence with %v", conn.RemoteAddr()) resp.Ver, err = payload.VersionDecode(m.Payload()) if err != nil { panic(err) } defer func() { n.VerIn <- resp }() if _, err := conn.Write(msg.New(msg.Cverack, []byte{}).Encode()); err != nil { panic(err) } n.verOutVerackIn(conn, resp.Ver.FromAddr, resp.Ver.Protocol()) n.sendInvAndAddr(conn, resp.Ver.Protocol()) // wait for addr and inv messages m = msg.Must(msg.ReadKind(conn, msg.Caddr)) resp.Peers, err = payload.AddrDecode(resp.Ver.Protocol(), m.Payload()) if err != nil { panic(err) } m = msg.Must(msg.ReadKind(conn, msg.Cinv)) resp.Inv, err = payload.InventoryDecode(resp.Ver.Protocol(), m.Payload()) if err != nil { panic(err) } n.Log.Printf("[INFO] version sequence with %v successful", conn.RemoteAddr()) }