diff --git a/libp2p/multiaddress.nim b/libp2p/multiaddress.nim index 9fd636c20..054fb00e8 100644 --- a/libp2p/multiaddress.nim +++ b/libp2p/multiaddress.nim @@ -222,6 +222,40 @@ proc onionVB(vb: var VBuffer): bool = if vb.readArray(buf) == 12: result = true +proc onion3StB(s: string, vb: var VBuffer): bool = + try: + var parts = s.split(':') + if len(parts) != 2: + return false + if len(parts[0]) != 56: + return false + var address = Base32Lower.decode(parts[0].toLowerAscii()) + var nport = parseInt(parts[1]) + if (nport > 0 and nport < 65536) and len(address) == 35: + address.setLen(37) + address[35] = cast[byte]((nport shr 8) and 0xFF) + address[36] = cast[byte](nport and 0xFF) + vb.writeArray(address) + result = true + except: + discard + +proc onion3BtS(vb: var VBuffer, s: var string): bool = + ## ONION address bufferToString() implementation. + var buf: array[37, byte] + if vb.readArray(buf) == 37: + var nport = (cast[uint16](buf[35]) shl 8) or cast[uint16](buf[36]) + s = Base32Lower.encode(buf.toOpenArray(0, 34)) + s.add(":") + s.add($nport) + result = true + +proc onion3VB(vb: var VBuffer): bool = + ## ONION address validateBuffer() implementation. + var buf: array[37, byte] + if vb.readArray(buf) == 37: + result = true + proc unixStB(s: string, vb: var VBuffer): bool = ## Unix socket name stringToBuffer() implementation. if len(s) > 0: @@ -310,6 +344,11 @@ const bufferToString: onionBtS, validateBuffer: onionVB ) + TranscoderOnion3* = Transcoder( + stringToBuffer: onion3StB, + bufferToString: onion3BtS, + validateBuffer: onion3VB + ) TranscoderDNS* = Transcoder( stringToBuffer: dnsStB, bufferToString: dnsBtS, @@ -363,6 +402,10 @@ const mcodec: multiCodec("onion"), kind: Fixed, size: 10, coder: TranscoderOnion ), + MAProtocol( + mcodec: multiCodec("onion3"), kind: Fixed, size: 37, + coder: TranscoderOnion3 + ), MAProtocol( mcodec: multiCodec("ws"), kind: Marker, size: 0 ), diff --git a/libp2p/multicodec.nim b/libp2p/multicodec.nim index 0cfc4c558..a1f710656 100644 --- a/libp2p/multicodec.nim +++ b/libp2p/multicodec.nim @@ -203,6 +203,7 @@ const MultiCodecList = [ ("p2p-webrtc-star", 0x0113), # not in multicodec list ("p2p-webrtc-direct", 0x0114), # not in multicodec list ("onion", 0x01BC), + ("onion3", 0x01BD), ("p2p-circuit", 0x0122), ("libp2p-peer-record", 0x0301), ("dns", 0x35), diff --git a/tests/testmultiaddress.nim b/tests/testmultiaddress.nim index 4ce91f729..2c05e212e 100644 --- a/tests/testmultiaddress.nim +++ b/tests/testmultiaddress.nim @@ -22,6 +22,8 @@ const "/ip6zone/x/ip6/fe80::1/udp/1234/quic", "/onion/timaq4ygg2iegci7:1234", "/onion/timaq4ygg2iegci7:80/http", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:1234", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:80/http", "/udp/0", "/tcp/0", "/sctp/0", @@ -79,6 +81,12 @@ const "/onion/timaq4ygg2iegci7:-1", "/onion/timaq4ygg2iegci7", "/onion/timaq4ygg2iegci@:666", + "/onion3/9ww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:80", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd7:80", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:0", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:-1", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyy@:666", "/udp/1234/sctp", "/udp/1234/udt/1234", "/udp/1234/utp/1234", @@ -170,6 +178,12 @@ const "/onion/timaq4ygg2iegci7:-1", "/onion/timaq4ygg2iegci7", "/onion/timaq4ygg2iegci@:666", + "/onion3/9ww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:80", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd7:80", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:0", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:-1", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd", + "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyy@:666", "/udp/1234/sctp", "/udp/1234/udt/1234", "/udp/1234/utp/1234", @@ -376,3 +390,15 @@ suite "MultiAddress test suite": $ma[1..2].get() == "/tcp/0/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC" $ma[^3..^1].get() == "/p2p-circuit/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSuNEXT/unix/stdio" ma[5..7].isErr() + + test "[](MultiCodec) test": + let onionMAStr = "/onion3/torchdeedp3i2jigzjdmfpn5ttjhthh5wbmda2rr3jvqjg5p77c54dqd:80" + let ma = MultiAddress.init(onionMAStr).get() + check $(ma[multiCodec("onion3")].tryGet()) == onionMAStr + + let onionMAWithTcpStr = "/onion3/torchdeedp3i2jigzjdmfpn5ttjhthh5wbmda2rr3jvqjg5p77c54dqd:80/tcp/80" + let maWithTcp = MultiAddress.init(onionMAWithTcpStr).get() + check $(maWithTcp[multiCodec("onion3")].tryGet()) == onionMAStr + + +