// Fetch a given number of best (most recenty seen) peers. // Set unconnected to true to only get those that we are not connected to. func GetBestPeers(limit uint, unconnected bool) (res manyPeers) { if proxyPeer != nil { if !unconnected || !ConnectionActive(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 && utils.ValidIp4(ad.Ip4[:]) && !common.IsIPBlocked(ad.Ip4[:]) { if !unconnected || !ConnectionActive(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 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") //println("ParseAddr:", n, e) break } a := NewPeer(buf[:]) if !utils.ValidIp4(a.Ip4[:]) { common.CountSafe("AddrInvalid") } 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(ExpirePeerAfter)) { k := qdb.KeyType(a.UniqID()) v := PeerDB.Get(k) if v != nil { a.Banned = NewPeer(v[:]).Banned } PeerDB.Put(k, a.Bytes()) } else { common.CountSafe("AddrStale") } } else { common.CountSafe("AddrInFuture") } } }
func main() { var dir string if len(os.Args) > 1 { dir = os.Args[1] } else { dir = utils.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 !utils.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 < 25; 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) } }
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.Mutex.Unlock() if utils.ValidIp4(pl[40:44]) { ExternalIpMutex.Lock() c.Node.ReportedIp4 = binary.BigEndian.Uint32(pl[40:44]) 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() } } else { return errors.New("common.Version message too short") } c.SendRawMsg("verack", []byte{}) return nil }