NatPunchModule.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #if DEBUG && !UNITY_WP_8_1 && !UNITY_WSA_8_1
  2. using System;
  3. using System.Collections.Generic;
  4. using FlyingWormConsole3.LiteNetLib.Utils;
  5. //Some code parts taked from lidgren-network-gen3
  6. namespace FlyingWormConsole3.LiteNetLib
  7. {
  8. public interface INatPunchListener
  9. {
  10. void OnNatIntroductionRequest(NetEndPoint localEndPoint, NetEndPoint remoteEndPoint, string token);
  11. void OnNatIntroductionSuccess(NetEndPoint targetEndPoint, string token);
  12. }
  13. public class EventBasedNatPunchListener : INatPunchListener
  14. {
  15. public delegate void OnNatIntroductionRequest(NetEndPoint localEndPoint, NetEndPoint remoteEndPoint, string token);
  16. public delegate void OnNatIntroductionSuccess(NetEndPoint targetEndPoint, string token);
  17. public event OnNatIntroductionRequest NatIntroductionRequest;
  18. public event OnNatIntroductionSuccess NatIntroductionSuccess;
  19. void INatPunchListener.OnNatIntroductionRequest(NetEndPoint localEndPoint, NetEndPoint remoteEndPoint, string token)
  20. {
  21. if(NatIntroductionRequest != null)
  22. NatIntroductionRequest(localEndPoint, remoteEndPoint, token);
  23. }
  24. void INatPunchListener.OnNatIntroductionSuccess(NetEndPoint targetEndPoint, string token)
  25. {
  26. if (NatIntroductionSuccess != null)
  27. NatIntroductionSuccess(targetEndPoint, token);
  28. }
  29. }
  30. public sealed class NatPunchModule
  31. {
  32. struct RequestEventData
  33. {
  34. public NetEndPoint LocalEndPoint;
  35. public NetEndPoint RemoteEndPoint;
  36. public string Token;
  37. }
  38. struct SuccessEventData
  39. {
  40. public NetEndPoint TargetEndPoint;
  41. public string Token;
  42. }
  43. private readonly NetManager _netBase;
  44. private readonly Queue<RequestEventData> _requestEvents;
  45. private readonly Queue<SuccessEventData> _successEvents;
  46. private const byte HostByte = 1;
  47. private const byte ClientByte = 0;
  48. public const int MaxTokenLength = 256;
  49. private INatPunchListener _natPunchListener;
  50. internal NatPunchModule(NetManager netBase)
  51. {
  52. _netBase = netBase;
  53. _requestEvents = new Queue<RequestEventData>();
  54. _successEvents = new Queue<SuccessEventData>();
  55. }
  56. public void Init(INatPunchListener listener)
  57. {
  58. _natPunchListener = listener;
  59. }
  60. public void NatIntroduce(
  61. NetEndPoint hostInternal,
  62. NetEndPoint hostExternal,
  63. NetEndPoint clientInternal,
  64. NetEndPoint clientExternal,
  65. string additionalInfo)
  66. {
  67. NetDataWriter dw = new NetDataWriter();
  68. //First packet (server)
  69. //send to client
  70. dw.Put(ClientByte);
  71. dw.Put(hostInternal);
  72. dw.Put(hostExternal);
  73. dw.Put(additionalInfo, MaxTokenLength);
  74. var packet = _netBase.PacketPool.GetWithData(PacketProperty.NatIntroduction, dw);
  75. _netBase.SendRawAndRecycle(packet, clientExternal);
  76. //Second packet (client)
  77. //send to server
  78. dw.Reset();
  79. dw.Put(HostByte);
  80. dw.Put(clientInternal);
  81. dw.Put(clientExternal);
  82. dw.Put(additionalInfo, MaxTokenLength);
  83. packet = _netBase.PacketPool.GetWithData(PacketProperty.NatIntroduction, dw);
  84. _netBase.SendRawAndRecycle(packet, hostExternal);
  85. }
  86. public void PollEvents()
  87. {
  88. if (_natPunchListener == null)
  89. return;
  90. lock (_successEvents)
  91. {
  92. while (_successEvents.Count > 0)
  93. {
  94. var evt = _successEvents.Dequeue();
  95. _natPunchListener.OnNatIntroductionSuccess(evt.TargetEndPoint, evt.Token);
  96. }
  97. }
  98. lock (_requestEvents)
  99. {
  100. while (_requestEvents.Count > 0)
  101. {
  102. var evt = _requestEvents.Dequeue();
  103. _natPunchListener.OnNatIntroductionRequest(evt.LocalEndPoint, evt.RemoteEndPoint, evt.Token);
  104. }
  105. }
  106. }
  107. public void SendNatIntroduceRequest(NetEndPoint masterServerEndPoint, string additionalInfo)
  108. {
  109. if (!_netBase.IsRunning)
  110. return;
  111. //prepare outgoing data
  112. NetDataWriter dw = new NetDataWriter();
  113. string networkIp = NetUtils.GetLocalIp(LocalAddrType.IPv4);
  114. if (string.IsNullOrEmpty(networkIp))
  115. {
  116. networkIp = NetUtils.GetLocalIp(LocalAddrType.IPv6);
  117. }
  118. int networkPort = _netBase.LocalEndPoint.Port;
  119. NetEndPoint localEndPoint = new NetEndPoint(networkIp, networkPort);
  120. dw.Put(localEndPoint);
  121. dw.Put(additionalInfo, MaxTokenLength);
  122. //prepare packet
  123. var packet = _netBase.PacketPool.GetWithData(PacketProperty.NatIntroductionRequest, dw);
  124. _netBase.SendRawAndRecycle(packet, masterServerEndPoint);
  125. }
  126. private void HandleNatPunch(NetEndPoint senderEndPoint, NetDataReader dr)
  127. {
  128. byte fromHostByte = dr.GetByte();
  129. if (fromHostByte != HostByte && fromHostByte != ClientByte)
  130. {
  131. //garbage
  132. return;
  133. }
  134. //Read info
  135. string additionalInfo = dr.GetString(MaxTokenLength);
  136. NetUtils.DebugWrite(ConsoleColor.Green, "[NAT] punch received from {0} - additional info: {1}", senderEndPoint, additionalInfo);
  137. //Release punch success to client; enabling him to Connect() to msg.Sender if token is ok
  138. lock (_successEvents)
  139. {
  140. _successEvents.Enqueue(new SuccessEventData { TargetEndPoint = senderEndPoint, Token = additionalInfo });
  141. }
  142. }
  143. private void HandleNatIntroduction(NetDataReader dr)
  144. {
  145. // read intro
  146. byte hostByte = dr.GetByte();
  147. NetEndPoint remoteInternal = dr.GetNetEndPoint();
  148. NetEndPoint remoteExternal = dr.GetNetEndPoint();
  149. string token = dr.GetString(MaxTokenLength);
  150. NetUtils.DebugWrite(ConsoleColor.Cyan, "[NAT] introduction received; we are designated " + (hostByte == HostByte ? "host" : "client"));
  151. NetDataWriter writer = new NetDataWriter();
  152. // send internal punch
  153. writer.Put(hostByte);
  154. writer.Put(token);
  155. var packet = _netBase.PacketPool.GetWithData(PacketProperty.NatPunchMessage, writer);
  156. _netBase.SendRawAndRecycle(packet, remoteInternal);
  157. NetUtils.DebugWrite(ConsoleColor.Cyan, "[NAT] internal punch sent to " + remoteInternal);
  158. // send external punch
  159. writer.Reset();
  160. writer.Put(hostByte);
  161. writer.Put(token);
  162. packet = _netBase.PacketPool.GetWithData(PacketProperty.NatPunchMessage, writer);
  163. _netBase.SendRawAndRecycle(packet, remoteExternal);
  164. NetUtils.DebugWrite(ConsoleColor.Cyan, "[NAT] external punch sent to " + remoteExternal);
  165. }
  166. private void HandleNatIntroductionRequest(NetEndPoint senderEndPoint, NetDataReader dr)
  167. {
  168. NetEndPoint localEp = dr.GetNetEndPoint();
  169. string token = dr.GetString(MaxTokenLength);
  170. lock (_requestEvents)
  171. {
  172. _requestEvents.Enqueue(new RequestEventData
  173. {
  174. LocalEndPoint = localEp,
  175. RemoteEndPoint = senderEndPoint,
  176. Token = token
  177. });
  178. }
  179. }
  180. internal void ProcessMessage(NetEndPoint senderEndPoint, NetPacket packet)
  181. {
  182. var dr = new NetDataReader(packet.RawData, NetConstants.HeaderSize, packet.Size);
  183. switch (packet.Property)
  184. {
  185. case PacketProperty.NatIntroductionRequest:
  186. //We got request and must introduce
  187. HandleNatIntroductionRequest(senderEndPoint, dr);
  188. break;
  189. case PacketProperty.NatIntroduction:
  190. //We got introduce and must punch
  191. HandleNatIntroduction(dr);
  192. break;
  193. case PacketProperty.NatPunchMessage:
  194. //We got punch and can connect
  195. HandleNatPunch(senderEndPoint, dr);
  196. break;
  197. }
  198. }
  199. }
  200. }
  201. #endif