从Host类到Session类
上一节我们跟踪到了Host::startPeerSession()
函数里,现在我们来深入这个函数看个究竟。
1 | void Host::startPeerSession(Public const& _id, RLP const& _rlp, unique_ptr<RLPXFrameCoder>&& _io, std::shared_ptr<RLPXSocket> const& _s) |
可以看到这个函数里先是创建了一个Session
类,然后对m_capabilities
的成员调用newPeerCapability()
来为每一个session
创建一个capability
,也就是消息处理器,最后调用session
类的start()
函数。
看到这里可能读者会一头雾水,不知道这里是做了什么处理,不用急,我们还是先从m_capabilities
谈起。m_capabilities
定义在Host
类中:
1 | std::map<CapDesc, std::shared_ptr<HostCapabilityFace>> m_capabilities; |
CapDesc定义为:
1 | using CapDesc = std::pair<std::string, u256>; |
HostCapabilityFace
是一个虚基类,最重要的成员有两个:
1 | class HostCapabilityFace |
这两个函数正是在Host::startPeerSession()
函数中被调用的那两个!
目前我们还不清楚这两个函数的具体功能,我们需要去找HostCapabilityFace
类的子类,看看它们的实现。
为了找子类,我们需要找m_capabilities
在哪里插入数据,发现是在Host::registerCapability()
函数中
1 | void Host::registerCapability(std::shared_ptr<HostCapabilityFace> const& _cap) |
再找Host::registerCapability()
在哪里被调用,找到libethereum\client.cpp
里的Client::init()
,里面有一段代码:
1 | auto ethHostCapability = |
_extNet
就是Host
对象,原来HostCapabilityFace
类的子类是EthereumHost
类。EthereumHost
类也是一个非常重要的类,我们后面再谈,这个类的定义有点意思,我们先来看看:
1 | class EthereumHost: public p2p::HostCapability<EthereumPeer>, Worker |
可以看到这个类除了从Worker
类继承外,还继承了 p2p::HostCapability<EthereumPeer>
类。一下子又引入了两个新类。
一个一个来,我们先来看看 p2p::HostCapability
类定义:
1 | template<class PeerCap> |
原来HostCapability<>
类才是HostCapabilityFace
类的直接子类,EthereumHost
类是HostCapabilityFace
类的孙子类。messageCount()
和newPeerCapability()
这两个函数在HostCapability<>
类里有一份实现。而且这个类是一个模板类,messageCount()
只是调用了模板参数PeerCap
的messageCount()
函数。newPeerCapability()
函数只是创建一个PeerCap
对象,并调用其registerCapability()
函数。
对于EthereumHost
类,模板参数PeerCap
就是EthereumPeer
,这点可以从EthereumHost
类定义中得到,因此在EthereumHost
类里,这两个函数相当于:
1 | unsigned EthereumHost::messageCount() const override { return EthereumPeer::messageCount(); } |
先来看newPeerCapability
这个函数吧,它创建了一个EthereumPeer
类对象,并调用SessionFace::registerCapability()
注册了该对象,也就是把EthereumPeer
类对象放到了Session
类对象里,EthereumPeer
类是Session
消息处理器。
实际上EthereumHost
类自身对newPeerCapability()
函数也有自己的实现,这个实现与父类HostCapability<>
的实现稍有不同,这个后面再谈。messageCount()
函数简单返回了一个消息数量,这个用来将不同的HostCapabilityFace
的消息错开,方便消息分发,每个HostCapabilityFace
处理某一段范围内的消息。