精通Filecoin:Filecoin 源码之 Hello 协议
Notify
方法,把自身作为被通知者注册到网络对象上。
h.Network().Notify((*helloNotify)(hello))
在这一步,通过调用 host
对象的 Network
方法,返回底层的 swarm 对象,然后把 hello
对象转化为 helloNotify
对象,最后调用 swarm 对象的 Notify
方法,从而当底层的 swarm 对象有任何事件发生时都会通知 helloNotify
对象(即 hello
对象)。
在 Hello 协议中我们只关心建立连接事件,所以 helloNotify
类型只实现了这个方法,其他方法都为空实现,具体如下:
type helloNotify Handler func (hn *helloNotify) hello() *Handler { return (*Handler)(hn) } const helloTimeout = time.Second * 10 func (hn *helloNotify) Connected(n net.Network, c net.Conn) { go func() { ctx, cancel := context.WithTimeout(context.Background(), helloTimeout) defer cancel() p := c.RemotePeer() if err := hn.hello().sayHello(ctx, p); err != nil { log.Warningf("failed to send hello handshake to peer %s: %s", p, err) } }() }
当节点作为客户端,拨号连接到远程对等节点时,底层的 swarm 对象会调用自身的 notifyAll
方法,通知所有的 Notify 对象有连接被打开,即调用所有 Notify 对象的 Connected
方法,包括前面我们注册的通知对象。当调用 helloNotify
对象的 Connected
方法时,这个方法内部调用自身的 hello
方法,后者返回自身并强制转化为 Handler
类型,然后调用它的 sayHello
方法,对我们当前连接的远程进行打招呼。
与此同时,当远程节点作为服务器,接收到我们发送的连接请求生成连接时,它的 swarm 对象也会通知它的所有 Notify 对象,从而也会它的前面注册的通知对象,即调用服务器商的 Connected
方法,从而调用它的 sayHello
方法向我们发送它的区块情况;因为第二步中,我们把 Hello 对象的 handleNewStream
方法注册为 Hello 协议的处理器,所以当节点接收到远程节点发送区块情况时,就会调用这个方法进行处理,这个方法又会调用调用全节点的 syncCallBack
方法进行区块同步处理。