Browse Source

Fix DNS and IPFS for Multiaddr (#43)

* Add DNS processing to multiaddr
* Fix IPFS resolution in multiaddr
* Fix comment about IPFS/P2P in multiaddr
pull/44/head
Harrm 5 years ago
committed by GitHub
parent
commit
2c23ef1b8d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      include/libp2p/multi/converters/dns_converter.hpp
  2. 9
      include/libp2p/multi/multiaddress_protocol_list.hpp
  3. 1
      src/multi/converters/CMakeLists.txt
  4. 7
      src/multi/converters/converter_utils.cpp
  5. 20
      src/multi/converters/dns_converter.cpp
  6. 17
      src/multi/multiaddress.cpp
  7. 16
      test/libp2p/multi/multiaddress_test.cpp
  8. 6
      test/libp2p/multi/utils/string_from_to_bytes_test.cpp
  9. 2
      test/libp2p/peer/peer_address_test.cpp

25
include/libp2p/multi/converters/dns_converter.hpp

@ -0,0 +1,25 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LIBP2P_DNS_CONVERTER_HPP
#define LIBP2P_DNS_CONVERTER_HPP
#include <libp2p/outcome/outcome.hpp>
namespace libp2p::multi::converters {
/**
* Converts a DNS part of a multiaddress (a hostname)
* to bytes representation as a hex string
*/
class DnsConverter {
public:
static auto addressToHex(std::string_view addr)
-> outcome::result<std::string>;
};
} // namespace libp2p::multi::converters
#endif // LIBP2P_DNS_CONVERTER_HPP

9
include/libp2p/multi/multiaddress_protocol_list.hpp

@ -78,6 +78,9 @@ namespace libp2p::multi {
* otherwise * otherwise
*/ */
static constexpr auto get(std::string_view name) -> Protocol const * { static constexpr auto get(std::string_view name) -> Protocol const * {
if(name == "ipfs") {
name = "p2p"; // IPFS is a legacy name, P2P is the preferred one
}
for (Protocol const &protocol : protocols_) { for (Protocol const &protocol : protocols_) {
if (protocol.name == name) { if (protocol.name == name) {
return &protocol; return &protocol;
@ -120,15 +123,15 @@ namespace libp2p::multi {
{Protocol::Code::IP6, 128, "ip6"}, {Protocol::Code::IP6, 128, "ip6"},
{Protocol::Code::IP6_ZONE, Protocol::kVarLen, "ip6zone"}, {Protocol::Code::IP6_ZONE, Protocol::kVarLen, "ip6zone"},
{Protocol::Code::DNS, Protocol::kVarLen, "dns"}, {Protocol::Code::DNS, Protocol::kVarLen, "dns"},
{Protocol::Code::DNS4, Protocol::kVarLen, "dns64"}, {Protocol::Code::DNS4, Protocol::kVarLen, "dns4"},
{Protocol::Code::DNS6, Protocol::kVarLen, "dns6"}, {Protocol::Code::DNS6, Protocol::kVarLen, "dns6"},
{Protocol::Code::DNS_ADDR, Protocol::kVarLen, "dnsaddr"}, {Protocol::Code::DNS_ADDR, Protocol::kVarLen, "dnsaddr"},
{Protocol::Code::SCTP, 16, "sctp"}, {Protocol::Code::SCTP, 16, "sctp"},
{Protocol::Code::UDT, 0, "udt"}, {Protocol::Code::UDT, 0, "udt"},
{Protocol::Code::UTP, 0, "utp"}, {Protocol::Code::UTP, 0, "utp"},
{Protocol::Code::UNIX, Protocol::kVarLen, "unix"}, {Protocol::Code::UNIX, Protocol::kVarLen, "unix"},
// {Protocol::Code::P2P, Protocol::kVarLen, "p2p"}, {Protocol::Code::P2P, Protocol::kVarLen, "p2p"},
{Protocol::Code::P2P, Protocol::kVarLen, "ipfs"}, // Also P2P protocol may have a legacy name "ipfs"
{Protocol::Code::ONION, 96, "onion"}, {Protocol::Code::ONION, 96, "onion"},
{Protocol::Code::ONION3, 296, "onion3"}, {Protocol::Code::ONION3, 296, "onion3"},
{Protocol::Code::GARLIC64, Protocol::kVarLen, "garlic64"}, {Protocol::Code::GARLIC64, Protocol::kVarLen, "garlic64"},

1
src/multi/converters/CMakeLists.txt

@ -11,6 +11,7 @@ libp2p_add_library(p2p_converters
tcp_converter.cpp tcp_converter.cpp
udp_converter.cpp udp_converter.cpp
ipfs_converter.cpp ipfs_converter.cpp
dns_converter.cpp
) )
target_link_libraries(p2p_converters target_link_libraries(p2p_converters
Boost::boost Boost::boost

7
src/multi/converters/converter_utils.cpp

@ -14,6 +14,7 @@
#include <libp2p/multi/converters/ip_v4_converter.hpp> #include <libp2p/multi/converters/ip_v4_converter.hpp>
#include <libp2p/multi/converters/ip_v6_converter.hpp> #include <libp2p/multi/converters/ip_v6_converter.hpp>
#include <libp2p/multi/converters/ipfs_converter.hpp> #include <libp2p/multi/converters/ipfs_converter.hpp>
#include <libp2p/multi/converters/dns_converter.hpp>
#include <libp2p/multi/converters/tcp_converter.hpp> #include <libp2p/multi/converters/tcp_converter.hpp>
#include <libp2p/multi/converters/udp_converter.hpp> #include <libp2p/multi/converters/udp_converter.hpp>
#include <libp2p/multi/multiaddress_protocol_list.hpp> #include <libp2p/multi/multiaddress_protocol_list.hpp>
@ -89,12 +90,14 @@ namespace libp2p::multi::converters {
case Protocol::Code::P2P: case Protocol::Code::P2P:
return IpfsConverter::addressToHex(addr); return IpfsConverter::addressToHex(addr);
case Protocol::Code::IP6_ZONE:
case Protocol::Code::DNS: case Protocol::Code::DNS:
case Protocol::Code::DNS4: case Protocol::Code::DNS4:
case Protocol::Code::DNS6: case Protocol::Code::DNS6:
case Protocol::Code::DNS_ADDR: case Protocol::Code::DNS_ADDR:
case Protocol::Code::UNIX: case Protocol::Code::UNIX:
return DnsConverter::addressToHex(addr);
case Protocol::Code::IP6_ZONE:
case Protocol::Code::ONION3: case Protocol::Code::ONION3:
case Protocol::Code::GARLIC64: case Protocol::Code::GARLIC64:
case Protocol::Code::QUIC: case Protocol::Code::QUIC:
@ -127,7 +130,7 @@ namespace libp2p::multi::converters {
return ConversionError::NO_SUCH_PROTOCOL; return ConversionError::NO_SUCH_PROTOCOL;
} }
if (protocol->name != "ipfs") { if (protocol->name != "ipfs" and protocol->name != "p2p") {
lastpos = lastpos lastpos = lastpos
+ UVarint::calculateSize(pid_bytes.subspan(lastpos / 2)) * 2; + UVarint::calculateSize(pid_bytes.subspan(lastpos / 2)) * 2;
std::string address; std::string address;

20
src/multi/converters/dns_converter.cpp

@ -0,0 +1,20 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#include <libp2p/multi/converters/dns_converter.hpp>
#include <libp2p/common/hexutil.hpp>
#include <libp2p/multi/uvarint.hpp>
namespace libp2p::multi::converters {
auto DnsConverter::addressToHex(std::string_view addr)
-> outcome::result<std::string> {
std::vector<uint8_t> bytes(addr.size());
std::copy(addr.begin(), addr.end(), bytes.begin());
auto hex = common::hex_lower(bytes);
return UVarint{bytes.size()}.toHex() + hex;
}
}

17
src/multi/multiaddress.cpp

@ -127,6 +127,17 @@ namespace libp2p::multi {
bool Multiaddress::decapsulateStringFromAddress(std::string_view proto, bool Multiaddress::decapsulateStringFromAddress(std::string_view proto,
const ByteBuffer &bytes) { const ByteBuffer &bytes) {
auto str_pos = stringified_address_.rfind(proto); auto str_pos = stringified_address_.rfind(proto);
if (proto == "/p2p" or proto == "/ipfs") {
auto alt_pos =
stringified_address_.rfind(proto == "/ipfs" ? "/p2p" : "/ipfs");
if (alt_pos != std::string::npos) {
if(str_pos == std::string::npos) {
str_pos = alt_pos;
} else {
str_pos = std::max(str_pos, alt_pos);
}
}
}
if (str_pos == std::string::npos) { if (str_pos == std::string::npos) {
return false; return false;
} }
@ -167,6 +178,12 @@ namespace libp2p::multi {
auto proto_str = "/"s + std::string(protocol->name); auto proto_str = "/"s + std::string(protocol->name);
auto proto_positions = auto proto_positions =
findSubstringOccurrences(stringified_address_, proto_str); findSubstringOccurrences(stringified_address_, proto_str);
if (proto == Protocol::Code::P2P) { // ipfs and p2p are equivalent
auto ipfs_occurences =
findSubstringOccurrences(stringified_address_, "/ipfs"s);
proto_positions.insert(proto_positions.end(), ipfs_occurences.begin(),
ipfs_occurences.end());
}
for (const auto &pos : proto_positions) { for (const auto &pos : proto_positions) {
auto value_pos = stringified_address_.find_first_of('/', pos + 1) + 1; auto value_pos = stringified_address_.find_first_of('/', pos + 1) + 1;

16
test/libp2p/multi/multiaddress_test.cpp

@ -38,9 +38,7 @@ class MultiaddressTest : public ::testing::Test {
* @then creation succeeds * @then creation succeeds
*/ */
TEST_F(MultiaddressTest, CreateFromStringValid) { TEST_F(MultiaddressTest, CreateFromStringValid) {
auto result = Multiaddress::create(valid_ip_udp); EXPECT_OUTCOME_TRUE(address, Multiaddress::create(valid_ip_udp));
ASSERT_TRUE(result);
auto &&address = result.value();
ASSERT_EQ(address.getStringAddress(), valid_ip_udp); ASSERT_EQ(address.getStringAddress(), valid_ip_udp);
ASSERT_EQ(address.getBytesAddress(), valid_ip_udp_bytes); ASSERT_EQ(address.getBytesAddress(), valid_ip_udp_bytes);
} }
@ -245,3 +243,15 @@ TEST_F(MultiaddressTest, GetProtocolsWithValues) {
std::make_pair(*ProtocolList::get("ip4"), "127.0.0.1"), std::make_pair(*ProtocolList::get("ip4"), "127.0.0.1"),
std::make_pair(*ProtocolList::get("udp"), "3232"))); std::make_pair(*ProtocolList::get("udp"), "3232")));
} }
/**
* @given a multiaddr containing DNS and P2P entries
* @when parsing it
* @then it is accepted
*/
TEST_F(MultiaddressTest, DnsAndIpfs) {
auto addr = "/dns4/kusama-bootnode-1.paritytech.net/tcp/30333/p2p/QmV32G18YzenpNFmhqg2n7TtdjYRK7oU6FhLbDL4oRgsbe"s;
EXPECT_OUTCOME_TRUE(address, Multiaddress::create(addr));
ASSERT_EQ(address.getStringAddress(), addr);
}

6
test/libp2p/multi/utils/string_from_to_bytes_test.cpp

@ -79,7 +79,7 @@ TEST(AddressConverter, BytesToString) {
VALID_BYTES_TO_STR("/udp/1234", "910204D2") VALID_BYTES_TO_STR("/udp/1234", "910204D2")
VALID_BYTES_TO_STR("/tcp/1234", "0604D2") VALID_BYTES_TO_STR("/tcp/1234", "0604D2")
VALID_BYTES_TO_STR( VALID_BYTES_TO_STR(
"/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", "/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
"A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C" "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C"
"0B0604D2") "0B0604D2")
VALID_BYTES_TO_STR("/ip4/127.0.0.1/udp/1234", "047F000001910204D2") VALID_BYTES_TO_STR("/ip4/127.0.0.1/udp/1234", "047F000001910204D2")
@ -87,11 +87,11 @@ TEST(AddressConverter, BytesToString) {
VALID_BYTES_TO_STR("/ip4/127.0.0.1/tcp/1234/udp/0/udp/1234", VALID_BYTES_TO_STR("/ip4/127.0.0.1/tcp/1234/udp/0/udp/1234",
"047F0000010604D291020000910204D2") "047F0000010604D291020000910204D2")
VALID_BYTES_TO_STR( VALID_BYTES_TO_STR(
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", "/ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
"047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20D" "047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20D"
"B76A68911C0B") "B76A68911C0B")
VALID_BYTES_TO_STR( VALID_BYTES_TO_STR(
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/" "/ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/"
"1234", "1234",
"047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20D" "047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20D"
"B76A68911C0B0604D2") "B76A68911C0B0604D2")

2
test/libp2p/peer/peer_address_test.cpp

@ -36,7 +36,7 @@ class PeerAddressTest : public ::testing::Test {
Multiaddress::create("/ip4/192.168.0.1/tcp/228").value(); Multiaddress::create("/ip4/192.168.0.1/tcp/228").value();
const std::string kaddressString = const std::string kaddressString =
std::string{kDefaultAddress.getStringAddress()} + "/ipfs/" std::string{kDefaultAddress.getStringAddress()} + "/p2p/"
+ kEncodedDefaultPeerId; + kEncodedDefaultPeerId;
}; };

Loading…
Cancel
Save