以太坊(ethereum)实现研究

ethereum p2p Kademlia的实现之八

2018-05-02  本文已影响15人  古则

之前已经分析了ethereum的tcp通信的调用过程
现在来看tcp通信的底层编码

1.建立连接时的握手过程

握手完成是建立连接的前提,先看握手过程调用的入口

//p2p/server.go
func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *discover.Node) error {
    // Prevent leftover pending conns from entering the handshake.
    srv.lock.Lock()
    running := srv.running
    srv.lock.Unlock()
    if !running {
        return errServerStopped
    }
    // Run the encryption handshake.
    var err error
    //debug.PrintStack()
    //fmt.Println("setupConn diadest:", dialDest)
    if c.id, err = c.doEncHandshake(srv.PrivateKey, dialDest); err != nil {
        srv.log.Trace("Failed RLPx handshake", "addr", c.fd.RemoteAddr(), "conn", c.flags, "err", err)
        //fmt.Println("Failed RLPx handshake", c.fd.RemoteAddr(), err)
        return err
    }
    clog := srv.log.New("id", c.id, "addr", c.fd.RemoteAddr(), "conn", c.flags)
    // For dialed connections, check that the remote public key matches.
    if dialDest != nil && c.id != dialDest.ID {
        clog.Trace("Dialed identity mismatch", "want", c, dialDest.ID)
        //fmt.Println("setupConn 1", err)
        return DiscUnexpectedIdentity
    }

    err = srv.checkpoint(c, srv.posthandshake)
    if err != nil {
        clog.Trace("Rejected peer before protocol handshake", "err", err)
        //fmt.Println("setupConn 2", err)
        return err
    }
    // Run the protocol handshake
    phs, err := c.doProtoHandshake(srv.ourHandshake)
    if err != nil {
        clog.Trace("Failed proto handshake", "err", err)
        //fmt.Println("setupConn ee 3", err)
        return err
    }
    if phs.ID != c.id {
        clog.Trace("Wrong devp2p handshake identity", "err", phs.ID)
        //fmt.Println("setupConn 4", err)
        return DiscUnexpectedIdentity
    }
    c.caps, c.name = phs.Caps, phs.Name
    err = srv.checkpoint(c, srv.addpeer)
    if err != nil {
        clog.Trace("Rejected peer", "err", err)
        //fmt.Println("setupConn 5", err)
        return err
    }
    // If the checks completed successfully, runPeer has now been
    // launched by run.
    clog.Trace("connection set up", "inbound", dialDest == nil)
    return nil
}

先看doEncHandshake方法

func (t *rlpx) doEncHandshake(prv *ecdsa.PrivateKey, dial *discover.Node) (discover.NodeID, error) {
    var (
        sec secrets
        err error
    )
######
如果是tcp服务端,接受tcp连接时
######
    if dial == nil {
        sec, err = receiverEncHandshake(t.fd, prv, nil)
    } else {
######
如果是tcp客户端,主动进行连接
######
        sec, err = initiatorEncHandshake(t.fd, prv, dial.ID, nil)
    }

    if err != nil {
        //fmt.Println("doEncHandshake err", err, dial)
        return discover.NodeID{}, err
    }
    t.wmu.Lock()
    t.rw = newRLPXFrameRW(t.fd, sec)
    t.wmu.Unlock()
    return sec.RemoteID, nil
}
上一篇下一篇

猜你喜欢

热点阅读