mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-30 01:52:26 +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
|
||||
|
||||
// the name system, resolves paths to hashes
|
||||
// Namesys *namesys.Namesys
|
||||
Namesys namesys.NSResolver
|
||||
}
|
||||
|
||||
// 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