From b185168cd2d55c1c57b9eceaedb3f504ce3ff988 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Sun, 17 Jan 2016 01:04:37 -0800 Subject: [PATCH 1/3] modularize multiaddr protocols --- protocols.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/protocols.go b/protocols.go index c233cef..8364d4c 100644 --- a/protocols.go +++ b/protocols.go @@ -55,6 +55,20 @@ var Protocols = []Protocol{ Protocol{P_IPFS, LengthPrefixedVarSize, "ipfs", CodeToVarint(P_IPFS)}, } +func AddProtocol(p Protocol) error { + for _, pt := range Protocols { + if pt.Code == p.Code { + return fmt.Errorf("protocol code %d already taken by %q", p.Code, pt.Name) + } + if pt.Name == p.Name { + return fmt.Errorf("protocol by the name %q already exists", p.Name) + } + } + + Protocols = append(Protocols, p) + return nil +} + // ProtocolWithName returns the Protocol description with given string name. func ProtocolWithName(s string) Protocol { for _, p := range Protocols { From a581da3f8f6c574804a23d117aaeeff66aff42f8 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Sun, 17 Jan 2016 05:14:38 -0800 Subject: [PATCH 2/3] add method to lookup values in a multiaddr --- interface.go | 3 +++ multiaddr.go | 29 +++++++++++++++++++++++++++++ multiaddr_test.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/interface.go b/interface.go index 512cb62..18de2a2 100644 --- a/interface.go +++ b/interface.go @@ -39,4 +39,7 @@ type Multiaddr interface { // /ip4/1.2.3.4/tcp/80 decapsulate /ip4/1.2.3.4 = /tcp/80 // Decapsulate(Multiaddr) Multiaddr + + // ValueForProtocol returns the value (if any) following the specified protocol + ValueForProtocol(code int) (string, error) } diff --git a/multiaddr.go b/multiaddr.go index 1cb7ad4..2343538 100644 --- a/multiaddr.go +++ b/multiaddr.go @@ -113,3 +113,32 @@ func (m *multiaddr) Decapsulate(o Multiaddr) Multiaddr { } return ma } + +var ErrProtocolNotFound = fmt.Errorf("protocol not found in multiaddr") + +func (m *multiaddr) ValueForProtocol(code int) (string, error) { + protos := m.Protocols() + found := -1 + index := 2 + + for i, p := range protos { + if code == p.Code { + if p.Size == 0 { + return "", nil + } + found = i + break + } else { + index += 2 + if p.Size == 0 { + index-- + } + } + } + + if found == -1 { + return "", ErrProtocolNotFound + } + + return strings.Split(m.String(), "/")[index], nil +} diff --git a/multiaddr_test.go b/multiaddr_test.go index 3a60751..e1994ff 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -300,3 +300,34 @@ func TestEncapsulate(t *testing.T) { t.Error("decapsulate /ip4 failed.", "/", s) } } + +func assertValueForProto(t *testing.T, a Multiaddr, p int, exp string) { + t.Logf("checking for %s in %s", ProtocolWithCode(p).Name, a) + fv, err := a.ValueForProtocol(p) + if err != nil { + t.Fatal(err) + } + + if fv != exp { + t.Fatalf("expected %q for %d in %d, but got %q instead", exp, p, a, fv) + } +} + +func TestGetValue(t *testing.T) { + a := newMultiaddr(t, "/ip4/127.0.0.1/utp/tcp/5555/udp/1234/utp/ipfs/QmbHVEEepCi7rn7VL7Exxpd2Ci9NNB6ifvqwhsrbRMgQFP") + assertValueForProto(t, a, P_IP4, "127.0.0.1") + assertValueForProto(t, a, P_UTP, "") + assertValueForProto(t, a, P_TCP, "5555") + assertValueForProto(t, a, P_UDP, "1234") + assertValueForProto(t, a, P_IPFS, "QmbHVEEepCi7rn7VL7Exxpd2Ci9NNB6ifvqwhsrbRMgQFP") + + _, err := a.ValueForProtocol(P_IP6) + switch err { + case ErrProtocolNotFound: + break + case nil: + t.Fatal("expected value lookup to fail") + default: + t.Fatalf("expected ErrProtocolNotFound but got: %s", err) + } +} From ae64eb994b7729052bbe85ff106a5e2d302b1d7b Mon Sep 17 00:00:00 2001 From: Jeromy Date: Mon, 18 Jan 2016 00:35:47 -0800 Subject: [PATCH 3/3] rewrite value for protocols and add more tests --- multiaddr.go | 23 +++++------------------ multiaddr_test.go | 11 +++++++++++ 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/multiaddr.go b/multiaddr.go index 2343538..0dbcede 100644 --- a/multiaddr.go +++ b/multiaddr.go @@ -117,28 +117,15 @@ func (m *multiaddr) Decapsulate(o Multiaddr) Multiaddr { var ErrProtocolNotFound = fmt.Errorf("protocol not found in multiaddr") func (m *multiaddr) ValueForProtocol(code int) (string, error) { - protos := m.Protocols() - found := -1 - index := 2 - - for i, p := range protos { - if code == p.Code { + for _, sub := range Split(m) { + p := sub.Protocols()[0] + if p.Code == code { if p.Size == 0 { return "", nil } - found = i - break - } else { - index += 2 - if p.Size == 0 { - index-- - } + return strings.Split(sub.String(), "/")[2], nil } } - if found == -1 { - return "", ErrProtocolNotFound - } - - return strings.Split(m.String(), "/")[index], nil + return "", ErrProtocolNotFound } diff --git a/multiaddr_test.go b/multiaddr_test.go index e1994ff..7c75274 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -330,4 +330,15 @@ func TestGetValue(t *testing.T) { default: t.Fatalf("expected ErrProtocolNotFound but got: %s", err) } + + a = newMultiaddr(t, "/ip4/0.0.0.0") // only one addr + assertValueForProto(t, a, P_IP4, "0.0.0.0") + + a = newMultiaddr(t, "/ip4/0.0.0.0/ip4/0.0.0.0/ip4/0.0.0.0") // same sub-addr + assertValueForProto(t, a, P_IP4, "0.0.0.0") + + a = newMultiaddr(t, "/ip4/0.0.0.0/udp/12345/utp") // ending in a no-value one. + assertValueForProto(t, a, P_IP4, "0.0.0.0") + assertValueForProto(t, a, P_UDP, "12345") + assertValueForProto(t, a, P_UTP, "") }