mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-30 18:13:54 +08:00
implement namesys resolvers (thanks to bren2010 for dns and proquint)
This commit is contained in:
44
cmd/ipfs/pin.go
Normal file
44
cmd/ipfs/pin.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/gonuts/flag"
|
||||||
|
"github.com/jbenet/commander"
|
||||||
|
"github.com/jbenet/go-ipfs/daemon"
|
||||||
|
u "github.com/jbenet/go-ipfs/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
var cmdIpfsPin = &commander.Command{
|
||||||
|
UsageLine: "pin",
|
||||||
|
Short: "pin an ipfs object to local storage.",
|
||||||
|
Long: `ipfs pin <ipfs-path> - pin ipfs object to local storage.
|
||||||
|
|
||||||
|
Retrieves the object named by <ipfs-path> and stores it locally
|
||||||
|
on disk.
|
||||||
|
`,
|
||||||
|
Run: pinCmd,
|
||||||
|
Flag: *flag.NewFlagSet("ipfs-pin", flag.ExitOnError),
|
||||||
|
}
|
||||||
|
|
||||||
|
func pinCmd(c *commander.Command, inp []string) error {
|
||||||
|
if len(inp) < 1 {
|
||||||
|
u.POut(c.Long)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
com := daemon.NewCommand()
|
||||||
|
com.Command = "pin"
|
||||||
|
com.Args = inp
|
||||||
|
|
||||||
|
err := daemon.SendCommand(com, "localhost:12345")
|
||||||
|
if err != nil {
|
||||||
|
n, err := localNode(false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
daemon.ExecuteCommand(com, n, os.Stdout)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -60,7 +60,7 @@ type IpfsNode struct {
|
|||||||
Resolver *path.Resolver
|
Resolver *path.Resolver
|
||||||
|
|
||||||
// the name system, resolves paths to hashes
|
// the name system, resolves paths to hashes
|
||||||
// Namesys *namesys.Namesys
|
Namesys namesys.NSResolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIpfsNode constructs a new IpfsNode based on the given config.
|
// NewIpfsNode constructs a new IpfsNode based on the given config.
|
||||||
|
33
namesys/dns.go
Normal file
33
namesys/dns.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package namesys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
u "github.com/jbenet/go-ipfs/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DNSResolver struct {
|
||||||
|
// TODO: maybe some sort of caching?
|
||||||
|
// cache would need a timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DNSResolver) Resolve(name string) (string, error) {
|
||||||
|
txt, err := net.LookupTXT(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, t := range txt {
|
||||||
|
pair := strings.Split(t, "=")
|
||||||
|
if len(pair) < 2 {
|
||||||
|
// Log error?
|
||||||
|
u.DErr("Incorrectly formatted text record.")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if pair[0] == name {
|
||||||
|
return pair[1], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", u.ErrNotFound
|
||||||
|
}
|
48
namesys/entry.pb.go
Normal file
48
namesys/entry.pb.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Code generated by protoc-gen-go.
|
||||||
|
// source: entry.proto
|
||||||
|
// DO NOT EDIT!
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package namesys is a generated protocol buffer package.
|
||||||
|
|
||||||
|
It is generated from these files:
|
||||||
|
entry.proto
|
||||||
|
|
||||||
|
It has these top-level messages:
|
||||||
|
InpsEntry
|
||||||
|
*/
|
||||||
|
package namesys
|
||||||
|
|
||||||
|
import proto "code.google.com/p/goprotobuf/proto"
|
||||||
|
import math "math"
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
type InpsEntry struct {
|
||||||
|
Value []byte `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
|
||||||
|
Signature []byte `protobuf:"bytes,2,req,name=signature" json:"signature,omitempty"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *InpsEntry) Reset() { *m = InpsEntry{} }
|
||||||
|
func (m *InpsEntry) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*InpsEntry) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (m *InpsEntry) GetValue() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *InpsEntry) GetSignature() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Signature
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
}
|
6
namesys/entry.proto
Normal file
6
namesys/entry.proto
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package namesys;
|
||||||
|
|
||||||
|
message InpsEntry {
|
||||||
|
required bytes value = 1;
|
||||||
|
required bytes signature = 2;
|
||||||
|
}
|
5
namesys/nsresolver.go
Normal file
5
namesys/nsresolver.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package namesys
|
||||||
|
|
||||||
|
type NSResolver interface {
|
||||||
|
Resolve(string) (string, error)
|
||||||
|
}
|
22
namesys/proquint.go
Normal file
22
namesys/proquint.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package namesys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
proquint "github.com/bren2010/proquint"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = proquint.Encode
|
||||||
|
|
||||||
|
type ProquintResolver struct{}
|
||||||
|
|
||||||
|
func (r *ProquintResolver) Resolve(name string) (string, error) {
|
||||||
|
ok, err := proquint.IsProquint(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("not a valid proquint string")
|
||||||
|
}
|
||||||
|
return string(proquint.Decode(name)), nil
|
||||||
|
}
|
21
namesys/resolver.go
Normal file
21
namesys/resolver.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package namesys
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
type MasterResolver struct {
|
||||||
|
dns *DNSResolver
|
||||||
|
routing *RoutingResolver
|
||||||
|
pro *ProquintResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mr *MasterResolver) Resolve(name string) (string, error) {
|
||||||
|
if strings.Contains(name, ".") {
|
||||||
|
return mr.dns.Resolve(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(name, "-") {
|
||||||
|
return mr.pro.Resolve(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mr.routing.Resolve(name)
|
||||||
|
}
|
77
namesys/routing.go
Normal file
77
namesys/routing.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package namesys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.google.com/p/goprotobuf/proto"
|
||||||
|
|
||||||
|
ci "github.com/jbenet/go-ipfs/crypto"
|
||||||
|
mdag "github.com/jbenet/go-ipfs/merkledag"
|
||||||
|
"github.com/jbenet/go-ipfs/routing"
|
||||||
|
u "github.com/jbenet/go-ipfs/util"
|
||||||
|
mh "github.com/jbenet/go-multihash"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RoutingName is the de-serialized name structure that is stored (serialized)
|
||||||
|
// in the routing system. Basically, a hash + a digital signature. (serialization can be
|
||||||
|
// protobuf, or a simple binary format)
|
||||||
|
type RoutingName struct {
|
||||||
|
Hash u.Key
|
||||||
|
Signature []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoutingResolver implements NSResolver for the main IPFS SFS-like naming
|
||||||
|
type RoutingResolver struct {
|
||||||
|
routing routing.IpfsRouting
|
||||||
|
dag mdag.DAGService
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RoutingResolver) Resolve(name string) (string, error) {
|
||||||
|
hash, err := mh.FromB58String(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// name should be a multihash. if it isn't, error out here.
|
||||||
|
|
||||||
|
// use the routing system to get the name.
|
||||||
|
// /ipns/<name>
|
||||||
|
h, err := u.Hash([]byte("ipns:" + name))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
inpsKey := u.Key(h)
|
||||||
|
val, err := r.routing.GetValue(inpsKey, time.Second*10)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := new(InpsEntry)
|
||||||
|
err = proto.Unmarshal(val, entry)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// name should be a public key retrievable from ipfs
|
||||||
|
// /ipfs/<name>
|
||||||
|
key := u.Key(hash)
|
||||||
|
node, err := r.dag.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// get PublicKey from node.Data
|
||||||
|
pk, err := ci.UnmarshalPublicKey(node.Data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check sig with pk
|
||||||
|
if ok, err := pk.Verify(entry.GetValue(), entry.GetSignature()); err != nil && ok {
|
||||||
|
return "", fmt.Errorf("Invalid value. Not signed by PrivateKey corresponding to %v", pk)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok sig checks out. this is a valid name.
|
||||||
|
return string(entry.GetValue()), nil
|
||||||
|
}
|
Reference in New Issue
Block a user