收到 P2PPurchHolePacket,設定 P2P 位址、嘗試 UPnP 埠映射、回覆 P2PPurchHoleAckPacket:
private void ProcP2PPurchHoleMsg(Packet packet, IPEndPoint remoteEP) {
P2PPurchHolePacket purchReqMsg = (P2PPurchHolePacket)packet;
PeerEntity toUser = userList.Single(c => c.UserName == purchReqMsg.ToUserName);
PeerEntity user = userList.Single(c => c.UserName == purchReqMsg.UserName);
toUser.P2PAddress = toUser.RemoteEndPoint;
printf("Set P2P Address for {0}->[{1}]", user.UserName, toUser.P2PAddress);
if (NAT.AddPortMapping(toUser.P2PAddress.Port, ProtocolType.Udp, "AddPortMapping"))
printf("Port mapping successed!");
P2PPurchHoleAckPacket trashMsg = new P2PPurchHoleAckPacket(purchReqMsg.UserName, purchReqMsg.ToUserName);
byte[] buffer = UtilityHelper.Serialize(trashMsg);
client.Send(buffer, buffer.Length, user.RemoteEndPoint);
}
持續 Receive、反序列化、依 Command 分派:
private void RecvThreadProc() {
IPEndPoint remotePoint = null;
byte[] msgBuffer = null;
while (true) {
msgBuffer = server.Receive(ref remotePoint);
try {
object msgObj = UtilityHelper.Deserialize(msgBuffer);
switch ((msgObj as Packet).GetCommandType()) {
case Command.MSG_USERLOGIN: ProcUserLoginMsg(...); break;
case Command.MSG_USERLOGOUT: ProcUserLogoutMsg(...); break;
case Command.MSG_GETUSERLIST: ProcGetUserListMsg(...); break;
case Command.MSG_P2PCONNECT: ProcP2PConnectMsg(...); break;
case Command.MSG_USERACTIVEQUERY: ProcUserActiveQueryMsg(...); break;
}
Thread.Sleep(100);
} catch { }
}
}