// Connect establishes a persistent connection to a peer, and adds it to the // Gateway's peer list. func (g *Gateway) Connect(addr modules.NetAddress) error { if addr == g.Address() { return errors.New("can't connect to our own address") } if build.Release != "testing" && addr.IsLoopback() { return errors.New("can't connect to loopback address") } id := g.mu.RLock() _, exists := g.peers[addr] g.mu.RUnlock(id) if exists { return errors.New("peer already added") } conn, err := net.DialTimeout("tcp", string(addr), dialTimeout) if err != nil { return err } // send our version if err := encoding.WriteObject(conn, build.Version); err != nil { return err } // read version ack var remoteVersion string if err := encoding.ReadObject(conn, &remoteVersion, maxAddrLength); err != nil { return err } else if remoteVersion == "reject" { return errors.New("peer rejected connection") } // decide whether to accept this version if build.VersionCmp(remoteVersion, "0.3.3") < 0 { conn.Close() return errors.New("unacceptable version: " + remoteVersion) } g.log.Println("INFO: connected to new peer", addr) id = g.mu.Lock() g.addPeer(&peer{addr: addr, sess: muxado.Client(conn), inbound: false}) g.mu.Unlock(id) // call initRPCs id = g.mu.RLock() for name, fn := range g.initRPCs { go g.RPC(addr, name, fn) } g.mu.RUnlock(id) return nil }