// currently just uses the ipfs core bootstrap nodes // TODO: allow user to specify their own func getBootstrapAddrs() ([]ma.Multiaddr, error) { addrs := []string{ "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", "/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx", "/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", "/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", "/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", "/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", } var maddrs []ma.Multiaddr for _, s := range addrs { a, err := ma.NewMultiaddr(s) if err != nil { return nil, err } maddrs = append(maddrs, a) } return maddrs, nil }
// APIAddr returns the registered API addr, according to the api file // in the fsrepo. This is a concurrent operation, meaning that any // process may read this file. modifying this file, therefore, should // use "mv" to replace the whole file and avoid interleaved read/writes. func APIAddr(repoPath string) (ma.Multiaddr, error) { repoPath = filepath.Clean(repoPath) apiFilePath := filepath.Join(repoPath, apiFile) // if there is no file, assume there is no api addr. f, err := os.Open(apiFilePath) if err != nil { if os.IsNotExist(err) { return nil, repo.ErrApiNotRunning } return nil, err } defer f.Close() // read up to 2048 bytes. io.ReadAll is a vulnerability, as // someone could hose the process by putting a massive file there. buf := make([]byte, 2048) n, err := f.Read(buf) if err != nil && err != io.EOF { return nil, err } s := string(buf[:n]) s = strings.TrimSpace(s) return ma.NewMultiaddr(s) }
func newMultiaddr(t *testing.T, s string) ma.Multiaddr { maddr, err := ma.NewMultiaddr(s) if err != nil { t.Fatal(err) } return maddr }
func init() { // initialize ZeroLocalTCPAddress maddr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0") if err != nil { panic(err) } ZeroLocalTCPAddress = maddr }
// serveHTTPGateway collects options, creates listener, prints status message and starts serving requests func serveHTTPGateway(req cmds.Request) (error, <-chan error) { cfg, err := req.InvocContext().GetConfig() if err != nil { return fmt.Errorf("serveHTTPGateway: GetConfig() failed: %s", err), nil } gatewayMaddr, err := ma.NewMultiaddr(cfg.Addresses.Gateway) if err != nil { return fmt.Errorf("serveHTTPGateway: invalid gateway address: %q (err: %s)", cfg.Addresses.Gateway, err), nil } writable, writableOptionFound, err := req.Option(writableKwd).Bool() if err != nil { return fmt.Errorf("serveHTTPGateway: req.Option(%s) failed: %s", writableKwd, err), nil } if !writableOptionFound { writable = cfg.Gateway.Writable } gwLis, err := manet.Listen(gatewayMaddr) if err != nil { return fmt.Errorf("serveHTTPGateway: manet.Listen(%s) failed: %s", gatewayMaddr, err), nil } // we might have listened to /tcp/0 - lets see what we are listing on gatewayMaddr = gwLis.Multiaddr() if writable { fmt.Printf("Gateway (writable) server listening on %s\n", gatewayMaddr) } else { fmt.Printf("Gateway (readonly) server listening on %s\n", gatewayMaddr) } var opts = []corehttp.ServeOption{ corehttp.MetricsCollectionOption("gateway"), corehttp.CommandsROOption(*req.InvocContext()), corehttp.VersionOption(), corehttp.IPNSHostnameOption(), corehttp.GatewayOption(writable, "/ipfs", "/ipns"), } if len(cfg.Gateway.RootRedirect) > 0 { opts = append(opts, corehttp.RedirectOption("", cfg.Gateway.RootRedirect)) } node, err := req.InvocContext().ConstructNode() if err != nil { return fmt.Errorf("serveHTTPGateway: ConstructNode() failed: %s", err), nil } errc := make(chan error) go func() { errc <- corehttp.Serve(node, gwLis.NetListener(), opts...) close(errc) }() return nil, errc }
func listenAddresses(cfg *config.Config) ([]ma.Multiaddr, error) { var listen []ma.Multiaddr for _, addr := range cfg.Addresses.Swarm { maddr, err := ma.NewMultiaddr(addr) if err != nil { return nil, fmt.Errorf("Failure to parse config.Addresses.Swarm: %s", cfg.Addresses.Swarm) } listen = append(listen, maddr) } return listen, nil }
func TestParseMultiaddrBad(t *testing.T) { for _, b := range bad { m, err := ma.NewMultiaddr(b) if err != nil { continue // skip these. } if _, err := ParseMultiaddr(m); err == nil { t.Error("succeeded in parsing", m) } } }
// ParseString parses a string representation of an address into an IPFSAddr func ParseString(str string) (a IPFSAddr, err error) { if str == "" { return nil, ErrInvalidAddr } m, err := ma.NewMultiaddr(str) if err != nil { return nil, err } return ParseMultiaddr(m) }
// getApiClient checks the repo, and the given options, checking for // a running API service. if there is one, it returns a client. // otherwise, it returns errApiNotRunning, or another error. func getApiClient(repoPath, apiAddrStr string) (cmdsHttp.Client, error) { if apiAddrStr == "" { var err error if apiAddrStr, err = fsrepo.APIAddr(repoPath); err != nil { return nil, err } } addr, err := ma.NewMultiaddr(apiAddrStr) if err != nil { return nil, err } return apiClientForAddr(addr) }
// ListenAndServe runs an HTTP server listening at |listeningMultiAddr| with // the given serve options. The address must be provided in multiaddr format. // // TODO intelligently parse address strings in other formats so long as they // unambiguously map to a valid multiaddr. e.g. for convenience, ":8080" should // map to "/ip4/0.0.0.0/tcp/8080". func ListenAndServe(n *core.IpfsNode, listeningMultiAddr string, options ...ServeOption) error { addr, err := ma.NewMultiaddr(listeningMultiAddr) if err != nil { return err } list, err := manet.Listen(addr) if err != nil { return err } // we might have listened to /tcp/0 - lets see what we are listing on addr = list.Multiaddr() fmt.Printf("API server listening on %s\n", addr) return Serve(n, list.NetListener(), options...) }
func main() { flag.Parse() // extract address from host flag addr, err := ma.NewMultiaddr(*host) if err != nil { log.Fatal("NewMultiaddr() failed: ", err) } p := addr.Protocols() if len(p) < 2 { log.Fatal("need two protocols in host flag (/ip/tcp): ", addr) } _, host, err := manet.DialArgs(addr) if err != nil { log.Fatal("manet.DialArgs() failed: ", err) } if *verbose { // lower log level logging.SetDebugLogging() } // 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.Debug("starting at %s, tries: %d, timeout: %s, url: %s", start, *tries, *timeout, u) for *tries > 0 { err := checkOK(http.Get(u.String())) if err == nil { log.Debugf("ok - endpoint reachable with %d tries remaining, took %s", *tries, time.Since(start)) os.Exit(0) } log.Debug("get failed: ", err) time.Sleep(*timeout) *tries-- } log.Error("failed.") os.Exit(1) }
// RandLocalTCPAddress returns a random multiaddr. it suppresses errors // for nice composability-- do check the address isn't nil. // // NOTE: for real network tests, use ZeroLocalTCPAddress so the kernel // assigns an unused TCP port. otherwise you may get clashes. This // function remains here so that p2p/net/mock (which does not touch the // real network) can assign different addresses to peers. func RandLocalTCPAddress() ma.Multiaddr { // chances are it will work out, but it **might** fail if the port is in use // most ports above 10000 aren't in use by long running processes, so yay. // (maybe there should be a range of "loopback" ports that are guaranteed // to be open for the process, but naturally can only talk to self.) lastPort.Lock() if lastPort.port == 0 { lastPort.port = 10000 + SeededRand.Intn(50000) } port := lastPort.port lastPort.port++ lastPort.Unlock() addr := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port) maddr, _ := ma.NewMultiaddr(addr) return maddr }
func spawnDHT(pk ci.PrivKey, dstore repo.Datastore, bootstraps []ma.Multiaddr) (*dht.IpfsDHT, error) { pub := pk.GetPublic() local, err := peer.IDFromPublicKey(pub) if err != nil { return nil, err } fmt.Println("Local peer ID: ", local.Pretty()) ps := pstore.NewPeerstore() ps.AddPrivKey(local, pk) ps.AddPubKey(local, pub) listenaddr, err := ma.NewMultiaddr("/ip4/0.0.0.0/tcp/0") if err != nil { return nil, err } s, err := swarm.NewNetwork(context.Background(), []ma.Multiaddr{listenaddr}, local, ps, metrics.NewBandwidthCounter()) if err != nil { fatal(err) } host := basichost.New(s) idht := dht.NewDHT(context.Background(), host, dstore) idht.Validator[IpnsValidatorTag] = namesys.IpnsRecordValidator idht.Selector[IpnsValidatorTag] = namesys.IpnsSelectorFunc err = doBootstrap(host, idht, bootstraps) if err != nil { return nil, err } return idht, nil }
// getApiClient checks the repo, and the given options, checking for // a running API service. if there is one, it returns a client. // otherwise, it returns errApiNotRunning, or another error. func getApiClient(repoPath, apiAddrStr string) (cmdsHttp.Client, error) { var apiErrorFmt string switch { case osh.IsUnix(): apiErrorFmt = apiFileErrorFmt + checkIPFSUnixFmt case osh.IsWindows(): apiErrorFmt = apiFileErrorFmt + checkIPFSWinFmt default: apiErrorFmt = apiFileErrorFmt } var addr ma.Multiaddr var err error if len(apiAddrStr) != 0 { addr, err = ma.NewMultiaddr(apiAddrStr) if err != nil { return nil, err } if len(addr.Protocols()) == 0 { return nil, fmt.Errorf("mulitaddr doesn't provide any protocols") } } else { addr, err = fsrepo.APIAddr(repoPath) if err == repo.ErrApiNotRunning { return nil, err } if err != nil { return nil, fmt.Errorf(apiErrorFmt, repoPath, err.Error()) } } if len(addr.Protocols()) == 0 { return nil, fmt.Errorf(apiErrorFmt, repoPath, "multiaddr doesn't provide any protocols") } return apiClientForAddr(addr) }
func ParsePeerParam(text string) (ma.Multiaddr, peer.ID, error) { // to be replaced with just multiaddr parsing, once ptp is a multiaddr protocol idx := strings.LastIndex(text, "/") if idx == -1 { pid, err := peer.IDB58Decode(text) if err != nil { return nil, "", err } return nil, pid, nil } addrS := text[:idx] peeridS := text[idx+1:] var maddr ma.Multiaddr var pid peer.ID // make sure addrS parses as a multiaddr. if len(addrS) > 0 { var err error maddr, err = ma.NewMultiaddr(addrS) if err != nil { return nil, "", err } } // make sure idS parses as a peer.ID var err error pid, err = peer.IDB58Decode(peeridS) if err != nil { return nil, "", err } return maddr, pid, nil }
res.SetError(err, cmds.ErrNormal) return } if !n.OnlineMode() { res.SetError(errNotOnline, cmds.ErrClient) return } proto := "/app/" + req.Arguments()[0] if checkProtoExists(n.PeerHost.Mux().Protocols(), proto) { res.SetError(errors.New("Protocol handler already registered."), cmds.ErrNormal) return } addr, err := ma.NewMultiaddr(req.Arguments()[1]) if err != nil { res.SetError(err, cmds.ErrNormal) return } listener, err := corenet.Listen(n, proto) if err != nil { res.SetError(err, cmds.ErrNormal) return } app := cnAppInfo{ identity: n.Identity, protocol: proto, address: addr,
// serveHTTPApi collects options, creates listener, prints status message and starts serving requests func serveHTTPApi(req cmds.Request) (error, <-chan error) { cfg, err := req.InvocContext().GetConfig() if err != nil { return fmt.Errorf("serveHTTPApi: GetConfig() failed: %s", err), nil } apiAddr, _, err := req.Option(commands.ApiOption).String() if err != nil { return fmt.Errorf("serveHTTPApi: %s", err), nil } if apiAddr == "" { apiAddr = cfg.Addresses.API } apiMaddr, err := ma.NewMultiaddr(apiAddr) if err != nil { return fmt.Errorf("serveHTTPApi: invalid API address: %q (err: %s)", apiAddr, err), nil } apiLis, err := manet.Listen(apiMaddr) if err != nil { return fmt.Errorf("serveHTTPApi: manet.Listen(%s) failed: %s", apiMaddr, err), nil } // we might have listened to /tcp/0 - lets see what we are listing on apiMaddr = apiLis.Multiaddr() fmt.Printf("API server listening on %s\n", apiMaddr) // by default, we don't let you load arbitrary ipfs objects through the api, // because this would open up the api to scripting vulnerabilities. // only the webui objects are allowed. // if you know what you're doing, go ahead and pass --unrestricted-api. unrestricted, _, err := req.Option(unrestrictedApiAccessKwd).Bool() if err != nil { return fmt.Errorf("serveHTTPApi: Option(%s) failed: %s", unrestrictedApiAccessKwd, err), nil } gatewayOpt := corehttp.GatewayOption(false, corehttp.WebUIPaths...) if unrestricted { gatewayOpt = corehttp.GatewayOption(true, "/ipfs", "/ipns") } var opts = []corehttp.ServeOption{ corehttp.MetricsCollectionOption("api"), corehttp.CommandsOption(*req.InvocContext()), corehttp.WebUIOption, gatewayOpt, corehttp.VersionOption(), defaultMux("/debug/vars"), defaultMux("/debug/pprof/"), corehttp.MetricsScrapingOption("/debug/metrics/prometheus"), corehttp.LogOption(), } if len(cfg.Gateway.RootRedirect) > 0 { opts = append(opts, corehttp.RedirectOption("", cfg.Gateway.RootRedirect)) } node, err := req.InvocContext().ConstructNode() if err != nil { return fmt.Errorf("serveHTTPApi: ConstructNode() failed: %s", err), nil } if err := node.Repo.SetAPIAddr(apiMaddr); err != nil { return fmt.Errorf("serveHTTPApi: SetAPIAddr() failed: %s", err), nil } errc := make(chan error) go func() { errc <- corehttp.Serve(node, apiLis.NetListener(), opts...) close(errc) }() return nil, errc }