mirror of
https://github.com/ipfs/kubo.git
synced 2025-09-10 11:52:21 +08:00
go lint
link errors left: - protocol buffers output is not lint-friendly
This commit is contained in:
@ -7,14 +7,14 @@ import (
|
|||||||
mh "github.com/jbenet/go-multihash"
|
mh "github.com/jbenet/go-multihash"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Blocks is the ipfs blocks service. It is the way
|
// Block is the ipfs blocks service. It is the way
|
||||||
// to retrieve blocks by the higher level ipfs modules
|
// to retrieve blocks by the higher level ipfs modules
|
||||||
|
|
||||||
type Block struct {
|
type Block struct {
|
||||||
Multihash mh.Multihash
|
Multihash mh.Multihash
|
||||||
Data []byte
|
Data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewBlock creates a Block object from opaque data. It will hash the data.
|
||||||
func NewBlock(data []byte) (*Block, error) {
|
func NewBlock(data []byte) (*Block, error) {
|
||||||
h, err := u.Hash(data)
|
h, err := u.Hash(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -23,15 +23,19 @@ func NewBlock(data []byte) (*Block, error) {
|
|||||||
return &Block{Data: data, Multihash: h}, nil
|
return &Block{Data: data, Multihash: h}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Key returns the block's Multihash as a Key value.
|
||||||
func (b *Block) Key() u.Key {
|
func (b *Block) Key() u.Key {
|
||||||
return u.Key(b.Multihash)
|
return u.Key(b.Multihash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlockService is a block datastore.
|
||||||
|
// It uses an internal `datastore.Datastore` instance to store values.
|
||||||
type BlockService struct {
|
type BlockService struct {
|
||||||
Datastore ds.Datastore
|
Datastore ds.Datastore
|
||||||
// Remote *bitswap.BitSwap // eventually.
|
// Remote *bitswap.BitSwap // eventually.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewBlockService creates a BlockService with given datastore instance.
|
||||||
func NewBlockService(d ds.Datastore) (*BlockService, error) {
|
func NewBlockService(d ds.Datastore) (*BlockService, error) {
|
||||||
if d == nil {
|
if d == nil {
|
||||||
return nil, fmt.Errorf("BlockService requires valid datastore")
|
return nil, fmt.Errorf("BlockService requires valid datastore")
|
||||||
@ -39,12 +43,15 @@ func NewBlockService(d ds.Datastore) (*BlockService, error) {
|
|||||||
return &BlockService{Datastore: d}, nil
|
return &BlockService{Datastore: d}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddBlock adds a particular block to the service, Putting it into the datastore.
|
||||||
func (s *BlockService) AddBlock(b *Block) (u.Key, error) {
|
func (s *BlockService) AddBlock(b *Block) (u.Key, error) {
|
||||||
k := b.Key()
|
k := b.Key()
|
||||||
dsk := ds.NewKey(string(k))
|
dsk := ds.NewKey(string(k))
|
||||||
return k, s.Datastore.Put(dsk, b.Data)
|
return k, s.Datastore.Put(dsk, b.Data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetBlock retrieves a particular block from the service,
|
||||||
|
// Getting it from the datastore using the key (hash).
|
||||||
func (s *BlockService) GetBlock(k u.Key) (*Block, error) {
|
func (s *BlockService) GetBlock(k u.Key) (*Block, error) {
|
||||||
dsk := ds.NewKey(string(k))
|
dsk := ds.NewKey(string(k))
|
||||||
datai, err := s.Datastore.Get(dsk)
|
datai, err := s.Datastore.Get(dsk)
|
||||||
|
15
cli/add.go
15
cli/add.go
@ -14,7 +14,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
var DepthLimitExceeded = fmt.Errorf("depth limit exceeded")
|
// Error indicating the max depth has been exceded.
|
||||||
|
var ErrDepthLimitExceeded = fmt.Errorf("depth limit exceeded")
|
||||||
|
|
||||||
var cmdIpfsAdd = &commander.Command{
|
var cmdIpfsAdd = &commander.Command{
|
||||||
UsageLine: "add",
|
UsageLine: "add",
|
||||||
@ -57,10 +58,10 @@ func addCmd(c *commander.Command, inp []string) error {
|
|||||||
_, err := addPath(n, fpath, depth)
|
_, err := addPath(n, fpath, depth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !recursive {
|
if !recursive {
|
||||||
return fmt.Errorf("%s is a directory. Use -r to add recursively.", fpath)
|
return fmt.Errorf("%s is a directory. Use -r to add recursively", fpath)
|
||||||
} else {
|
|
||||||
u.PErr("error adding %s: %v\n", fpath, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u.PErr("error adding %s: %v\n", fpath, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -68,7 +69,7 @@ func addCmd(c *commander.Command, inp []string) error {
|
|||||||
|
|
||||||
func addPath(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
|
func addPath(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
return nil, DepthLimitExceeded
|
return nil, ErrDepthLimitExceeded
|
||||||
}
|
}
|
||||||
|
|
||||||
fi, err := os.Stat(fpath)
|
fi, err := os.Stat(fpath)
|
||||||
@ -78,9 +79,9 @@ func addPath(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
|
|||||||
|
|
||||||
if fi.IsDir() {
|
if fi.IsDir() {
|
||||||
return addDir(n, fpath, depth)
|
return addDir(n, fpath, depth)
|
||||||
} else {
|
|
||||||
return addFile(n, fpath, depth)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return addFile(n, fpath, depth)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addDir(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
|
func addDir(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The IPFS command tree. It is an instance of `commander.Command`.
|
||||||
var CmdIpfs = &commander.Command{
|
var CmdIpfs = &commander.Command{
|
||||||
UsageLine: "ipfs [<flags>] <command> [<args>]",
|
UsageLine: "ipfs [<flags>] <command> [<args>]",
|
||||||
Short: "global versioned p2p merkledag file system",
|
Short: "global versioned p2p merkledag file system",
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
u "github.com/jbenet/go-ipfs/util"
|
u "github.com/jbenet/go-ipfs/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The IPFS version.
|
||||||
const Version = "0.1.0"
|
const Version = "0.1.0"
|
||||||
|
|
||||||
var cmdIpfsVersion = &commander.Command{
|
var cmdIpfsVersion = &commander.Command{
|
||||||
|
@ -5,15 +5,18 @@ import (
|
|||||||
u "github.com/jbenet/go-ipfs/util"
|
u "github.com/jbenet/go-ipfs/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Identity tracks the configuration of the local node's identity.
|
||||||
type Identity struct {
|
type Identity struct {
|
||||||
PeerId string
|
PeerId string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Datastore tracks the configuration of the datastore.
|
||||||
type Datastore struct {
|
type Datastore struct {
|
||||||
Type string
|
Type string
|
||||||
Path string
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config is used to load IPFS config files.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Identity *Identity
|
Identity *Identity
|
||||||
Datastore *Datastore
|
Datastore *Datastore
|
||||||
@ -29,6 +32,7 @@ var defaultConfigFile = `{
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// LoadConfig reads given file and returns the read config, or error.
|
||||||
func LoadConfig(filename string) (*Config, error) {
|
func LoadConfig(filename string) (*Config, error) {
|
||||||
if len(filename) == 0 {
|
if len(filename) == 0 {
|
||||||
filename = defaultConfigFilePath
|
filename = defaultConfigFilePath
|
||||||
|
@ -7,10 +7,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ReadFile(filename string) ([]byte, error) {
|
// WriteFile writes the given buffer `buf` into file named `filename`.
|
||||||
return ioutil.ReadFile(filename)
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteFile(filename string, buf []byte) error {
|
func WriteFile(filename string, buf []byte) error {
|
||||||
err := os.MkdirAll(path.Dir(filename), 0777)
|
err := os.MkdirAll(path.Dir(filename), 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -20,8 +17,9 @@ func WriteFile(filename string, buf []byte) error {
|
|||||||
return ioutil.WriteFile(filename, buf, 0666)
|
return ioutil.WriteFile(filename, buf, 0666)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadConfigFile reads the config from `filename` into `cfg`.
|
||||||
func ReadConfigFile(filename string, cfg *Config) error {
|
func ReadConfigFile(filename string, cfg *Config) error {
|
||||||
buf, err := ReadFile(filename)
|
buf, err := ioutil.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -29,6 +27,7 @@ func ReadConfigFile(filename string, cfg *Config) error {
|
|||||||
return json.Unmarshal(buf, cfg)
|
return json.Unmarshal(buf, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteConfigFile writes the config from `cfg` into `filename`.
|
||||||
func WriteConfigFile(filename string, cfg *Config) error {
|
func WriteConfigFile(filename string, cfg *Config) error {
|
||||||
buf, err := json.MarshalIndent(cfg, "", " ")
|
buf, err := json.MarshalIndent(cfg, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
peer "github.com/jbenet/go-ipfs/peer"
|
peer "github.com/jbenet/go-ipfs/peer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IPFS Core module. It represents an IPFS instance.
|
// IpfsNode is IPFS Core module. It represents an IPFS instance.
|
||||||
type IpfsNode struct {
|
type IpfsNode struct {
|
||||||
|
|
||||||
// the node's configuration
|
// the node's configuration
|
||||||
@ -47,9 +47,10 @@ type IpfsNode struct {
|
|||||||
// Namesys *namesys.Namesys
|
// Namesys *namesys.Namesys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewIpfsNode constructs a new IpfsNode based on the given config.
|
||||||
func NewIpfsNode(cfg *config.Config) (*IpfsNode, error) {
|
func NewIpfsNode(cfg *config.Config) (*IpfsNode, error) {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
return nil, fmt.Errorf("configuration required.")
|
return nil, fmt.Errorf("configuration required")
|
||||||
}
|
}
|
||||||
|
|
||||||
d, err := makeDatastore(cfg.Datastore)
|
d, err := makeDatastore(cfg.Datastore)
|
||||||
|
@ -4,4 +4,4 @@ package dht
|
|||||||
// Coral and S/Kademlia modifications. It is used to
|
// Coral and S/Kademlia modifications. It is used to
|
||||||
// implement the base IPFS Routing module.
|
// implement the base IPFS Routing module.
|
||||||
|
|
||||||
TODO. SEE https://github.com/jbenet/node-ipfs/blob/master/submodules/ipfs-dht/index.js
|
// TODO. SEE https://github.com/jbenet/node-ipfs/blob/master/submodules/ipfs-dht/index.js
|
||||||
|
@ -16,26 +16,32 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FileSystem is the readonly Ipfs Fuse Filesystem.
|
||||||
type FileSystem struct {
|
type FileSystem struct {
|
||||||
Ipfs *core.IpfsNode
|
Ipfs *core.IpfsNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewFileSystem constructs new fs using given core.IpfsNode instance.
|
||||||
func NewFileSystem(ipfs *core.IpfsNode) *FileSystem {
|
func NewFileSystem(ipfs *core.IpfsNode) *FileSystem {
|
||||||
return &FileSystem{Ipfs: ipfs}
|
return &FileSystem{Ipfs: ipfs}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Root constructs the Root of the filesystem, a Root object.
|
||||||
func (f FileSystem) Root() (fs.Node, fuse.Error) {
|
func (f FileSystem) Root() (fs.Node, fuse.Error) {
|
||||||
return &Root{Ipfs: f.Ipfs}, nil
|
return &Root{Ipfs: f.Ipfs}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Root is the root object of the filesystem tree.
|
||||||
type Root struct {
|
type Root struct {
|
||||||
Ipfs *core.IpfsNode
|
Ipfs *core.IpfsNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attr returns file attributes.
|
||||||
func (*Root) Attr() fuse.Attr {
|
func (*Root) Attr() fuse.Attr {
|
||||||
return fuse.Attr{Mode: os.ModeDir | 0111} // -rw+x
|
return fuse.Attr{Mode: os.ModeDir | 0111} // -rw+x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lookup performs a lookup under this node.
|
||||||
func (s *Root) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
func (s *Root) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
||||||
switch name {
|
switch name {
|
||||||
case "mach_kernel", ".hidden", "._.":
|
case "mach_kernel", ".hidden", "._.":
|
||||||
@ -52,15 +58,18 @@ func (s *Root) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
|||||||
return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
|
return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadDir reads a particular directory. Disallowed for root.
|
||||||
func (*Root) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
|
func (*Root) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
|
||||||
return nil, fuse.EPERM
|
return nil, fuse.EPERM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Node is the core object representing a filesystem tree node.
|
||||||
type Node struct {
|
type Node struct {
|
||||||
Ipfs *core.IpfsNode
|
Ipfs *core.IpfsNode
|
||||||
Nd *mdag.Node
|
Nd *mdag.Node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attr returns the attributes of a given node.
|
||||||
func (s *Node) Attr() fuse.Attr {
|
func (s *Node) Attr() fuse.Attr {
|
||||||
if len(s.Nd.Links) > 0 {
|
if len(s.Nd.Links) > 0 {
|
||||||
return fuse.Attr{Mode: os.ModeDir | 0555}
|
return fuse.Attr{Mode: os.ModeDir | 0555}
|
||||||
@ -70,6 +79,7 @@ func (s *Node) Attr() fuse.Attr {
|
|||||||
return fuse.Attr{Mode: 0444, Size: uint64(size)}
|
return fuse.Attr{Mode: 0444, Size: uint64(size)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lookup performs a lookup under this node.
|
||||||
func (s *Node) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
func (s *Node) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
||||||
nd, err := s.Ipfs.Resolver.ResolveLinks(s.Nd, []string{name})
|
nd, err := s.Ipfs.Resolver.ResolveLinks(s.Nd, []string{name})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -80,6 +90,7 @@ func (s *Node) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
|||||||
return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
|
return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadDir reads the link structure as directory entries
|
||||||
func (s *Node) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
|
func (s *Node) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
|
||||||
entries := make([]fuse.Dirent, len(s.Nd.Links))
|
entries := make([]fuse.Dirent, len(s.Nd.Links))
|
||||||
for i, link := range s.Nd.Links {
|
for i, link := range s.Nd.Links {
|
||||||
@ -96,10 +107,13 @@ func (s *Node) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
|
|||||||
return nil, fuse.ENOENT
|
return nil, fuse.ENOENT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadAll reads the object data as file data
|
||||||
func (s *Node) ReadAll(intr fs.Intr) ([]byte, fuse.Error) {
|
func (s *Node) ReadAll(intr fs.Intr) ([]byte, fuse.Error) {
|
||||||
return []byte(s.Nd.Data), nil
|
return []byte(s.Nd.Data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mount mounts an IpfsNode instance at a particular path. It
|
||||||
|
// serves until the process receives exit signals (to Unmount).
|
||||||
func Mount(ipfs *core.IpfsNode, fpath string) error {
|
func Mount(ipfs *core.IpfsNode, fpath string) error {
|
||||||
|
|
||||||
sigc := make(chan os.Signal, 1)
|
sigc := make(chan os.Signal, 1)
|
||||||
|
@ -8,13 +8,17 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BlockSizeLimit specifies the maximum size an imported block can have.
|
||||||
var BlockSizeLimit = int64(1048576) // 1 MB
|
var BlockSizeLimit = int64(1048576) // 1 MB
|
||||||
var SizeLimitExceeded = fmt.Errorf("object size limit exceeded")
|
|
||||||
|
// ErrSizeLimitExceeded signals that a block is larger than BlockSizeLimit.
|
||||||
|
var ErrSizeLimitExceeded = fmt.Errorf("object size limit exceeded")
|
||||||
|
|
||||||
// todo: incremental construction with an ipfs node. dumping constructed
|
// todo: incremental construction with an ipfs node. dumping constructed
|
||||||
// objects into the datastore, to avoid buffering all in memory
|
// objects into the datastore, to avoid buffering all in memory
|
||||||
|
|
||||||
// size required for block construction
|
// NewDagFromReader constructs a Merkle DAG from the given io.Reader.
|
||||||
|
// size required for block construction.
|
||||||
func NewDagFromReader(r io.Reader, size int64) (*dag.Node, error) {
|
func NewDagFromReader(r io.Reader, size int64) (*dag.Node, error) {
|
||||||
// todo: block-splitting based on rabin fingerprinting
|
// todo: block-splitting based on rabin fingerprinting
|
||||||
// todo: block-splitting with user-defined function
|
// todo: block-splitting with user-defined function
|
||||||
@ -22,7 +26,7 @@ func NewDagFromReader(r io.Reader, size int64) (*dag.Node, error) {
|
|||||||
|
|
||||||
// totally just trusts the reported size. fix later.
|
// totally just trusts the reported size. fix later.
|
||||||
if size > BlockSizeLimit { // 1 MB limit for now.
|
if size > BlockSizeLimit { // 1 MB limit for now.
|
||||||
return nil, SizeLimitExceeded
|
return nil, ErrSizeLimitExceeded
|
||||||
}
|
}
|
||||||
|
|
||||||
// we're doing it live!
|
// we're doing it live!
|
||||||
@ -32,7 +36,7 @@ func NewDagFromReader(r io.Reader, size int64) (*dag.Node, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if int64(len(buf)) > BlockSizeLimit {
|
if int64(len(buf)) > BlockSizeLimit {
|
||||||
return nil, SizeLimitExceeded // lying punk.
|
return nil, ErrSizeLimitExceeded // lying punk.
|
||||||
}
|
}
|
||||||
|
|
||||||
root := &dag.Node{Data: buf}
|
root := &dag.Node{Data: buf}
|
||||||
@ -40,6 +44,7 @@ func NewDagFromReader(r io.Reader, size int64) (*dag.Node, error) {
|
|||||||
return root, nil
|
return root, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDagFromFile constructs a Merkle DAG from the file at given path.
|
||||||
func NewDagFromFile(fpath string) (*dag.Node, error) {
|
func NewDagFromFile(fpath string) (*dag.Node, error) {
|
||||||
stat, err := os.Stat(fpath)
|
stat, err := os.Stat(fpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
// for now, we use a PBNode intermediate thing.
|
// for now, we use a PBNode intermediate thing.
|
||||||
// because native go objects are nice.
|
// because native go objects are nice.
|
||||||
|
|
||||||
|
// Unmarshal decodes raw data into a *Node instance.
|
||||||
|
// The conversion uses an intermediate PBNode.
|
||||||
func (n *Node) Unmarshal(encoded []byte) error {
|
func (n *Node) Unmarshal(encoded []byte) error {
|
||||||
var pbn PBNode
|
var pbn PBNode
|
||||||
if err := pbn.Unmarshal(encoded); err != nil {
|
if err := pbn.Unmarshal(encoded); err != nil {
|
||||||
@ -29,6 +31,8 @@ func (n *Node) Unmarshal(encoded []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalTo encodes a *Node instance into a given byte slice.
|
||||||
|
// The conversion uses an intermediate PBNode.
|
||||||
func (n *Node) MarshalTo(encoded []byte) error {
|
func (n *Node) MarshalTo(encoded []byte) error {
|
||||||
pbn := n.getPBNode()
|
pbn := n.getPBNode()
|
||||||
if _, err := pbn.MarshalTo(encoded); err != nil {
|
if _, err := pbn.MarshalTo(encoded); err != nil {
|
||||||
@ -37,6 +41,8 @@ func (n *Node) MarshalTo(encoded []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marshal encodes a *Node instance into a new byte slice.
|
||||||
|
// The conversion uses an intermediate PBNode.
|
||||||
func (n *Node) Marshal() ([]byte, error) {
|
func (n *Node) Marshal() ([]byte, error) {
|
||||||
pbn := n.getPBNode()
|
pbn := n.getPBNode()
|
||||||
data, err := pbn.Marshal()
|
data, err := pbn.Marshal()
|
||||||
@ -60,6 +66,8 @@ func (n *Node) getPBNode() *PBNode {
|
|||||||
return pbn
|
return pbn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encoded returns the encoded raw data version of a Node instance.
|
||||||
|
// It may use a cached encoded version, unless the force flag is given.
|
||||||
func (n *Node) Encoded(force bool) ([]byte, error) {
|
func (n *Node) Encoded(force bool) ([]byte, error) {
|
||||||
if n.encoded == nil || force {
|
if n.encoded == nil || force {
|
||||||
var err error
|
var err error
|
||||||
@ -72,6 +80,7 @@ func (n *Node) Encoded(force bool) ([]byte, error) {
|
|||||||
return n.encoded, nil
|
return n.encoded, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decoded decodes raw data and returns a new Node instance.
|
||||||
func Decoded(encoded []byte) (*Node, error) {
|
func Decoded(encoded []byte) (*Node, error) {
|
||||||
n := &Node{}
|
n := &Node{}
|
||||||
err := n.Unmarshal(encoded)
|
err := n.Unmarshal(encoded)
|
||||||
|
@ -7,11 +7,12 @@ import (
|
|||||||
mh "github.com/jbenet/go-multihash"
|
mh "github.com/jbenet/go-multihash"
|
||||||
)
|
)
|
||||||
|
|
||||||
// can't use []byte/Multihash for keys :(
|
// NodeMap maps u.Keys to Nodes.
|
||||||
// so have to convert Multihash bytes to string
|
// We cannot use []byte/Multihash for keys :(
|
||||||
|
// so have to convert Multihash bytes to string (u.Key)
|
||||||
type NodeMap map[u.Key]*Node
|
type NodeMap map[u.Key]*Node
|
||||||
|
|
||||||
// A node in the IPFS Merkle DAG.
|
// Node represents a node in the IPFS Merkle DAG.
|
||||||
// nodes have opaque data and a set of navigable links.
|
// nodes have opaque data and a set of navigable links.
|
||||||
type Node struct {
|
type Node struct {
|
||||||
Links []*Link
|
Links []*Link
|
||||||
@ -21,7 +22,7 @@ type Node struct {
|
|||||||
encoded []byte
|
encoded []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// An IPFS Merkle DAG Link
|
// Link represents an IPFS Merkle DAG Link between Nodes.
|
||||||
type Link struct {
|
type Link struct {
|
||||||
// utf string name. should be unique per object
|
// utf string name. should be unique per object
|
||||||
Name string // utf8
|
Name string // utf8
|
||||||
@ -36,6 +37,7 @@ type Link struct {
|
|||||||
Node *Node
|
Node *Node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddNodeLink adds a link to another node.
|
||||||
func (n *Node) AddNodeLink(name string, that *Node) error {
|
func (n *Node) AddNodeLink(name string, that *Node) error {
|
||||||
s, err := that.Size()
|
s, err := that.Size()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -55,6 +57,8 @@ func (n *Node) AddNodeLink(name string, that *Node) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Size returns the total size of the data addressed by node,
|
||||||
|
// including the total sizes of references.
|
||||||
func (n *Node) Size() (uint64, error) {
|
func (n *Node) Size() (uint64, error) {
|
||||||
b, err := n.Encoded(false)
|
b, err := n.Encoded(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -68,6 +72,7 @@ func (n *Node) Size() (uint64, error) {
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multihash hashes the encoded data of this node.
|
||||||
func (n *Node) Multihash() (mh.Multihash, error) {
|
func (n *Node) Multihash() (mh.Multihash, error) {
|
||||||
b, err := n.Encoded(false)
|
b, err := n.Encoded(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -77,18 +82,20 @@ func (n *Node) Multihash() (mh.Multihash, error) {
|
|||||||
return u.Hash(b)
|
return u.Hash(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Key returns the Multihash as a key, for maps.
|
||||||
func (n *Node) Key() (u.Key, error) {
|
func (n *Node) Key() (u.Key, error) {
|
||||||
h, err := n.Multihash()
|
h, err := n.Multihash()
|
||||||
return u.Key(h), err
|
return u.Key(h), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// An IPFS Merkle DAG service.
|
// DAGService is an IPFS Merkle DAG service.
|
||||||
// the root is virtual (like a forest)
|
// - the root is virtual (like a forest)
|
||||||
// stores nodes' data in a blockService
|
// - stores nodes' data in a BlockService
|
||||||
type DAGService struct {
|
type DAGService struct {
|
||||||
Blocks *blocks.BlockService
|
Blocks *blocks.BlockService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Put adds a node to the DAGService, storing the block in the BlockService
|
||||||
func (n *DAGService) Put(nd *Node) (u.Key, error) {
|
func (n *DAGService) Put(nd *Node) (u.Key, error) {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return "", fmt.Errorf("DAGService is nil")
|
return "", fmt.Errorf("DAGService is nil")
|
||||||
@ -107,6 +114,7 @@ func (n *DAGService) Put(nd *Node) (u.Key, error) {
|
|||||||
return n.Blocks.AddBlock(b)
|
return n.Blocks.AddBlock(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get retrieves a node from the DAGService, fetching the block in the BlockService
|
||||||
func (n *DAGService) Get(k u.Key) (*Node, error) {
|
func (n *DAGService) Get(k u.Key) (*Node, error) {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return nil, fmt.Errorf("DAGService is nil")
|
return nil, fmt.Errorf("DAGService is nil")
|
||||||
|
15
path/path.go
15
path/path.go
@ -9,12 +9,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Path resolution for IPFS
|
// Resolver provides path resolution to IPFS
|
||||||
|
// It has a pointer to a DAGService, which is uses to resolve nodes.
|
||||||
type Resolver struct {
|
type Resolver struct {
|
||||||
DAG *merkledag.DAGService
|
DAG *merkledag.DAGService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolvePath fetches the node for given path. It uses the first
|
||||||
|
// path component as a hash (key) of the first node, then resolves
|
||||||
|
// all other components walking the links, with ResolveLinks.
|
||||||
func (s *Resolver) ResolvePath(fpath string) (*merkledag.Node, error) {
|
func (s *Resolver) ResolvePath(fpath string) (*merkledag.Node, error) {
|
||||||
fpath = path.Clean(fpath)
|
fpath = path.Clean(fpath)
|
||||||
|
|
||||||
@ -27,7 +30,7 @@ func (s *Resolver) ResolvePath(fpath string) (*merkledag.Node, error) {
|
|||||||
|
|
||||||
// if nothing, bail.
|
// if nothing, bail.
|
||||||
if len(parts) == 0 {
|
if len(parts) == 0 {
|
||||||
return nil, fmt.Errorf("ipfs path must contain at least one component.")
|
return nil, fmt.Errorf("ipfs path must contain at least one component")
|
||||||
}
|
}
|
||||||
|
|
||||||
// first element in the path is a b58 hash (for now)
|
// first element in the path is a b58 hash (for now)
|
||||||
@ -44,6 +47,12 @@ func (s *Resolver) ResolvePath(fpath string) (*merkledag.Node, error) {
|
|||||||
return s.ResolveLinks(nd, parts[1:])
|
return s.ResolveLinks(nd, parts[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolveLinks iteratively resolves names by walking the link hierarchy.
|
||||||
|
// Every node is fetched from the DAGService, resolving the next name.
|
||||||
|
// Returns the last node found.
|
||||||
|
//
|
||||||
|
// ResolveLinks(nd, []string{"foo", "bar", "baz"})
|
||||||
|
// would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links
|
||||||
func (s *Resolver) ResolveLinks(ndd *merkledag.Node, names []string) (
|
func (s *Resolver) ResolveLinks(ndd *merkledag.Node, names []string) (
|
||||||
nd *merkledag.Node, err error) {
|
nd *merkledag.Node, err error) {
|
||||||
|
|
||||||
|
@ -6,24 +6,30 @@ import (
|
|||||||
mh "github.com/jbenet/go-multihash"
|
mh "github.com/jbenet/go-multihash"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PeerId is a byte slice representing the identity of a peer.
|
||||||
type PeerId mh.Multihash
|
type PeerId mh.Multihash
|
||||||
|
|
||||||
// have to map Key (string) : *Peer because slices are not comparable.
|
// PeerBook maps Key (string) : *Peer (slices are not comparable).
|
||||||
type PeerBook map[u.Key]*Peer
|
type PeerBook map[u.Key]*Peer
|
||||||
|
|
||||||
|
// Peer represents the identity information of an IPFS Node, including
|
||||||
|
// a PeerId, and relevant Addresses.
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
Id PeerId
|
Id PeerId
|
||||||
Addresses []*ma.Multiaddr
|
Addresses []*ma.Multiaddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Key returns the PeerId as a Key (string) for maps.
|
||||||
func (p *Peer) Key() u.Key {
|
func (p *Peer) Key() u.Key {
|
||||||
return u.Key(p.Id)
|
return u.Key(p.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddAddress adds the given Multiaddr address to Peer's addresses.
|
||||||
func (p *Peer) AddAddress(a *ma.Multiaddr) {
|
func (p *Peer) AddAddress(a *ma.Multiaddr) {
|
||||||
p.Addresses = append(p.Addresses, a)
|
p.Addresses = append(p.Addresses, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NetAddress returns the first Multiaddr found for a given network.
|
||||||
func (p *Peer) NetAddress(n string) *ma.Multiaddr {
|
func (p *Peer) NetAddress(n string) *ma.Multiaddr {
|
||||||
for _, a := range p.Addresses {
|
for _, a := range p.Addresses {
|
||||||
ps, err := a.Protocols()
|
ps, err := a.Protocols()
|
||||||
|
@ -9,8 +9,10 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ChanBuffer is the size of the buffer in the Conn Chan
|
||||||
const ChanBuffer = 10
|
const ChanBuffer = 10
|
||||||
|
|
||||||
|
// Conn represents a connection to another Peer (IPFS Node).
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
Peer *peer.Peer
|
Peer *peer.Peer
|
||||||
Addr *ma.Multiaddr
|
Addr *ma.Multiaddr
|
||||||
@ -21,8 +23,11 @@ type Conn struct {
|
|||||||
Incoming *msgio.Chan
|
Incoming *msgio.Chan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConnMap maps Keys (PeerIds) to Connections.
|
||||||
type ConnMap map[u.Key]*Conn
|
type ConnMap map[u.Key]*Conn
|
||||||
|
|
||||||
|
// Dial connects to a particular peer, over a given network
|
||||||
|
// Example: Dial("udp", peer)
|
||||||
func Dial(network string, peer *peer.Peer) (*Conn, error) {
|
func Dial(network string, peer *peer.Peer) (*Conn, error) {
|
||||||
addr := peer.NetAddress(network)
|
addr := peer.NetAddress(network)
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
@ -58,6 +63,7 @@ func Dial(network string, peer *peer.Peer) (*Conn, error) {
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close closes the connection, and associated channels.
|
||||||
func (s *Conn) Close() error {
|
func (s *Conn) Close() error {
|
||||||
if s.Conn == nil {
|
if s.Conn == nil {
|
||||||
return fmt.Errorf("Already closed.") // already closed
|
return fmt.Errorf("Already closed.") // already closed
|
||||||
|
@ -6,6 +6,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Message represents a packet of information sent to or received from a
|
||||||
|
// particular Peer.
|
||||||
type Message struct {
|
type Message struct {
|
||||||
// To or from, depending on direction.
|
// To or from, depending on direction.
|
||||||
Peer *peer.Peer
|
Peer *peer.Peer
|
||||||
@ -14,6 +16,7 @@ type Message struct {
|
|||||||
Data []byte
|
Data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Chan is a swam channel, which provides duplex communication and errors.
|
||||||
type Chan struct {
|
type Chan struct {
|
||||||
Outgoing chan Message
|
Outgoing chan Message
|
||||||
Incoming chan Message
|
Incoming chan Message
|
||||||
@ -21,6 +24,7 @@ type Chan struct {
|
|||||||
Close chan bool
|
Close chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewChan constructs a Chan instance, with given buffer size bufsize.
|
||||||
func NewChan(bufsize int) *Chan {
|
func NewChan(bufsize int) *Chan {
|
||||||
return &Chan{
|
return &Chan{
|
||||||
Outgoing: make(chan Message, bufsize),
|
Outgoing: make(chan Message, bufsize),
|
||||||
@ -30,12 +34,17 @@ func NewChan(bufsize int) *Chan {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Swarm is a connection muxer, allowing connections to other peers to
|
||||||
|
// be opened and closed, while still using the same Chan for all
|
||||||
|
// communication. The Chan sends/receives Messages, which note the
|
||||||
|
// destination or source Peer.
|
||||||
type Swarm struct {
|
type Swarm struct {
|
||||||
Chan *Chan
|
Chan *Chan
|
||||||
conns ConnMap
|
conns ConnMap
|
||||||
connsLock sync.RWMutex
|
connsLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSwarm constructs a Swarm, with a Chan.
|
||||||
func NewSwarm() *Swarm {
|
func NewSwarm() *Swarm {
|
||||||
s := &Swarm{
|
s := &Swarm{
|
||||||
Chan: NewChan(10),
|
Chan: NewChan(10),
|
||||||
@ -45,6 +54,7 @@ func NewSwarm() *Swarm {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close closes a swam.
|
||||||
func (s *Swarm) Close() {
|
func (s *Swarm) Close() {
|
||||||
s.connsLock.RLock()
|
s.connsLock.RLock()
|
||||||
l := len(s.conns)
|
l := len(s.conns)
|
||||||
@ -57,6 +67,14 @@ func (s *Swarm) Close() {
|
|||||||
s.Chan.Close <- true // listener
|
s.Chan.Close <- true // listener
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dial connects to a peer.
|
||||||
|
//
|
||||||
|
// The idea is that the client of Swarm does not need to know what network
|
||||||
|
// the connection will happen over. Swarm can use whichever it choses.
|
||||||
|
// This allows us to use various transport protocols, do NAT traversal/relay,
|
||||||
|
// etc. to achive connection.
|
||||||
|
//
|
||||||
|
// For now, Dial uses only TCP. This will be extended.
|
||||||
func (s *Swarm) Dial(peer *peer.Peer) (*Conn, error) {
|
func (s *Swarm) Dial(peer *peer.Peer) (*Conn, error) {
|
||||||
k := peer.Key()
|
k := peer.Key()
|
||||||
|
|
||||||
|
18
util/util.go
18
util/util.go
@ -8,18 +8,21 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Debug is a global flag for debugging.
|
||||||
var Debug bool
|
var Debug bool
|
||||||
var NotImplementedError = fmt.Errorf("Error: not implemented yet.")
|
|
||||||
|
|
||||||
// a Key for maps. It's a string (rep of a multihash).
|
// ErrNotImplemented signifies a function has not been implemented yet.
|
||||||
|
var ErrNotImplemented = fmt.Errorf("Error: not implemented yet.")
|
||||||
|
|
||||||
|
// Key is a string representation of multihash for use with maps.
|
||||||
type Key string
|
type Key string
|
||||||
|
|
||||||
// global hash function. uses multihash SHA2_256, 256 bits
|
// Hash is the global IPFS hash function. uses multihash SHA2_256, 256 bits
|
||||||
func Hash(data []byte) (mh.Multihash, error) {
|
func Hash(data []byte) (mh.Multihash, error) {
|
||||||
return mh.Sum(data, mh.SHA2_256, -1)
|
return mh.Sum(data, mh.SHA2_256, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tilde expansion
|
// TildeExpansion expands a filename, which may begin with a tilde.
|
||||||
func TildeExpansion(filename string) (string, error) {
|
func TildeExpansion(filename string) (string, error) {
|
||||||
if strings.HasPrefix(filename, "~/") {
|
if strings.HasPrefix(filename, "~/") {
|
||||||
usr, err := user.Current()
|
usr, err := user.Current()
|
||||||
@ -33,21 +36,26 @@ func TildeExpansion(filename string) (string, error) {
|
|||||||
return filename, nil
|
return filename, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shorthand printing functions.
|
// PErr is a shorthand printing function to output to Stderr.
|
||||||
func PErr(format string, a ...interface{}) {
|
func PErr(format string, a ...interface{}) {
|
||||||
fmt.Fprintf(os.Stderr, format, a...)
|
fmt.Fprintf(os.Stderr, format, a...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POut is a shorthand printing function to output to Stdout.
|
||||||
func POut(format string, a ...interface{}) {
|
func POut(format string, a ...interface{}) {
|
||||||
fmt.Fprintf(os.Stdout, format, a...)
|
fmt.Fprintf(os.Stdout, format, a...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DErr is a shorthand debug printing function to output to Stderr.
|
||||||
|
// Will only print if Debug is true.
|
||||||
func DErr(format string, a ...interface{}) {
|
func DErr(format string, a ...interface{}) {
|
||||||
if Debug {
|
if Debug {
|
||||||
PErr(format, a...)
|
PErr(format, a...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DOut is a shorthand debug printing function to output to Stdout.
|
||||||
|
// Will only print if Debug is true.
|
||||||
func DOut(format string, a ...interface{}) {
|
func DOut(format string, a ...interface{}) {
|
||||||
if Debug {
|
if Debug {
|
||||||
POut(format, a...)
|
POut(format, a...)
|
||||||
|
Reference in New Issue
Block a user