P2P網絡資料處理流程
監聽(ListenLoop)+撥号(Dial) –> 建立連接配接(SetupConn) –> Enc 握手(doEncHandshake) –> 協定握手(doProtoHandshake) –> 添加Peer Addpeer –> Run Peer
1. Enc握手 doEncHandshake
監聽時接收到Enc握手:receiverEncHandshake
撥号時發起初始End握手:initiatorEncHandshake
連結的發起者被稱為initiator(主動撥号),連結的被動接受者被成為receiver(被動監聽)。 這兩種模式下處理的流程是不同的,完成握手後, 生成了一個sec可以了解為拿到了對稱加密的密鑰。 然後建立了一個newRLPXFrameRW幀讀寫器,完成加密信道的建立過程。
initiatorEncHandshake 和receiverEncHandshake有些像,但邏輯處理是相反的過程。
makeAuthMsg
makeAuthMsg這個方法建立了handshake message。 首先對端的公鑰可以通過對端的ID來擷取。對端的公鑰對于發起者來說是知道的;對于接收者來說是不知道的。
- 根據對端的ID計算出對端公鑰remotePub
- 生成一個随機的初始值initNonce
- 生成一個随機的私鑰
- 使用自己的私鑰和對方的公鑰生成的一個共享秘密
- 用共享秘密來加密這個initNonce
- 這裡把發起者的公鑰告知對方
這一步,主要是建構authMsgV4結構體。
sealEIP8
sealEIP8對msg進行rlp的編碼,填充一下資料,然後使用對方的公鑰把資料進行加密。
readHandshakeMsg
readHandshakeMsg有兩個地方調用: 一個是在initiatorEncHandshake,另外一個就是在receiverEncHandshake。 這個方法比較簡單, 首先用一種格式嘗試解碼,如果不行就換另外一種。基本上就是使用自己的私鑰進行解碼然後調用rlp解碼成結構體。 結構體的描述就是authRespV4,裡面最重要的就是對端的随機公鑰。 雙方通過自己的私鑰和對端的随機公鑰可以得到一樣的共享秘密。 而這個共享秘密是第三方拿不到的。
secrets
secrets函數是在handshake完成之後調用。它通過自己的随機私鑰和對端的公鑰來生成一個共享秘密,這個共享秘密是瞬時的(隻在目前這個連結中存在)。
這個函數計算出IngressMAC和EgressMAC用于rlpxFrameRW中ReadMsg,WriteMsg資料的接收發送。
資料幀結構
| |
2. 協定握手doProtoHandshake
這個方法比較簡單,加密信道已經建立完畢。 我們看到這裡隻是約定了是否使用Snappy加密然後就退出了。
在這個函數,發送給對方 handshakeMsg = 0x00,在readProtocolHandshake中讀取接收對方發過來的handshakeMsg。
3. RLPX 資料分幀
在完成Encode握手之後,調用newRLPXFrameRW方法建立rlpxFrameRW對象,這的對象提供ReadMsg和WriteMsg方法
ReadMsg
)
1讀取幀頭header
2 驗證幀頭MAC
3 擷取幀體Frame大小
4 讀取幀體資料
5 驗證幀體MAC資訊
6 解密幀體内容(NewCTR à XORKeyStream)
7 解碼幀體(RLP Decode)
8 解析幀體結構(msg.Size & msg.Payload)
9 snappy解碼
WriteMsg
1 RLP編碼msg.Code
2 如果snappy,就對讀取payload并進行snappy編碼
3 寫幀頭header (32位元組)
4 寫幀頭MAC
5 寫幀體資訊(ptype+payload+padding)
6 寫幀體MAC
4. runPeer
newPeerHook,建立peer的鈎子函數
廣播PeerEventTypeAdd事件
運作protocol
廣播PeerEventTypeDrop事件
删除peer
run protocol
1 啟動協程readLoop,讀取消息并根據msg.Code處理消息:
pingMsg->pongMsg
discMsg->RLP解碼msg.Payload傳回reason
其他協定消息處理,根據msg.Code的取值範圍,把msg分給注冊的協定進行處理。
2 啟動協程pingLoop
根據pingInterval(15秒)定時發送pingMsg消息
3 啟動協定
startProtocols主要功能是啟動協程運作注冊協定的run函數proto.Run(p, rw),這個rw參數類型是protoRW,它實作的ReadMsg和WriteMsg增加msg.Code取值範圍的處理。不同的protocol有不同的code取值範圍,根據offset和Length确定。
原文連結:http://wangxiaoming.com/blog/2018/06/28/HPB-48-ETH-P2P-Net/