cpp-libp2p源码阅读笔记:(二)网络模块

 1 #ifndef LIBP2P_CONNECTION_MANAGER_IMPL_HPP
 2 #define LIBP2P_CONNECTION_MANAGER_IMPL_HPP
 3 
 4 #include <unordered_set>
 5 
 6 #include <libp2p/event/bus.hpp>
 7 #include <libp2p/network/connection_manager.hpp>
 8 #include <libp2p/network/transport_manager.hpp>
 9 #include <libp2p/peer/peer_id.hpp>
10 
11 namespace libp2p::network {
12 
13   class ConnectionManagerImpl : public ConnectionManager {
14    public:
15     explicit ConnectionManagerImpl(std::shared_ptr<libp2p::event::Bus> bus);
16 
17     std::vector<ConnectionSPtr> getConnections() const override;
18 
19     std::vector<ConnectionSPtr> getConnectionsToPeer(
20         const peer::PeerId &p) const override;
21 
22     ConnectionSPtr getBestConnectionForPeer(
23         const peer::PeerId &p) const override;
24 
25     void addConnectionToPeer(const peer::PeerId &p, ConnectionSPtr c) override;
26 
27     void collectGarbage() override;
28 
29     void closeConnectionsToPeer(const peer::PeerId &p) override;
30 
31     void onConnectionClosed(
32         const peer::PeerId &peer_id,
33         const std::shared_ptr<connection::CapableConnection> &conn) override;
34 
35    private:
36     std::unordered_map<peer::PeerId, std::unordered_set<ConnectionSPtr>>
37         connections_;
38 
39     std::shared_ptr<libp2p::event::Bus> bus_;
40 
41     /// Reentrancy resolver between closeConnectionsToPeer and
42     /// onConnectionClosed
43     boost::optional<peer::PeerId> closing_connections_to_peer_;
44   };
45 
46 }  // namespace libp2p::network
47 
48 #endif  // LIBP2P_CONNECTION_MANAGER_IMPL_HPP

这段代码实现了一个名为 ConnectionManagerImpl 的类,它维护了对一组对等体的连接(peer)。它是 libp2p 网络库中的一个组件,用于管理与其他对等体的连接。

  1. 函数 `getConnectionsToPeer` 返回与给定的 peer 关联的连接的 vector。
  2. 函数 `getBestConnectionForPeer` 返回与给定的 peer 关联的最佳(当前未关闭的)连接。
  3. 函数 `addConnectionToPeer` 将一个连接添加到与给定的 peer 关联的连接列表中。
  4. 函数 `getConnections` 返回管理的所有连接的 vector。
  5. 构造函数` ConnectionManagerImpl` 接收一个事件总线(event bus)作为参数,用于在连接发生更改时发布通知。
  6. 函数 `collectGarbage` 清理已关闭的连接。
  7. 函数 `closeConnectionsToPeer` 关闭与给定 peer 关联的所有连接。
  8. 函数 `onConnectionClosed` 在连接关闭时调用,从维护的连接列表中删除该连接。
 1 #ifndef LIBP2P_DIALER_IMPL_HPP
 2 #define LIBP2P_DIALER_IMPL_HPP
 3 
 4 #include <set>
 5 #include <unordered_map>
 6 
 7 #include <libp2p/basic/scheduler.hpp>
 8 #include <libp2p/network/connection_manager.hpp>
 9 #include <libp2p/network/dialer.hpp>
10 #include <libp2p/network/listener_manager.hpp>
11 #include <libp2p/network/transport_manager.hpp>
12 #include <libp2p/protocol_muxer/protocol_muxer.hpp>
13 
14 namespace libp2p::network {
15 
16   class DialerImpl : public Dialer,
17                      public std::enable_shared_from_this<DialerImpl> {
18    public:
19     ~DialerImpl() override = default;
20 
21     DialerImpl(std::shared_ptr<protocol_muxer::ProtocolMuxer> multiselect,
22                std::shared_ptr<TransportManager> tmgr,
23                std::shared_ptr<ConnectionManager> cmgr,
24                std::shared_ptr<ListenerManager> listener,
25                std::shared_ptr<basic::Scheduler> scheduler);
26 
27     // Establishes a connection to a given peer
28     void dial(const peer::PeerInfo &p, DialResultFunc cb,
29               std::chrono::milliseconds timeout) override;
30 
31     // NewStream returns a new stream to given peer p.
32     // If there is no connection to p, attempts to create one.
33     void newStream(const peer::PeerInfo &p, StreamProtocols protocols,
34                    StreamAndProtocolOrErrorCb cb,
35                    std::chrono::milliseconds timeout = {}) override;
36 
37     void newStream(const peer::PeerId &peer_id, StreamProtocols protocols,
38                    StreamAndProtocolOrErrorCb cb) override;
39 
40    private:
41     // A context to handle an intermediary state of the peer we are dialing to
42     // but the connection is not yet established
43     struct DialCtx {
44       /// Known and scheduled addresses to try to dial via
45       std::set<multi::Multiaddress> addresses;
46 
47       /// Timeout for a single connection attempt
48       std::chrono::milliseconds timeout;
49 
50       /// Addresses we already tried, but no connection was established
51       std::set<multi::Multiaddress> tried_addresses;
52 
53       /// Callbacks for all who requested a connection to the peer
54       std::vector<Dialer::DialResultFunc> callbacks;
55 
56       /// Result temporary storage to propagate via callbacks
57       boost::optional<DialResult> result;
58       // ^ used when all connecting attempts failed and no more known peer
59       // addresses are left
60 
61       // indicates that at least one attempt to dial was happened
62       // (at least one supported network transport was found and used)
63       bool dialled = false;
64     };
65 
66     // Perform a single attempt to dial to the peer via the next known address
67     void rotate(const peer::PeerId &peer_id);
68 
69     // Finalize dialing to the peer and propagate a given result to all
70     // connection requesters
71     void completeDial(const peer::PeerId &peer_id, const DialResult &result);
72 
73     void newStream(std::shared_ptr<connection::CapableConnection> conn,
74                    StreamProtocols protocols, StreamAndProtocolOrErrorCb cb);
75 
76     std::shared_ptr<protocol_muxer::ProtocolMuxer> multiselect_;
77     std::shared_ptr<TransportManager> tmgr_;
78     std::shared_ptr<ConnectionManager> cmgr_;
79     std::shared_ptr<ListenerManager> listener_;
80     std::shared_ptr<basic::Scheduler> scheduler_;
81     log::Logger log_;
82 
83     // peers we are currently dialing to
84     std::unordered_map<peer::PeerId, DialCtx> dialing_peers_;
85   };
86 
87 }  // namespace libp2p::network
88 
89 #endif  // LIBP2P_DIALER_IMPL_HPP

这段代码主要定义了一个名为 `ListenerManagerImpl` 的类,该类实现了一些监听地址的操作。下面是该类中的各个函数的详细说明:

  • 构造函数`ListenerManagerImpl` :该函数会接收一个协议多路复用器,一个路由器,一个传输管理器和一个连接管理器。该函数会调用 BOOST_ASSERT 函数来保证这些参数都不为空。该函数会将这些参数赋值给对应的成员变量 multiselect_、router_、tmgr_ 和 cmgr_。
  • 函数 `isStarted`:该函数返回一个 bool 类型的值,表示监听是否已经启动。
  • 函数  `closeListener` :该函数接收一个多地址参数,会首先检查该多地址是否已经在监听列表中。如果存在,则关闭该监听器并将其从监听列表中删除;否则,该函数会在整个监听列表中查找是否有监听地址是该多地址的接口地址,如果找到,则关闭该监听器并将其从监听列表中删除。如果既找不到该多地址也找不到该多地址的接口地址,则返回一个 std::errc::invalid_argument 类型的错误。
  • 函数  `removeListene` :该函数接收一个多地址参数,会在监听列表中查找该多地址是否存在,如果存在,则将其删除;否则,返回一个 std::errc::invalid_argument 类型的错误。
  • 函数  `start` :该函数用于启动监听器,如果监听器已经启动,则不执行任何操作。该函数会对监听列表中的所有监听器进行启动操作。
  • 函数  `stop` :该函数用于停止监听器,如果监听器已经停止,则不执行任何操作。该函数会对监听列表中的所有监听器进行停止操作。
  • 函数  `listen` :该函数接收一个多地址参数,会首先通过传输管理器找到一个最优的传输方式。如果找不到,则返回 std::errc::address_family_not_supported 类型的错误。如果找到了,则会在监听列表中查找该多地址是否已经存在,如果存在,则返回 std::errc::address_in_use 类型的错误。如果不存在,则会通过传输方式创建一个新的监听器,并将其加入到监听列表中。
  • 函数 `getListenAddresses`:该函数返回一个包含所有监听地址的 vector。
  • 函数  `getListenAddressesInterfaces`:该函数返回一个包含所有监听接口地址的 vector。
  • 函数  `onConnection`:该函数会在有新的连接建立时被调用,该函数接收一个 std::shared_ptrconnection::CapableConnection 类型的参数。在函数体内,该函数会获取远程节点的 ID,并调用 ConnectionManager 的 onConnection 函数来处理该连接。
 1 #ifndef LIBP2P_DIALER_IMPL_HPP
 2 #define LIBP2P_DIALER_IMPL_HPP
 3 
 4 #include <set>
 5 #include <unordered_map>
 6 
 7 #include <libp2p/basic/scheduler.hpp>
 8 #include <libp2p/network/connection_manager.hpp>
 9 #include <libp2p/network/dialer.hpp>
10 #include <libp2p/network/listener_manager.hpp>
11 #include <libp2p/network/transport_manager.hpp>
12 #include <libp2p/protocol_muxer/protocol_muxer.hpp>
13 
14 namespace libp2p::network {
15 
16   class DialerImpl : public Dialer,
17                      public std::enable_shared_from_this<DialerImpl> {
18    public:
19     ~DialerImpl() override = default;
20 
21     DialerImpl(std::shared_ptr<protocol_muxer::ProtocolMuxer> multiselect,
22                std::shared_ptr<TransportManager> tmgr,
23                std::shared_ptr<ConnectionManager> cmgr,
24                std::shared_ptr<ListenerManager> listener,
25                std::shared_ptr<basic::Scheduler> scheduler);
26 
27     // Establishes a connection to a given peer
28     void dial(const peer::PeerInfo &p, DialResultFunc cb,
29               std::chrono::milliseconds timeout) override;
30 
31     // NewStream returns a new stream to given peer p.
32     // If there is no connection to p, attempts to create one.
33     void newStream(const peer::PeerInfo &p, StreamProtocols protocols,
34                    StreamAndProtocolOrErrorCb cb,
35                    std::chrono::milliseconds timeout = {}) override;
36 
37     void newStream(const peer::PeerId &peer_id, StreamProtocols protocols,
38                    StreamAndProtocolOrErrorCb cb) override;
39 
40    private:
41     // A context to handle an intermediary state of the peer we are dialing to
42     // but the connection is not yet established
43     struct DialCtx {
44       /// Known and scheduled addresses to try to dial via
45       std::set<multi::Multiaddress> addresses;
46 
47       /// Timeout for a single connection attempt
48       std::chrono::milliseconds timeout;
49 
50       /// Addresses we already tried, but no connection was established
51       std::set<multi::Multiaddress> tried_addresses;
52 
53       /// Callbacks for all who requested a connection to the peer
54       std::vector<Dialer::DialResultFunc> callbacks;
55 
56       /// Result temporary storage to propagate via callbacks
57       boost::optional<DialResult> result;
58       // ^ used when all connecting attempts failed and no more known peer
59       // addresses are left
60 
61       // indicates that at least one attempt to dial was happened
62       // (at least one supported network transport was found and used)
63       bool dialled = false;
64     };
65 
66     // Perform a single attempt to dial to the peer via the next known address
67     void rotate(const peer::PeerId &peer_id);
68 
69     // Finalize dialing to the peer and propagate a given result to all
70     // connection requesters
71     void completeDial(const peer::PeerId &peer_id, const DialResult &result);
72 
73     void newStream(std::shared_ptr<connection::CapableConnection> conn,
74                    StreamProtocols protocols, StreamAndProtocolOrErrorCb cb);
75 
76     std::shared_ptr<protocol_muxer::ProtocolMuxer> multiselect_;
77     std::shared_ptr<TransportManager> tmgr_;
78     std::shared_ptr<ConnectionManager> cmgr_;
79     std::shared_ptr<ListenerManager> listener_;
80     std::shared_ptr<basic::Scheduler> scheduler_;
81     log::Logger log_;
82 
83     // peers we are currently dialing to
84     std::unordered_map<peer::PeerId, DialCtx> dialing_peers_;
85   };
86 
87 }  // namespace libp2p::network
88 
89 #endif  // LIBP2P_DIALER_IMPL_HPP

这段代码是DialerImpl类的定义,其中有3个函数:

  • 函数  `dial`: 尝试连接指定的对等节点,并在完成后调用回调函数cb,如果在超时时间内无法建立连接,则调用cb以报告错误。
  • 函数  `rotate` : 在连接尝试的地址列表中旋转,尝试使用下一个地址进行连接。如果所有地址都失败,则调用completeDial以报告错误。
  • 函数  `completeDial`: 根据结果调用之前注册的回调函数。如果结果是错误,则调用回调函数并报告错误。

该类是使用libp2p连接模块(stream.hpp)和日志模块(logger.hpp)构建的,并通过DialerImpl::dial尝试与对等节点建立连接。首先,检查是否已存在到该对等节点的连接。如果是,则使用现有连接,否则将尝试使用PeerInfo中提供的地址列表中的地址之一。如果所有地址都失败,则将调用completeDial以报告错误。rotate函数通过循环使用PeerInfo中的地址列表来完成连接,如果无法建立连接,则会尝试下一个地址。如果所有地址都失败,则会调用completeDial。

 1 #ifndef LIBP2P_INCLUDE_LIBP2P_NETWORK_IMPL_DNSADDR_RESOLVER_IMPL_HPP
 2 #define LIBP2P_INCLUDE_LIBP2P_NETWORK_IMPL_DNSADDR_RESOLVER_IMPL_HPP
 3 
 4 #include <libp2p/network/dnsaddr_resolver.hpp>
 5 
 6 #include <memory>
 7 #include <string>
 8 
 9 #include <boost/asio.hpp>
10 #include <libp2p/network/cares/cares.hpp>
11 
12 namespace libp2p::network {
13 
14   class DnsaddrResolverImpl : public DnsaddrResolver {
15    public:
16     static constexpr auto kDnsaddr = multi::Protocol::Code::DNS_ADDR;
17 
18     enum class Error {
19       INVALID_DNSADDR = 1,
20       MALFORMED_RESPONSE,
21       BAD_ADDR_IN_RESPONSE,
22     };
23 
24     DnsaddrResolverImpl(std::shared_ptr<boost::asio::io_context> io_context,
25                         const c_ares::Ares &cares);
26 
27     void load(multi::Multiaddress address, AddressesCallback callback) override;
28 
29    private:
30     /// Convert multiaddr "/dnsaddr/hostname" to string "_dnsaddr.hostname"
31     static outcome::result<std::string> dnsaddrUriFromMultiaddr(
32         const multi::Multiaddress &address);
33 
34     std::shared_ptr<boost::asio::io_context> io_context_;
35     // captured by reference intentionally to force DI use the single instance
36     const c_ares::Ares &cares_;
37   };
38 
39 }  // namespace libp2p::network
40 
41 OUTCOME_HPP_DECLARE_ERROR(libp2p::network, DnsaddrResolverImpl::Error);
42 
43 #endif  // LIBP2P_INCLUDE_LIBP2P_NETWORK_IMPL_DNSADDR_RESOLVER_IMPL_HPP

这是个文件包含了用于 DNS 解析的类和函数。其中,该文件中的函数 `load`  通过将多地址解析为 DNS 地址,然后向 DNS 服务器查询相应的 TXT 记录,并将记录解析成多地址,最终返回给回调函数,其中如果出现错误会返回错误码。类 DnsaddrResolverImpl 的实例化需要传入一个 boost::asio::io_context 对象和一个 c_ares::Ares 对象,类中包含了对 DNS 地址进行解析和处理的函数和常量。

  • OUTCOME_CPP_DEFINE_CATEGORY:这是一个宏定义,用于定义一个带有 Error 类型的错误码,并提供了对该错误码的解释信息。在此宏定义中,libp2p::network 是命名空间,DnsaddrResolverImpl::Error 是枚举类型名称,e 是枚举类型的变量名。其中,枚举类型中包含了多个错误码,通过 switch 语句来返回对应错误的解释信息。
  • DnsaddrResolverImpl:DnsaddrResolverImpl 的构造函数,接受一个 boost::asio::io_context 对象和一个 c_ares::Ares 对象作为参数。在函数体中,将这两个对象分别保存到成员变量 io_context_cares_ 中。
  • load:DnsaddrResolverImpl 中的一个函数,用于将一个多地址解析为 DNS 地址,并向 DNS 服务器查询相应的 TXT 记录,并将记录解析成多地址,最终返回给回调函数。函数接受两个参数,第一个参数是一个 multi::Multiaddress 对象,第二个参数是一个回调函数。函数体中,首先将多地址解析为 DNS 地址,如果出现错误,则直接调用回调函数并将错误码传入;否则,调用成员函数 cares_.resolveTxt 来解析 TXT 记录,并将记录解析成多地址,最终将多地址返回给回调函数。在函数中,也会对一些解析过程中可能出现的错误进行处理。
  • dnsaddrUriFromMultiaddr:DnsaddrResolverImpl 中的一个函数,用于将一个多地址解析为 DNS 地址。函数接受一个 multi::Multiaddress 对象作为参数,返回一个 outcome::result<std::string> 类型的值。如果多地址不是一个有效的 DNS 地址,函数会返回一个对应的错误码;否则,函数会将多地址解析为 DNS 地址,并在前面加上 _dnsaddr. 前缀,最终返回该地址。在函数中,也会对一些解析过程中可能出现的错误进行处理。
posted @ 2023-02-13 17:05  Akephalos  阅读(286)  评论(0)    收藏  举报