diff --git a/codec.go b/codec.go index 36de467..1b39786 100644 --- a/codec.go +++ b/codec.go @@ -4,15 +4,19 @@ import ( "bytes" "encoding/base32" "encoding/binary" + "errors" "fmt" "net" "strconv" "strings" - "errors" + b58 "github.com/jbenet/go-base58" mh "github.com/jbenet/go-multihash" ) +// Size of an ed25519 public key. Copied from github.com/agl/ed25519. +const ed25519PublicKeySize = 32 + func stringToBytes(s string) ([]byte, error) { // consume trailing slashes @@ -256,6 +260,15 @@ func addressStringToBytes(p Protocol, s string) ([]byte, error) { b := append(size, m...) return b, nil + case P_SHS: // shs + // the address is a varint prefixed multihash string representation + a := b58.Decode(s) + if len(a) != ed25519PublicKeySize { + return nil, fmt.Errorf("failed to parse %s addr %s", p.Name, s) + } + + return a, nil + case P_UNIX: // the address is the whole remaining string, prefixed by a varint len size := CodeToVarint(len(s)) @@ -298,7 +311,18 @@ func addressBytesToString(p Protocol, b []byte) (string, error) { case P_ONION: addr := strings.ToLower(base32.StdEncoding.EncodeToString(b[0:10])) port := binary.BigEndian.Uint16(b[10:12]) - return addr + ":"+ strconv.Itoa(int(port)), nil + return addr + ":" + strconv.Itoa(int(port)), nil + + case P_SHS: // shs + if len(b) != ed25519PublicKeySize { + return "", fmt.Errorf("shs address has wrong length") + } + + m := b58.Encode(b) + if len(m) == 0 { + return m, fmt.Errorf("could not decode address") + } + return m, nil case P_UNIX: // the address is a varint len prefixed string diff --git a/multiaddr_test.go b/multiaddr_test.go index 9cd6b19..2d74671 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -41,6 +41,8 @@ func TestConstructFails(t *testing.T) { "/ip4/127.0.0.1/udp", "/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa", "/ip4/127.0.0.1/tcp", + "/ip4/127.0.0.1/shs", + "/ip4/127.0.0.1/tcp/8008/shs/7ZVaSM9sQ4mCCkn4MVIAhkcmSqF9V4u8p8r5hvxX4FnW", // contains illegal char 'I' "/ip4/127.0.0.1/ipfs", "/ip4/127.0.0.1/ipfs/tcp", "/unix", @@ -70,6 +72,7 @@ func TestConstructSucceeds(t *testing.T) { "/sctp/1234", "/udp/65535", "/tcp/65535", + "/shs/7ZVaSM9sQ4mCCkn4MV1AhkcmSqF9V4u8p8r5hvxX4FnW", "/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", "/udp/1234/sctp/1234", "/udp/1234/udt", @@ -81,6 +84,7 @@ func TestConstructSucceeds(t *testing.T) { "/ip4/127.0.0.1/udp/0", "/ip4/127.0.0.1/tcp/1234", "/ip4/127.0.0.1/tcp/1234/", + "/ip4/127.0.0.1/tcp/8008/shs/7ZVaSM9sQ4mCCkn4MV1AhkcmSqF9V4u8p8r5hvxX4FnW", "/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", "/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", "/unix/a/b/c/d/e", @@ -360,6 +364,10 @@ func TestGetValue(t *testing.T) { assertValueForProto(t, a, P_UDP, "12345") assertValueForProto(t, a, P_UTP, "") + a = newMultiaddr(t, "/ip4/0.0.0.0/shs/7ZVaSM9sQ4mCCkn4MV1AhkcmSqF9V4u8p8r5hvxX4FnW") // test shs. + assertValueForProto(t, a, P_IP4, "0.0.0.0") + assertValueForProto(t, a, P_SHS, "7ZVaSM9sQ4mCCkn4MV1AhkcmSqF9V4u8p8r5hvxX4FnW") + a = newMultiaddr(t, "/ip4/0.0.0.0/unix/a/b/c/d") // ending in a path one. assertValueForProto(t, a, P_IP4, "0.0.0.0") assertValueForProto(t, a, P_UNIX, "a/b/c/d") @@ -384,7 +392,7 @@ func TestFuzzBytes(t *testing.T) { } func randMaddrString() string { - good_corpus := []string{"tcp", "ip", "udp", "ipfs", "0.0.0.0", "127.0.0.1", "12345", "QmbHVEEepCi7rn7VL7Exxpd2Ci9NNB6ifvqwhsrbRMgQFP"} + good_corpus := []string{"tcp", "ip", "udp", "ipfs", "shs", "0.0.0.0", "127.0.0.1", "12345", "QmbHVEEepCi7rn7VL7Exxpd2Ci9NNB6ifvqwhsrbRMgQFP", "7ZVaSM9sQ4mCCkn4MV1AhkcmSqF9V4u8p8r5hvxX4FnW"} size := rand.Intn(256) parts := make([]string, 0, size) diff --git a/protocols.csv b/protocols.csv index 996b855..9a5009c 100644 --- a/protocols.csv +++ b/protocols.csv @@ -8,6 +8,7 @@ code size name 132 16 sctp 301 0 utp 302 0 udt +350 256 shs 400 V unix 421 V ipfs 480 0 http diff --git a/protocols.go b/protocols.go index aff30dc..d3eeab3 100644 --- a/protocols.go +++ b/protocols.go @@ -28,6 +28,7 @@ const ( P_SCTP = 132 P_UTP = 301 P_UDT = 302 + P_SHS = 350 P_UNIX = 400 P_IPFS = 421 P_HTTP = 480 @@ -52,6 +53,7 @@ var Protocols = []Protocol{ Protocol{P_ONION, 96, "onion", CodeToVarint(P_ONION), false}, Protocol{P_UTP, 0, "utp", CodeToVarint(P_UTP), false}, Protocol{P_UDT, 0, "udt", CodeToVarint(P_UDT), false}, + Protocol{P_SHS, 256, "shs", CodeToVarint(P_SHS), false}, Protocol{P_HTTP, 0, "http", CodeToVarint(P_HTTP), false}, Protocol{P_HTTPS, 0, "https", CodeToVarint(P_HTTPS), false}, Protocol{P_IPFS, LengthPrefixedVarSize, "ipfs", CodeToVarint(P_IPFS), false},