mirror of
https://github.com/ipfs/kubo.git
synced 2025-08-06 11:31:54 +08:00
268 lines
6.2 KiB
Go
268 lines
6.2 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"math"
|
|
"os"
|
|
gopath "path"
|
|
"time"
|
|
|
|
random "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-random"
|
|
commands "github.com/ipfs/go-ipfs/commands"
|
|
core "github.com/ipfs/go-ipfs/core"
|
|
corehttp "github.com/ipfs/go-ipfs/core/corehttp"
|
|
corerouting "github.com/ipfs/go-ipfs/core/corerouting"
|
|
"github.com/ipfs/go-ipfs/core/coreunix"
|
|
"github.com/ipfs/go-ipfs/repo"
|
|
config "github.com/ipfs/go-ipfs/repo/config"
|
|
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
|
|
ds2 "github.com/ipfs/go-ipfs/thirdparty/datastore2"
|
|
"github.com/ipfs/go-ipfs/thirdparty/ipfsaddr"
|
|
unit "github.com/ipfs/go-ipfs/thirdparty/unit"
|
|
"gx/ipfs/QmZ6A6P6AMo8SR3jXAwzTuSU6B9R2Y4eqW2yW9VvfUayDN/go-datastore"
|
|
syncds "gx/ipfs/QmZ6A6P6AMo8SR3jXAwzTuSU6B9R2Y4eqW2yW9VvfUayDN/go-datastore/sync"
|
|
|
|
pstore "gx/ipfs/QmXHUpFsnpCmanRnacqYkFoLoFfEq5yS2nUgGkAjJ1Nj9j/go-libp2p-peerstore"
|
|
logging "gx/ipfs/QmYtB7Qge8cJpXc4irsEp8zRqfnZMBeB7aTrMEkPk67DRv/go-log"
|
|
ma "gx/ipfs/QmYzDkkgAEmrcNzFCiYo6L1dTX4EAG1gZkbtdbd9trL4vd/go-multiaddr"
|
|
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
|
|
)
|
|
|
|
var elog = logging.Logger("gc-client")
|
|
|
|
var (
|
|
cat = flag.Bool("cat", false, "else add")
|
|
seed = flag.Int64("seed", 1, "")
|
|
nBitsForKeypair = flag.Int("b", 1024, "number of bits for keypair (if repo is uninitialized)")
|
|
)
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
if err := run(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "error: %s\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func run() error {
|
|
servers := config.DefaultSNRServers
|
|
fmt.Println("using gcr remotes:")
|
|
for _, p := range servers {
|
|
fmt.Println("\t", p)
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
repoPath := gopath.Join(cwd, config.DefaultPathName)
|
|
if err := ensureRepoInitialized(repoPath); err != nil {
|
|
}
|
|
repo, err := fsrepo.Open(repoPath)
|
|
if err != nil { // owned by node
|
|
return err
|
|
}
|
|
cfg, err := repo.Config()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cfg.Bootstrap = servers
|
|
if err := repo.SetConfig(cfg); err != nil {
|
|
return err
|
|
}
|
|
|
|
var addrs []ipfsaddr.IPFSAddr
|
|
for _, info := range servers {
|
|
addr, err := ipfsaddr.ParseString(info)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
addrs = append(addrs, addr)
|
|
}
|
|
|
|
var infos []pstore.PeerInfo
|
|
for _, addr := range addrs {
|
|
infos = append(infos, pstore.PeerInfo{
|
|
ID: addr.ID(),
|
|
Addrs: []ma.Multiaddr{addr.Transport()},
|
|
})
|
|
}
|
|
|
|
node, err := core.NewNode(ctx, &core.BuildCfg{
|
|
Online: true,
|
|
Repo: repo,
|
|
Routing: corerouting.SupernodeClient(infos...),
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer node.Close()
|
|
|
|
opts := []corehttp.ServeOption{
|
|
corehttp.CommandsOption(cmdCtx(node, repoPath)),
|
|
corehttp.GatewayOption(false, nil),
|
|
}
|
|
|
|
if *cat {
|
|
if err := runFileCattingWorker(ctx, node); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
if err := runFileAddingWorker(node); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return corehttp.ListenAndServe(node, cfg.Addresses.API, opts...)
|
|
}
|
|
|
|
func ensureRepoInitialized(path string) error {
|
|
if !fsrepo.IsInitialized(path) {
|
|
conf, err := config.Init(ioutil.Discard, *nBitsForKeypair)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := fsrepo.Init(path, conf); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func sizeOfIthFile(i int64) int64 {
|
|
return (1 << uint64(i)) * unit.KB
|
|
}
|
|
|
|
func runFileAddingWorker(n *core.IpfsNode) error {
|
|
errs := make(chan error)
|
|
go func() {
|
|
var i int64
|
|
for i = 1; i < math.MaxInt32; i++ {
|
|
piper, pipew := io.Pipe()
|
|
go func() {
|
|
defer pipew.Close()
|
|
if err := random.WritePseudoRandomBytes(sizeOfIthFile(i), pipew, *seed); err != nil {
|
|
errs <- err
|
|
}
|
|
}()
|
|
k, err := coreunix.Add(n, piper)
|
|
if err != nil {
|
|
errs <- err
|
|
}
|
|
log.Println("added file", "seed", *seed, "#", i, "key", k, "size", unit.Information(sizeOfIthFile(i)))
|
|
time.Sleep(1 * time.Second)
|
|
}
|
|
}()
|
|
|
|
var i int64
|
|
for i = 0; i < math.MaxInt32; i++ {
|
|
err := <-errs
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func runFileCattingWorker(ctx context.Context, n *core.IpfsNode) error {
|
|
conf, err := config.Init(ioutil.Discard, *nBitsForKeypair)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
r := &repo.Mock{
|
|
D: ds2.CloserWrap(syncds.MutexWrap(datastore.NewMapDatastore())),
|
|
C: *conf,
|
|
}
|
|
dummy, err := core.NewNode(ctx, &core.BuildCfg{
|
|
Repo: r,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
errs := make(chan error)
|
|
|
|
go func() {
|
|
defer dummy.Close()
|
|
var i int64 = 1
|
|
for {
|
|
buf := new(bytes.Buffer)
|
|
if err := random.WritePseudoRandomBytes(sizeOfIthFile(i), buf, *seed); err != nil {
|
|
errs <- err
|
|
}
|
|
// add to a dummy node to discover the key
|
|
k, err := coreunix.Add(dummy, bytes.NewReader(buf.Bytes()))
|
|
if err != nil {
|
|
errs <- err
|
|
}
|
|
e := elog.EventBegin(ctx, "cat", logging.LoggableF(func() map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"key": k,
|
|
"localPeer": n.Identity,
|
|
}
|
|
}))
|
|
if r, err := coreunix.Cat(ctx, n, k); err != nil {
|
|
e.Done()
|
|
log.Printf("failed to cat file. seed: %d #%d key: %s err: %s", *seed, i, k, err)
|
|
} else {
|
|
log.Println("found file", "seed", *seed, "#", i, "key", k, "size", unit.Information(sizeOfIthFile(i)))
|
|
io.Copy(ioutil.Discard, r)
|
|
e.Done()
|
|
log.Println("catted file", "seed", *seed, "#", i, "key", k, "size", unit.Information(sizeOfIthFile(i)))
|
|
i++
|
|
}
|
|
time.Sleep(time.Second)
|
|
}
|
|
}()
|
|
|
|
err = <-errs
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func toPeerInfos(bpeers []config.BootstrapPeer) ([]pstore.PeerInfo, error) {
|
|
var peers []pstore.PeerInfo
|
|
for _, bootstrap := range bpeers {
|
|
p, err := toPeerInfo(bootstrap)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
peers = append(peers, p)
|
|
}
|
|
return peers, nil
|
|
}
|
|
|
|
func toPeerInfo(bootstrap config.BootstrapPeer) (p pstore.PeerInfo, err error) {
|
|
p = pstore.PeerInfo{
|
|
ID: bootstrap.ID(),
|
|
Addrs: []ma.Multiaddr{bootstrap.Multiaddr()},
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
func cmdCtx(node *core.IpfsNode, repoPath string) commands.Context {
|
|
return commands.Context{
|
|
Online: true,
|
|
ConfigRoot: repoPath,
|
|
LoadConfig: func(path string) (*config.Config, error) {
|
|
return node.Repo.Config()
|
|
},
|
|
ConstructNode: func() (*core.IpfsNode, error) {
|
|
return node, nil
|
|
},
|
|
}
|
|
}
|