// Fetch a given number of best (most recenty seen) peers. func GetBestPeers(limit uint, isConnected func(*PeerAddr) bool) (res manyPeers) { if proxyPeer != nil { if isConnected == nil || !isConnected(proxyPeer) { return manyPeers{proxyPeer} } return manyPeers{} } peerdb_mutex.Lock() tmp := make(manyPeers, 0) PeerDB.Browse(func(k qdb.KeyType, v []byte) uint32 { ad := NewPeer(v) if ad.Banned == 0 && sys.ValidIp4(ad.Ip4[:]) && !sys.IsIPBlocked(ad.Ip4[:]) { if isConnected == nil || !isConnected(ad) { tmp = append(tmp, ad) } } return 0 }) peerdb_mutex.Unlock() // Copy the top rows to the result buffer if len(tmp) > 0 { sort.Sort(tmp) if uint(len(tmp)) < limit { limit = uint(len(tmp)) } res = make(manyPeers, limit) copy(res, tmp[:limit]) } return }
// Parese network's "addr" message func (c *OneConnection) ParseAddr(pl []byte) { b := bytes.NewBuffer(pl) cnt, _ := btc.ReadVLen(b) for i := 0; i < int(cnt); i++ { var buf [30]byte n, e := b.Read(buf[:]) if n != len(buf) || e != nil { common.CountSafe("AddrError") c.DoS("AddrError") //println("ParseAddr:", n, e) break } a := peersdb.NewPeer(buf[:]) if !sys.ValidIp4(a.Ip4[:]) { c.Misbehave("AddrLocal", 2) } else if time.Unix(int64(a.Time), 0).Before(time.Now().Add(time.Minute)) { if time.Now().Before(time.Unix(int64(a.Time), 0).Add(peersdb.ExpirePeerAfter)) { k := qdb.KeyType(a.UniqID()) v := peersdb.PeerDB.Get(k) if v != nil { a.Banned = peersdb.NewPeer(v[:]).Banned } peersdb.PeerDB.Put(k, a.Bytes()) } else { common.CountSafe("AddrStale") } } else { c.Misbehave("AddrFuture", 5) } } }
func (c *OneConnection) HandleVersion(pl []byte) error { if len(pl) >= 80 /*Up to, includiong, the nonce */ { c.Mutex.Lock() c.Node.Version = binary.LittleEndian.Uint32(pl[0:4]) if bytes.Equal(pl[72:80], nonce[:]) { c.Mutex.Unlock() return errors.New("Connecting to ourselves") } if c.Node.Version < MIN_PROTO_VERSION { c.Mutex.Unlock() return errors.New("Client version too low") } c.Node.Services = binary.LittleEndian.Uint64(pl[4:12]) c.Node.Timestamp = binary.LittleEndian.Uint64(pl[12:20]) c.Node.ReportedIp4 = binary.BigEndian.Uint32(pl[40:44]) if len(pl) >= 86 { le, of := btc.VLen(pl[80:]) of += 80 c.Node.Agent = string(pl[of : of+le]) of += le if len(pl) >= of+4 { c.Node.Height = binary.LittleEndian.Uint32(pl[of : of+4]) c.X.GetBlocksDataNow = true of += 4 if len(pl) > of && pl[of] == 0 { c.Node.DoNotRelayTxs = true } } } c.Mutex.Unlock() if sys.ValidIp4(pl[40:44]) { ExternalIpMutex.Lock() _, use_this_ip := ExternalIp4[c.Node.ReportedIp4] if !use_this_ip { // New IP use_this_ip = true for x, v := range IgnoreExternalIpFrom { if c.Node.Agent == v { use_this_ip = false common.CountSafe(fmt.Sprint("IgnoreExtIP", x)) break } } if use_this_ip { fmt.Printf("New external IP %d.%d.%d.%d from %s\n> ", pl[40], pl[41], pl[42], pl[43], c.Node.Agent) } } if use_this_ip { ExternalIp4[c.Node.ReportedIp4] = [2]uint{ExternalIp4[c.Node.ReportedIp4][0] + 1, uint(time.Now().Unix())} } ExternalIpMutex.Unlock() } } else { return errors.New("version message too short") } c.SendRawMsg("verack", []byte{}) return nil }
func parse_addr(pl []byte) { b := bytes.NewBuffer(pl) cnt, _ := btc.ReadVLen(b) for i := 0; i < int(cnt); i++ { var buf [30]byte n, e := b.Read(buf[:]) if n != len(buf) || e != nil { COUNTER("ADER") break } a := peersdb.NewPeer(buf[:]) if !sys.ValidIp4(a.Ip4[:]) { COUNTER("ADNO") } else if time.Unix(int64(a.Time), 0).Before(time.Now().Add(time.Minute)) { if time.Now().Before(time.Unix(int64(a.Time), 0).Add(peersdb.ExpirePeerAfter)) { k := qdb.KeyType(a.UniqID()) v := peersdb.PeerDB.Get(k) if v != nil { a.Banned = peersdb.NewPeer(v[:]).Banned } peersdb.PeerDB.Put(k, a.Bytes()) } else { COUNTER("ADST") } } else { COUNTER("ADFU") } } }
func (c *OneConnection) HandleVersion(pl []byte) error { if len(pl) >= 80 /*Up to, includiong, the nonce */ { var new_ext_ip bool c.Mutex.Lock() c.Node.Version = binary.LittleEndian.Uint32(pl[0:4]) if bytes.Equal(pl[72:80], nonce[:]) { c.Mutex.Unlock() return errors.New("Connecting to ourselves") } if c.Node.Version < MIN_PROTO_VERSION { c.Mutex.Unlock() return errors.New("Client version too low") } c.Node.Services = binary.LittleEndian.Uint64(pl[4:12]) c.Node.Timestamp = binary.LittleEndian.Uint64(pl[12:20]) c.Mutex.Unlock() if sys.ValidIp4(pl[40:44]) { ExternalIpMutex.Lock() c.Node.ReportedIp4 = binary.BigEndian.Uint32(pl[40:44]) _, new_ext_ip = ExternalIp4[c.Node.ReportedIp4] new_ext_ip = !new_ext_ip ExternalIp4[c.Node.ReportedIp4] = [2]uint{ExternalIp4[c.Node.ReportedIp4][0] + 1, uint(time.Now().Unix())} ExternalIpMutex.Unlock() } if len(pl) >= 86 { c.Mutex.Lock() le, of := btc.VLen(pl[80:]) of += 80 c.Node.Agent = string(pl[of : of+le]) of += le if len(pl) >= of+4 { c.Node.Height = binary.LittleEndian.Uint32(pl[of : of+4]) of += 4 if len(pl) > of && pl[of] == 0 { c.Node.DoNotRelayTxs = true } } c.Mutex.Unlock() } if new_ext_ip { print("New external IP from ", c.Node.Agent, "\n> ") } } else { return errors.New("version message too short") } c.SendRawMsg("verack", []byte{}) return nil }
func main() { var dir string if len(os.Args) > 1 { dir = os.Args[1] } else { dir = sys.BitcoinHome() + "gocoin" + string(os.PathSeparator) + "btcnet" + string(os.PathSeparator) + "peers3" } db, er := qdb.NewDB(dir, true) if er != nil { println(er.Error()) os.Exit(1) } println(db.Count(), "peers in databse", dir) if db.Count() == 0 { return } tmp := make(manyPeers, db.Count()) cnt := 0 db.Browse(func(k qdb.KeyType, v []byte) uint32 { np := utils.NewPeer(v) if !sys.ValidIp4(np.Ip4[:]) { return 0 } if cnt < len(tmp) { tmp[cnt] = np cnt++ } return 0 }) sort.Sort(tmp[:cnt]) for cnt = 0; cnt < len(tmp) && cnt < 2500; cnt++ { ad := tmp[cnt] fmt.Printf("%3d) %16s %5d - seen %5d min ago\n", cnt+1, fmt.Sprintf("%d.%d.%d.%d", ad.Ip4[0], ad.Ip4[1], ad.Ip4[2], ad.Ip4[3]), ad.Port, (time.Now().Unix()-int64(ad.Time))/60) } }
// Parese network's "addr" message func (c *OneConnection) ParseAddr(pl []byte) { b := bytes.NewBuffer(pl) cnt, _ := btc.ReadVLen(b) for i := 0; i < int(cnt); i++ { var buf [30]byte n, e := b.Read(buf[:]) if n != len(buf) || e != nil { common.CountSafe("AddrError") c.DoS("AddrError") //println("ParseAddr:", n, e) break } a := peersdb.NewPeer(buf[:]) if !sys.ValidIp4(a.Ip4[:]) { //common.CountSafe("AddrLocal") if c.Misbehave("AddrLocal", 1) { break } //print(c.PeerAddr.Ip(), " ", c.Node.Agent, " ", c.Node.Version, " addr local ", a.String(), "\n> ") } else if time.Unix(int64(a.Time), 0).Before(time.Now().Add(time.Minute)) { if time.Now().Before(time.Unix(int64(a.Time), 0).Add(peersdb.ExpirePeerAfter)) { k := qdb.KeyType(a.UniqID()) v := peersdb.PeerDB.Get(k) if v != nil { a.Banned = peersdb.NewPeer(v[:]).Banned } a.Time = uint32(time.Now().Add(-5 * time.Minute).Unix()) // add new peers as not just alive peersdb.PeerDB.Put(k, a.Bytes()) } else { common.CountSafe("AddrStale") } } else { if c.Misbehave("AddrFuture", 50) { break } } } }