// addNode adds an address to the set of nodes on the network. func (g *Gateway) addNode(addr modules.NetAddress) error { if addr == g.myAddr { return errOurAddress } else if _, exists := g.nodes[addr]; exists { return errNodeExists } else if addr.IsStdValid() != nil { return errors.New("address is not valid: " + string(addr)) } else if net.ParseIP(addr.Host()) == nil { return errors.New("address must be an IP address: " + string(addr)) } g.nodes[addr] = struct{}{} return nil }
// managedConnect establishes a persistent connection to a peer, and adds it to // the Gateway's peer list. func (g *Gateway) managedConnect(addr modules.NetAddress) error { // Perform verification on the input address. g.mu.RLock() gaddr := g.myAddr g.mu.RUnlock() if addr == gaddr { return errors.New("can't connect to our own address") } if err := addr.IsStdValid(); err != nil { return errors.New("can't connect to invalid address") } if net.ParseIP(addr.Host()) == nil { return errors.New("address must be an IP address") } g.mu.RLock() _, exists := g.peers[addr] g.mu.RUnlock() if exists { return errPeerExists } // Dial the peer and perform peer initialization. conn, err := g.dial(addr) if err != nil { return err } // Perform peer initialization. remoteVersion, err := connectVersionHandshake(conn, build.Version) if err != nil { conn.Close() return err } if build.VersionCmp(remoteVersion, handshakeUpgradeVersion) < 0 { err = g.managedConnectOldPeer(conn, remoteVersion, addr) } else { err = g.managedConnectNewPeer(conn, remoteVersion, addr) } if err != nil { conn.Close() return err } g.log.Debugln("INFO: connected to new peer", addr) // Connection successful, clear the timeout as to maintain a persistent // connection to this peer. conn.SetDeadline(time.Time{}) // call initRPCs g.mu.RLock() for name, fn := range g.initRPCs { go func(name string, fn modules.RPCFunc) { if g.threads.Add() != nil { return } defer g.threads.Done() err := g.managedRPC(addr, name, fn) if err != nil { g.log.Debugf("INFO: RPC %q on peer %q failed: %v", name, addr, err) } }(name, fn) } g.mu.RUnlock() return nil }