Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for dns #26

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gx/lastpubver
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.0.0: QmVamAeNWEFjKqNZLCMo4EiYrFRnZsMQyXocPvjyXZJJj2
84 changes: 59 additions & 25 deletions codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ func stringToBytes(s string) ([]byte, error) {
if len(sp) < 1 {
return nil, fmt.Errorf("protocol requires address, none given: %s", p.Name)
}
a, err := addressStringToBytes(p, sp[0])
a, sr, err := addressStringToBytes(p, sp)
if err != nil {
return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err)
}
sp = sr
b = append(b, a...)
sp = sp[1:]
}
return b, nil
}
Expand Down Expand Up @@ -136,82 +136,101 @@ func bytesSplit(b []byte) (ret [][]byte, err error) {
return ret, nil
}

func addressStringToBytes(p Protocol, s string) ([]byte, error) {
func addressStringToBytes(p Protocol, s []string) ([]byte, []string, error) {
switch p.Code {

case P_IP4: // ipv4
i := net.ParseIP(s).To4()
i := net.ParseIP(s[0]).To4()
if i == nil {
return nil, fmt.Errorf("failed to parse ip4 addr: %s", s)
return nil, s, fmt.Errorf("failed to parse ip4 addr: %s", s[0])
}
return i, nil
s = s[1:]
return i, s, nil

case P_IP6: // ipv6
i := net.ParseIP(s).To16()
i := net.ParseIP(s[0]).To16()
if i == nil {
return nil, fmt.Errorf("failed to parse ip6 addr: %s", s)
return nil, s, fmt.Errorf("failed to parse ip6 addr: %s", s)
}
return i, nil
s = s[1:]
return i, s, nil

// tcp udp dccp sctp
case P_TCP, P_UDP, P_DCCP, P_SCTP:
i, err := strconv.Atoi(s)
i, err := strconv.Atoi(s[0])
if err != nil {
return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, err)
return nil, s, fmt.Errorf("failed to parse %s addr: %s", p.Name, err)
}
if i >= 65536 {
return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, "greater than 65536")
return nil, s, fmt.Errorf("failed to parse %s addr: %s", p.Name, "greater than 65536")
}
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, uint16(i))
return b, nil
s = s[1:]
return b, s, nil

case P_ONION:
addr := strings.Split(s, ":")
addr := strings.Split(s[0], ":")
if len(addr) != 2 {
return nil, fmt.Errorf("failed to parse %s addr: %s does not contain a port number.", p.Name, s)
return nil, s, fmt.Errorf("failed to parse %s addr: %s does not contain a port number.", p.Name, s[0])
}

// onion address without the ".onion" substring
if len(addr[0]) != 16 {
return nil, fmt.Errorf("failed to parse %s addr: %s not a Tor onion address.", p.Name, s)
return nil, s, fmt.Errorf("failed to parse %s addr: %s not a Tor onion address.", p.Name, s)
}
onionHostBytes, err := base32.StdEncoding.DecodeString(strings.ToUpper(addr[0]))
if err != nil {
return nil, fmt.Errorf("failed to decode base32 %s addr: %s %s", p.Name, s, err)
return nil, s, fmt.Errorf("failed to decode base32 %s addr: %s %s", p.Name, s, err)
}

// onion port number
i, err := strconv.Atoi(addr[1])
if err != nil {
return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, err)
return nil, s, fmt.Errorf("failed to parse %s addr: %s", p.Name, err)
}
if i >= 65536 {
return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, "port greater than 65536")
return nil, s, fmt.Errorf("failed to parse %s addr: %s", p.Name, "port greater than 65536")
}
if i < 1 {
return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, "port less than 1")
return nil, s, fmt.Errorf("failed to parse %s addr: %s", p.Name, "port less than 1")
}

onionPortBytes := make([]byte, 2)
binary.BigEndian.PutUint16(onionPortBytes, uint16(i))
bytes := []byte{}
bytes = append(bytes, onionHostBytes...)
bytes = append(bytes, onionPortBytes...)
return bytes, nil
s = s[1:]
return bytes, s, nil

case P_IPFS: // ipfs
// the address is a varint prefixed multihash string representation
m, err := mh.FromB58String(s)
m, err := mh.FromB58String(s[0])
if err != nil {
return nil, fmt.Errorf("failed to parse ipfs addr: %s %s", s, err)
return nil, s, fmt.Errorf("failed to parse ipfs addr: %s %s", s, err)
}
size := CodeToVarint(len(m))
b := append(size, m...)
return b, nil
s = s[1:]
return b, s, nil

case P_DNS: // dns
b := append(CodeToVarint(len(s[0])+1), []byte(s[0])...)
s = s[1:]
if len(s) == 0 {
return nil, s, fmt.Errorf("ip version not specified in dns addr")
}
p := ProtocolWithName(s[0])
if p.Code != P_IP4 && p.Code != P_IP6 {
return nil, s, fmt.Errorf("unsupported ip version in dns addr: %s", s[0])
}
b = append(b, byte(p.Code))
s = s[1:]
return b, s, nil
}

return []byte{}, fmt.Errorf("failed to parse %s addr: unknown", p.Name)
return []byte{}, s, fmt.Errorf("failed to parse %s addr: unknown", p.Name)
}

func addressBytesToString(p Protocol, b []byte) (string, error) {
Expand All @@ -238,6 +257,21 @@ func addressBytesToString(p Protocol, b []byte) (string, error) {
return "", err
}
return m.B58String(), nil

case P_DNS: // dns
size, n := ReadVarintCode(b)
b = b[n:]
if len(b) != size {
panic("inconsistent lengths")
}
s := string(b[:len(b)-1])
c := int(b[len(b)-1])
p := ProtocolWithCode(c)
if p.Code != P_IP4 && p.Code != P_IP6 {
panic(fmt.Sprintf("unsupported dns address protocol %s", s[0]))
}

return fmt.Sprintf("%s/%s", s, p.Name), nil
}

return "", fmt.Errorf("unknown protocol")
Expand Down
2 changes: 1 addition & 1 deletion multiaddr.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func (m *multiaddr) ValueForProtocol(code int) (string, error) {
if p.Size == 0 {
return "", nil
}
return strings.Split(sub.String(), "/")[2], nil
return strings.Join(strings.Split(sub.String(), "/")[2:], "/"), nil
}
}

Expand Down
27 changes: 25 additions & 2 deletions multiaddr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ func TestConstructFails(t *testing.T) {
"/ip4/127.0.0.1/tcp",
"/ip4/127.0.0.1/ipfs",
"/ip4/127.0.0.1/ipfs/tcp",
"/dns/ipfs.io",
"/dns/ipfs.io/ip3/tcp/1234",
"/dns/ipfs.io/udp/1234",
}

for _, a := range cases {
Expand Down Expand Up @@ -78,6 +81,8 @@ func TestConstructSucceeds(t *testing.T) {
"/ip4/127.0.0.1/tcp/1234/",
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
"/dns/www.google.com/ip4/tcp/1234",
"/dns/www.yahoo.com/ip6/udp/1234",
}

for _, a := range cases {
Expand Down Expand Up @@ -136,13 +141,14 @@ func TestStringToBytes(t *testing.T) {
}

if !bytes.Equal(b1, b2) {
t.Error("failed to convert", s, "to", b1, "got", b2)
t.Error("failed to convert", s, "to", hex.EncodeToString(b1), "got", hex.EncodeToString(b2))
}
}

testString("/ip4/127.0.0.1/udp/1234", "047f0000011104d2")
testString("/ip4/127.0.0.1/tcp/4321", "047f0000010610e1")
testString("/ip4/127.0.0.1/udp/1234/ip4/127.0.0.1/tcp/4321", "047f0000011104d2047f0000010610e1")
testString("/dns/www.google.com/ip4/tcp/1234", "bd030f7777772e676f6f676c652e636f6d040604d2")
}

func TestBytesToString(t *testing.T) {
Expand All @@ -159,13 +165,14 @@ func TestBytesToString(t *testing.T) {
}

if s1 != s2 {
t.Error("failed to convert", b, "to", s1, "got", s2)
t.Error("failed to convert", hex.EncodeToString(b), "to", s1, "got", s2)
}
}

testString("/ip4/127.0.0.1/udp/1234", "047f0000011104d2")
testString("/ip4/127.0.0.1/tcp/4321", "047f0000010610e1")
testString("/ip4/127.0.0.1/udp/1234/ip4/127.0.0.1/tcp/4321", "047f0000011104d2047f0000010610e1")
testString("/dns/www.google.com/ip4/tcp/1234", "bd030f7777772e676f6f676c652e636f6d040604d2")
}

func TestBytesSplitAndJoin(t *testing.T) {
Expand Down Expand Up @@ -211,6 +218,7 @@ func TestBytesSplitAndJoin(t *testing.T) {
[]string{"/ip4/1.2.3.4", "/tcp/1", "/ip4/2.3.4.5", "/udp/2"})
testString("/ip4/1.2.3.4/utp/ip4/2.3.4.5/udp/2/udt",
[]string{"/ip4/1.2.3.4", "/utp", "/ip4/2.3.4.5", "/udp/2", "/udt"})
testString("/dns/www.google.com/ip4/udp/2", []string{"/dns/www.google.com/ip4", "/udp/2"})
}

func TestProtocols(t *testing.T) {
Expand Down Expand Up @@ -299,6 +307,17 @@ func TestEncapsulate(t *testing.T) {
if s := d.String(); s != "" {
t.Error("decapsulate /ip4 failed.", "/", s)
}

m5, _ := NewMultiaddr("/dns/www.google.com/ip4")
e := m5.Encapsulate(m3)
if s := e.String(); s != "/dns/www.google.com/ip4/udp/5678" {
t.Error("encapsulate /dns/www.google.com/ip4/udp/5678")
}

f := e.Decapsulate(m3)
if s := f.String(); s != "/dns/www.google.com/ip4" {
t.Error("decapsulate /udp failed.", "/dns/www.google.com/ip4", s)
}
}

func assertValueForProto(t *testing.T, a Multiaddr, p int, exp string) {
Expand Down Expand Up @@ -341,4 +360,8 @@ func TestGetValue(t *testing.T) {
assertValueForProto(t, a, P_IP4, "0.0.0.0")
assertValueForProto(t, a, P_UDP, "12345")
assertValueForProto(t, a, P_UTP, "")

a = newMultiaddr(t, "/dns/www.google.com/ip4/udp/12345")
assertValueForProto(t, a, P_DNS, "www.google.com/ip4")
assertValueForProto(t, a, P_UDP, "12345")
}
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"author": "sivachandran",
"bugs": {},
"gx": {
"dvcsimport": "github.com/RealImage/go-multiaddr"
},
"gxVersion": "0.4.0",
"language": "go",
"license": "",
"name": "go-multiaddr",
"version": "0.0.0"
}
3 changes: 2 additions & 1 deletion protocols.csv
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ code size name
421 V ipfs
480 0 http
443 0 https
444 10 onion
444 10 onion
445 V dns
2 changes: 2 additions & 0 deletions protocols.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const (
P_HTTP = 480
P_HTTPS = 443
P_ONION = 444
P_DNS = 445
)

// These are special sizes
Expand All @@ -53,6 +54,7 @@ var Protocols = []Protocol{
Protocol{P_HTTP, 0, "http", CodeToVarint(P_HTTP)},
Protocol{P_HTTPS, 0, "https", CodeToVarint(P_HTTPS)},
Protocol{P_IPFS, LengthPrefixedVarSize, "ipfs", CodeToVarint(P_IPFS)},
Protocol{P_DNS, LengthPrefixedVarSize, "dns", CodeToVarint(P_DNS)},
}

func AddProtocol(p Protocol) error {
Expand Down