func reuseDial(dialer net.Dialer, laddr, raddr ma.Multiaddr) (conn net.Conn, retry bool, err error) { if laddr == nil { // if we're given no local address no sense in using reuseport to dial, dial out as usual. return nil, true, reuseport.ErrReuseFailed } // give reuse.Dialer the manet.Dialer's Dialer. // (wow, Dialer should've so been an interface...) rd := reuseport.Dialer{dialer} // get the local net.Addr manually rd.D.LocalAddr, err = manet.ToNetAddr(laddr) if err != nil { return nil, true, err // something wrong with laddr. retry without. } // get the raddr dial args for rd.dial network, netraddr, err := manet.DialArgs(raddr) if err != nil { return nil, true, err // something wrong with laddr. retry without. } // rd.Dial gets us a net.Conn with SO_REUSEPORT and SO_REUSEADDR set. conn, err = rd.Dial(network, netraddr) return conn, reuseErrShouldRetry(err), err // hey! it worked! }
func apiClientForAddr(addr ma.Multiaddr) (cmdsHttp.Client, error) { _, host, err := manet.DialArgs(addr) if err != nil { return nil, err } return cmdsHttp.NewClient(host), nil }
func main() { flag.Parse() // extract address from host flag addr, err := ma.NewMultiaddr(*host) if err != nil { log.WithField("err", err).Fatal("NewMultiaddr() failed") } p := addr.Protocols() if len(p) < 2 { log.WithField("addr", addr).Fatal("need two protocols in host flag (/ip/tcp)") } _, host, err := manet.DialArgs(addr) if err != nil { log.WithField("err", err).Fatal("manet.DialArgs() failed") } if *verbose { // lower log level log.SetLevel(log.DebugLevel) } // construct url to dial var u url.URL u.Scheme = "http" u.Host = host u.Path = *endpoint // show what we got start := time.Now() log.WithFields(log.Fields{ "when": start, "tries": *tries, "timeout": *timeout, "url": u.String(), }).Debug("starting") for *tries > 0 { f := log.Fields{"tries": *tries} err := checkOK(http.Get(u.String())) if err == nil { f["took"] = time.Since(start) log.WithFields(f).Println("status ok - endpoint reachable") os.Exit(0) } f["error"] = err log.WithFields(f).Debug("get failed") time.Sleep(*timeout) *tries-- } log.Println("failed.") os.Exit(1) }
// rawConnDial dials the underlying net.Conn + manet.Conns func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote peer.ID) (manet.Conn, error) { // before doing anything, check we're going to be able to dial. // we may not support the given address. if _, _, err := manet.DialArgs(raddr); err != nil { return nil, err } if strings.HasPrefix(raddr.String(), "/ip4/0.0.0.0") { log.Event(ctx, "connDialZeroAddr", lgbl.Dial("conn", d.LocalPeer, remote, nil, raddr)) return nil, fmt.Errorf("Attempted to connect to zero address: %s", raddr) } // get local addr to use. laddr := pickLocalAddr(d.LocalAddrs, raddr) logdial := lgbl.Dial("conn", d.LocalPeer, remote, laddr, raddr) defer log.EventBegin(ctx, "connDialRawConn", logdial).Done() // make a copy of the manet.Dialer, we may need to change its timeout. madialer := d.Dialer if laddr != nil && reuseportIsAvailable() { // we're perhaps going to dial twice. half the timeout, so we can afford to. // otherwise our context would expire right after the first dial. madialer.Dialer.Timeout = (madialer.Dialer.Timeout / 2) // dial using reuseport.Dialer, because we're probably reusing addrs. // this is optimistic, as the reuseDial may fail to bind the port. rpev := log.EventBegin(ctx, "connDialReusePort", logdial) if nconn, retry, reuseErr := reuseDial(madialer.Dialer, laddr, raddr); reuseErr == nil { // if it worked, wrap the raw net.Conn with our manet.Conn logdial["reuseport"] = "success" rpev.Done() return manet.WrapNetConn(nconn) } else if !retry { // reuseDial is sure this is a legitimate dial failure, not a reuseport failure. logdial["reuseport"] = "failure" logdial["error"] = reuseErr rpev.Done() return nil, reuseErr } else { // this is a failure to reuse port. log it. logdial["reuseport"] = "retry" logdial["error"] = reuseErr rpev.Done() } } defer log.EventBegin(ctx, "connDialManet", logdial).Done() return madialer.Dial(raddr) }
func (f *Filters) AddrBlocked(a ma.Multiaddr) bool { _, addr, err := manet.DialArgs(a) if err != nil { // if we cant parse it, its probably not blocked return false } ipstr := strings.Split(addr, ":")[0] ip := net.ParseIP(ipstr) for _, ft := range f.filters { if ft.Contains(ip) { return true } } return false }
// NewMapping attemps to construct a mapping on protocol and internal port // It will also periodically renew the mapping until the returned Mapping // -- or its parent NAT -- is Closed. // // May not succeed, and mappings may change over time; // NAT devices may not respect our port requests, and even lie. // Clients should not store the mapped results, but rather always // poll our object for the latest mappings. func (nat *NAT) NewMapping(maddr ma.Multiaddr) (Mapping, error) { if nat == nil { return nil, fmt.Errorf("no nat available") } network, addr, err := manet.DialArgs(maddr) if err != nil { return nil, fmt.Errorf("DialArgs failed on addr:", maddr.String()) } switch network { case "tcp", "tcp4", "tcp6": network = "tcp" case "udp", "udp4", "udp6": network = "udp" default: return nil, fmt.Errorf("transport not supported by NAT: %s", network) } intports := strings.Split(addr, ":")[1] intport, err := strconv.Atoi(intports) if err != nil { return nil, err } m := &mapping{ nat: nat, proto: network, intport: intport, intaddr: maddr, } m.proc = goprocess.WithTeardown(func() error { nat.rmMapping(m) return nil }) nat.addMapping(m) m.proc.AddChild(periodic.Every(MappingDuration/3, func(worker goprocess.Process) { nat.establishMapping(m) })) // do it once synchronously, so first mapping is done right away, and before exiting, // allowing users -- in the optimistic case -- to use results right after. nat.establishMapping(m) return m, nil }
func manetListen(addr ma.Multiaddr) (manet.Listener, error) { network, naddr, err := manet.DialArgs(addr) if err != nil { return nil, err } if reuseportIsAvailable() { nl, err := reuseport.Listen(network, naddr) if err == nil { // hey, it worked! return manet.WrapNetListener(nl) } // reuseport is available, but we failed to listen. log debug, and retry normally. log.Debugf("reuseport available, but failed to listen: %s %s, %s", network, naddr, err) } // either reuseport not available, or it failed. try normally. return manet.Listen(addr) }
func IpfsStart(waitall bool) error { var addrs []string n := GetNumNodes() for i := 0; i < n; i++ { dir := IpfsDirN(i) cmd := exec.Command("ipfs", "daemon") cmd.Dir = dir cmd.Env = []string{"IPFS_PATH=" + dir} cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true} stdout, err := os.Create(path.Join(dir, "daemon.stdout")) if err != nil { return err } stderr, err := os.Create(path.Join(dir, "daemon.stderr")) if err != nil { return err } cmd.Stdout = stdout cmd.Stderr = stderr err = cmd.Start() if err != nil { return err } pid := cmd.Process.Pid fmt.Printf("Started daemon %d, pid = %d\n", i, pid) err = ioutil.WriteFile(path.Join(dir, "daemon.pid"), []byte(fmt.Sprint(pid)), 0666) if err != nil { return err } // Make sure node 0 is up before starting the rest so // bootstrapping works properly if i == 0 || waitall { cfg, err := serial.Load(path.Join(IpfsDirN(i), "config")) if err != nil { return err } maddr := ma.StringCast(cfg.Addresses.API) _, addr, err := manet.DialArgs(maddr) if err != nil { return err } addrs = append(addrs, addr) err = waitOnAPI(cfg.Identity.PeerID, addr) if err != nil { return err } } } if waitall { for i := 0; i < n; i++ { err := waitOnSwarmPeers(addrs[i]) if err != nil { return err } } } return nil }