diff --git a/blocks/blocks.go b/blocks/blocks.go index 8d5f64e05..4d5e9e952 100644 --- a/blocks/blocks.go +++ b/blocks/blocks.go @@ -7,14 +7,14 @@ import ( 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 - type Block struct { Multihash mh.Multihash Data []byte } +// NewBlock creates a Block object from opaque data. It will hash the data. func NewBlock(data []byte) (*Block, error) { h, err := u.Hash(data) if err != nil { @@ -23,15 +23,19 @@ func NewBlock(data []byte) (*Block, error) { return &Block{Data: data, Multihash: h}, nil } +// Key returns the block's Multihash as a Key value. func (b *Block) Key() u.Key { return u.Key(b.Multihash) } +// BlockService is a block datastore. +// It uses an internal `datastore.Datastore` instance to store values. type BlockService struct { Datastore ds.Datastore // Remote *bitswap.BitSwap // eventually. } +// NewBlockService creates a BlockService with given datastore instance. func NewBlockService(d ds.Datastore) (*BlockService, error) { if d == nil { return nil, fmt.Errorf("BlockService requires valid datastore") @@ -39,12 +43,15 @@ func NewBlockService(d ds.Datastore) (*BlockService, error) { 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) { k := b.Key() dsk := ds.NewKey(string(k)) 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) { dsk := ds.NewKey(string(k)) datai, err := s.Datastore.Get(dsk) diff --git a/cli/add.go b/cli/add.go index 4f90eb264..c80d8ce18 100644 --- a/cli/add.go +++ b/cli/add.go @@ -14,7 +14,8 @@ import ( "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{ UsageLine: "add", @@ -57,10 +58,10 @@ func addCmd(c *commander.Command, inp []string) error { _, err := addPath(n, fpath, depth) if err != nil { if !recursive { - return fmt.Errorf("%s is a directory. Use -r to add recursively.", fpath) - } else { - u.PErr("error adding %s: %v\n", fpath, err) + return fmt.Errorf("%s is a directory. Use -r to add recursively", fpath) } + + u.PErr("error adding %s: %v\n", fpath, 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) { if depth == 0 { - return nil, DepthLimitExceeded + return nil, ErrDepthLimitExceeded } fi, err := os.Stat(fpath) @@ -78,9 +79,9 @@ func addPath(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) { if fi.IsDir() { 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) { diff --git a/cli/ipfs.go b/cli/ipfs.go index e970ef634..a4d685eec 100644 --- a/cli/ipfs.go +++ b/cli/ipfs.go @@ -10,6 +10,7 @@ import ( "os" ) +// The IPFS command tree. It is an instance of `commander.Command`. var CmdIpfs = &commander.Command{ UsageLine: "ipfs [] []", Short: "global versioned p2p merkledag file system", diff --git a/cli/version.go b/cli/version.go index 5b7f3109a..3f6fd3b4b 100644 --- a/cli/version.go +++ b/cli/version.go @@ -5,6 +5,7 @@ import ( u "github.com/jbenet/go-ipfs/util" ) +// The IPFS version. const Version = "0.1.0" var cmdIpfsVersion = &commander.Command{ diff --git a/config/config.go b/config/config.go index 8a5245020..f1ae627d1 100644 --- a/config/config.go +++ b/config/config.go @@ -5,15 +5,18 @@ import ( u "github.com/jbenet/go-ipfs/util" ) +// Identity tracks the configuration of the local node's identity. type Identity struct { PeerId string } +// Datastore tracks the configuration of the datastore. type Datastore struct { Type string Path string } +// Config is used to load IPFS config files. type Config struct { Identity *Identity 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) { if len(filename) == 0 { filename = defaultConfigFilePath diff --git a/config/serialize.go b/config/serialize.go index e5c9e0855..a88f50a2f 100644 --- a/config/serialize.go +++ b/config/serialize.go @@ -7,10 +7,7 @@ import ( "path" ) -func ReadFile(filename string) ([]byte, error) { - return ioutil.ReadFile(filename) -} - +// WriteFile writes the given buffer `buf` into file named `filename`. func WriteFile(filename string, buf []byte) error { err := os.MkdirAll(path.Dir(filename), 0777) if err != nil { @@ -20,8 +17,9 @@ func WriteFile(filename string, buf []byte) error { return ioutil.WriteFile(filename, buf, 0666) } +// ReadConfigFile reads the config from `filename` into `cfg`. func ReadConfigFile(filename string, cfg *Config) error { - buf, err := ReadFile(filename) + buf, err := ioutil.ReadFile(filename) if err != nil { return err } @@ -29,6 +27,7 @@ func ReadConfigFile(filename string, cfg *Config) error { return json.Unmarshal(buf, cfg) } +// WriteConfigFile writes the config from `cfg` into `filename`. func WriteConfigFile(filename string, cfg *Config) error { buf, err := json.MarshalIndent(cfg, "", " ") if err != nil { diff --git a/core/core.go b/core/core.go index 7da2e1844..bd22ff9f2 100644 --- a/core/core.go +++ b/core/core.go @@ -10,7 +10,7 @@ import ( 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 { // the node's configuration @@ -47,9 +47,10 @@ type IpfsNode struct { // Namesys *namesys.Namesys } +// NewIpfsNode constructs a new IpfsNode based on the given config. func NewIpfsNode(cfg *config.Config) (*IpfsNode, error) { if cfg == nil { - return nil, fmt.Errorf("configuration required.") + return nil, fmt.Errorf("configuration required") } d, err := makeDatastore(cfg.Datastore) diff --git a/dht/dht.go b/dht/dht.go index f553e9c24..20095ac41 100644 --- a/dht/dht.go +++ b/dht/dht.go @@ -4,4 +4,4 @@ package dht // Coral and S/Kademlia modifications. It is used to // 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 diff --git a/fuse/readonly/readonly.go b/fuse/readonly/readonly.go index d0bdfcd39..299003592 100644 --- a/fuse/readonly/readonly.go +++ b/fuse/readonly/readonly.go @@ -16,26 +16,32 @@ import ( "time" ) +// FileSystem is the readonly Ipfs Fuse Filesystem. type FileSystem struct { Ipfs *core.IpfsNode } +// NewFileSystem constructs new fs using given core.IpfsNode instance. func NewFileSystem(ipfs *core.IpfsNode) *FileSystem { return &FileSystem{Ipfs: ipfs} } +// Root constructs the Root of the filesystem, a Root object. func (f FileSystem) Root() (fs.Node, fuse.Error) { return &Root{Ipfs: f.Ipfs}, nil } +// Root is the root object of the filesystem tree. type Root struct { Ipfs *core.IpfsNode } +// Attr returns file attributes. func (*Root) Attr() fuse.Attr { 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) { switch name { 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 } +// ReadDir reads a particular directory. Disallowed for root. func (*Root) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) { return nil, fuse.EPERM } +// Node is the core object representing a filesystem tree node. type Node struct { Ipfs *core.IpfsNode Nd *mdag.Node } +// Attr returns the attributes of a given node. func (s *Node) Attr() fuse.Attr { if len(s.Nd.Links) > 0 { 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)} } +// Lookup performs a lookup under this node. func (s *Node) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) { nd, err := s.Ipfs.Resolver.ResolveLinks(s.Nd, []string{name}) 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 } +// ReadDir reads the link structure as directory entries func (s *Node) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) { entries := make([]fuse.Dirent, len(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 } +// ReadAll reads the object data as file data func (s *Node) ReadAll(intr fs.Intr) ([]byte, fuse.Error) { 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 { sigc := make(chan os.Signal, 1) diff --git a/importer/importer.go b/importer/importer.go index 195cae8f1..b37225f63 100644 --- a/importer/importer.go +++ b/importer/importer.go @@ -8,13 +8,17 @@ import ( "os" ) +// BlockSizeLimit specifies the maximum size an imported block can have. 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 // 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) { // todo: block-splitting based on rabin fingerprinting // 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. if size > BlockSizeLimit { // 1 MB limit for now. - return nil, SizeLimitExceeded + return nil, ErrSizeLimitExceeded } // we're doing it live! @@ -32,7 +36,7 @@ func NewDagFromReader(r io.Reader, size int64) (*dag.Node, error) { } if int64(len(buf)) > BlockSizeLimit { - return nil, SizeLimitExceeded // lying punk. + return nil, ErrSizeLimitExceeded // lying punk. } root := &dag.Node{Data: buf} @@ -40,6 +44,7 @@ func NewDagFromReader(r io.Reader, size int64) (*dag.Node, error) { return root, nil } +// NewDagFromFile constructs a Merkle DAG from the file at given path. func NewDagFromFile(fpath string) (*dag.Node, error) { stat, err := os.Stat(fpath) if err != nil { diff --git a/merkledag/coding.go b/merkledag/coding.go index 7b256460a..d87f134f6 100644 --- a/merkledag/coding.go +++ b/merkledag/coding.go @@ -8,6 +8,8 @@ import ( // for now, we use a PBNode intermediate thing. // 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 { var pbn PBNode if err := pbn.Unmarshal(encoded); err != nil { @@ -29,6 +31,8 @@ func (n *Node) Unmarshal(encoded []byte) error { 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 { pbn := n.getPBNode() if _, err := pbn.MarshalTo(encoded); err != nil { @@ -37,6 +41,8 @@ func (n *Node) MarshalTo(encoded []byte) error { return nil } +// Marshal encodes a *Node instance into a new byte slice. +// The conversion uses an intermediate PBNode. func (n *Node) Marshal() ([]byte, error) { pbn := n.getPBNode() data, err := pbn.Marshal() @@ -60,6 +66,8 @@ func (n *Node) getPBNode() *PBNode { 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) { if n.encoded == nil || force { var err error @@ -72,6 +80,7 @@ func (n *Node) Encoded(force bool) ([]byte, error) { return n.encoded, nil } +// Decoded decodes raw data and returns a new Node instance. func Decoded(encoded []byte) (*Node, error) { n := &Node{} err := n.Unmarshal(encoded) diff --git a/merkledag/merkledag.go b/merkledag/merkledag.go index 77ca2c173..251ea0bee 100644 --- a/merkledag/merkledag.go +++ b/merkledag/merkledag.go @@ -7,11 +7,12 @@ import ( mh "github.com/jbenet/go-multihash" ) -// can't use []byte/Multihash for keys :( -// so have to convert Multihash bytes to string +// NodeMap maps u.Keys to Nodes. +// We cannot use []byte/Multihash for keys :( +// so have to convert Multihash bytes to string (u.Key) 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. type Node struct { Links []*Link @@ -21,7 +22,7 @@ type Node struct { encoded []byte } -// An IPFS Merkle DAG Link +// Link represents an IPFS Merkle DAG Link between Nodes. type Link struct { // utf string name. should be unique per object Name string // utf8 @@ -36,6 +37,7 @@ type Link struct { Node *Node } +// AddNodeLink adds a link to another node. func (n *Node) AddNodeLink(name string, that *Node) error { s, err := that.Size() if err != nil { @@ -55,6 +57,8 @@ func (n *Node) AddNodeLink(name string, that *Node) error { 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) { b, err := n.Encoded(false) if err != nil { @@ -68,6 +72,7 @@ func (n *Node) Size() (uint64, error) { return s, nil } +// Multihash hashes the encoded data of this node. func (n *Node) Multihash() (mh.Multihash, error) { b, err := n.Encoded(false) if err != nil { @@ -77,18 +82,20 @@ func (n *Node) Multihash() (mh.Multihash, error) { return u.Hash(b) } +// Key returns the Multihash as a key, for maps. func (n *Node) Key() (u.Key, error) { h, err := n.Multihash() return u.Key(h), err } -// An IPFS Merkle DAG service. -// the root is virtual (like a forest) -// stores nodes' data in a blockService +// DAGService is an IPFS Merkle DAG service. +// - the root is virtual (like a forest) +// - stores nodes' data in a BlockService type DAGService struct { 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) { if n == 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) } +// Get retrieves a node from the DAGService, fetching the block in the BlockService func (n *DAGService) Get(k u.Key) (*Node, error) { if n == nil { return nil, fmt.Errorf("DAGService is nil") diff --git a/path/path.go b/path/path.go index 47d0346b7..3f1c3997e 100644 --- a/path/path.go +++ b/path/path.go @@ -9,12 +9,15 @@ import ( "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 { 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) { fpath = path.Clean(fpath) @@ -27,7 +30,7 @@ func (s *Resolver) ResolvePath(fpath string) (*merkledag.Node, error) { // if nothing, bail. 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) @@ -44,6 +47,12 @@ func (s *Resolver) ResolvePath(fpath string) (*merkledag.Node, error) { 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) ( nd *merkledag.Node, err error) { diff --git a/peer/peer.go b/peer/peer.go index 20da1ff9a..96e0aba80 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -6,24 +6,30 @@ import ( mh "github.com/jbenet/go-multihash" ) +// PeerId is a byte slice representing the identity of a peer. 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 +// Peer represents the identity information of an IPFS Node, including +// a PeerId, and relevant Addresses. type Peer struct { Id PeerId Addresses []*ma.Multiaddr } +// Key returns the PeerId as a Key (string) for maps. func (p *Peer) Key() u.Key { return u.Key(p.Id) } +// AddAddress adds the given Multiaddr address to Peer's addresses. func (p *Peer) AddAddress(a *ma.Multiaddr) { p.Addresses = append(p.Addresses, a) } +// NetAddress returns the first Multiaddr found for a given network. func (p *Peer) NetAddress(n string) *ma.Multiaddr { for _, a := range p.Addresses { ps, err := a.Protocols() diff --git a/swarm/conn.go b/swarm/conn.go index 73116d38b..23938555c 100644 --- a/swarm/conn.go +++ b/swarm/conn.go @@ -9,8 +9,10 @@ import ( "net" ) +// ChanBuffer is the size of the buffer in the Conn Chan const ChanBuffer = 10 +// Conn represents a connection to another Peer (IPFS Node). type Conn struct { Peer *peer.Peer Addr *ma.Multiaddr @@ -21,8 +23,11 @@ type Conn struct { Incoming *msgio.Chan } +// ConnMap maps Keys (PeerIds) to Connections. 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) { addr := peer.NetAddress(network) if addr == nil { @@ -58,6 +63,7 @@ func Dial(network string, peer *peer.Peer) (*Conn, error) { return conn, nil } +// Close closes the connection, and associated channels. func (s *Conn) Close() error { if s.Conn == nil { return fmt.Errorf("Already closed.") // already closed diff --git a/swarm/swarm.go b/swarm/swarm.go index 37598b165..9f4759895 100644 --- a/swarm/swarm.go +++ b/swarm/swarm.go @@ -6,6 +6,8 @@ import ( "sync" ) +// Message represents a packet of information sent to or received from a +// particular Peer. type Message struct { // To or from, depending on direction. Peer *peer.Peer @@ -14,6 +16,7 @@ type Message struct { Data []byte } +// Chan is a swam channel, which provides duplex communication and errors. type Chan struct { Outgoing chan Message Incoming chan Message @@ -21,6 +24,7 @@ type Chan struct { Close chan bool } +// NewChan constructs a Chan instance, with given buffer size bufsize. func NewChan(bufsize int) *Chan { return &Chan{ 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 { Chan *Chan conns ConnMap connsLock sync.RWMutex } +// NewSwarm constructs a Swarm, with a Chan. func NewSwarm() *Swarm { s := &Swarm{ Chan: NewChan(10), @@ -45,6 +54,7 @@ func NewSwarm() *Swarm { return s } +// Close closes a swam. func (s *Swarm) Close() { s.connsLock.RLock() l := len(s.conns) @@ -57,6 +67,14 @@ func (s *Swarm) Close() { 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) { k := peer.Key() diff --git a/util/util.go b/util/util.go index 9ee662e36..639b913c9 100644 --- a/util/util.go +++ b/util/util.go @@ -8,18 +8,21 @@ import ( "strings" ) +// Debug is a global flag for debugging. 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 -// 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) { 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) { if strings.HasPrefix(filename, "~/") { usr, err := user.Current() @@ -33,21 +36,26 @@ func TildeExpansion(filename string) (string, error) { return filename, nil } -// Shorthand printing functions. +// PErr is a shorthand printing function to output to Stderr. func PErr(format string, a ...interface{}) { fmt.Fprintf(os.Stderr, format, a...) } +// POut is a shorthand printing function to output to Stdout. func POut(format string, a ...interface{}) { 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{}) { if Debug { 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{}) { if Debug { POut(format, a...)