UDPProxyClient.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "NativeFeatureIncludes.h"
  11. #if _RAKNET_SUPPORT_UDPProxyClient==1
  12. #include "UDPProxyClient.h"
  13. #include "BitStream.h"
  14. #include "UDPProxyCommon.h"
  15. #include "RakPeerInterface.h"
  16. #include "MessageIdentifiers.h"
  17. #include "GetTime.h"
  18. using namespace RakNet;
  19. static const int DEFAULT_UNRESPONSIVE_PING_TIME_COORDINATOR=1000;
  20. // bool operator<( const DataStructures::MLKeyRef<UDPProxyClient::ServerWithPing> &inputKey, const UDPProxyClient::ServerWithPing &cls ) {return inputKey.Get().serverAddress < cls.serverAddress;}
  21. // bool operator>( const DataStructures::MLKeyRef<UDPProxyClient::ServerWithPing> &inputKey, const UDPProxyClient::ServerWithPing &cls ) {return inputKey.Get().serverAddress > cls.serverAddress;}
  22. // bool operator==( const DataStructures::MLKeyRef<UDPProxyClient::ServerWithPing> &inputKey, const UDPProxyClient::ServerWithPing &cls ) {return inputKey.Get().serverAddress == cls.serverAddress;}
  23. STATIC_FACTORY_DEFINITIONS(UDPProxyClient,UDPProxyClient);
  24. UDPProxyClient::UDPProxyClient()
  25. {
  26. resultHandler=0;
  27. }
  28. UDPProxyClient::~UDPProxyClient()
  29. {
  30. Clear();
  31. }
  32. void UDPProxyClient::SetResultHandler(UDPProxyClientResultHandler *rh)
  33. {
  34. resultHandler=rh;
  35. }
  36. bool UDPProxyClient::RequestForwarding(SystemAddress proxyCoordinator, SystemAddress sourceAddress, RakNetGUID targetGuid, RakNet::TimeMS timeoutOnNoDataMS, RakNet::BitStream *serverSelectionBitstream)
  37. {
  38. // Return false if not connected
  39. ConnectionState cs = rakPeerInterface->GetConnectionState(proxyCoordinator);
  40. if (cs!=IS_CONNECTED)
  41. return false;
  42. // Pretty much a bug not to set the result handler, as otherwise you won't know if the operation succeeed or not
  43. RakAssert(resultHandler!=0);
  44. if (resultHandler==0)
  45. return false;
  46. BitStream outgoingBs;
  47. outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
  48. outgoingBs.Write((MessageID)ID_UDP_PROXY_FORWARDING_REQUEST_FROM_CLIENT_TO_COORDINATOR);
  49. outgoingBs.Write(sourceAddress);
  50. outgoingBs.Write(false);
  51. outgoingBs.Write(targetGuid);
  52. outgoingBs.Write(timeoutOnNoDataMS);
  53. if (serverSelectionBitstream && serverSelectionBitstream->GetNumberOfBitsUsed()>0)
  54. {
  55. outgoingBs.Write(true);
  56. outgoingBs.Write(serverSelectionBitstream);
  57. }
  58. else
  59. {
  60. outgoingBs.Write(false);
  61. }
  62. rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, proxyCoordinator, false);
  63. return true;
  64. }
  65. bool UDPProxyClient::RequestForwarding(SystemAddress proxyCoordinator, SystemAddress sourceAddress, SystemAddress targetAddressAsSeenFromCoordinator, RakNet::TimeMS timeoutOnNoDataMS, RakNet::BitStream *serverSelectionBitstream)
  66. {
  67. // Return false if not connected
  68. ConnectionState cs = rakPeerInterface->GetConnectionState(proxyCoordinator);
  69. if (cs!=IS_CONNECTED)
  70. return false;
  71. // Pretty much a bug not to set the result handler, as otherwise you won't know if the operation succeeed or not
  72. RakAssert(resultHandler!=0);
  73. if (resultHandler==0)
  74. return false;
  75. BitStream outgoingBs;
  76. outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
  77. outgoingBs.Write((MessageID)ID_UDP_PROXY_FORWARDING_REQUEST_FROM_CLIENT_TO_COORDINATOR);
  78. outgoingBs.Write(sourceAddress);
  79. outgoingBs.Write(true);
  80. outgoingBs.Write(targetAddressAsSeenFromCoordinator);
  81. outgoingBs.Write(timeoutOnNoDataMS);
  82. if (serverSelectionBitstream && serverSelectionBitstream->GetNumberOfBitsUsed()>0)
  83. {
  84. outgoingBs.Write(true);
  85. outgoingBs.Write(serverSelectionBitstream);
  86. }
  87. else
  88. {
  89. outgoingBs.Write(false);
  90. }
  91. rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, proxyCoordinator, false);
  92. return true;
  93. }
  94. void UDPProxyClient::Update(void)
  95. {
  96. unsigned int idx1=0;
  97. while (idx1 < pingServerGroups.Size())
  98. {
  99. PingServerGroup *psg = pingServerGroups[idx1];
  100. if (psg->serversToPing.Size() > 0 &&
  101. RakNet::GetTimeMS() > psg->startPingTime+DEFAULT_UNRESPONSIVE_PING_TIME_COORDINATOR)
  102. {
  103. // If they didn't reply within DEFAULT_UNRESPONSIVE_PING_TIME_COORDINATOR, just give up on them
  104. psg->SendPingedServersToCoordinator(rakPeerInterface);
  105. RakNet::OP_DELETE(psg,_FILE_AND_LINE_);
  106. pingServerGroups.RemoveAtIndex(idx1);
  107. }
  108. else
  109. idx1++;
  110. }
  111. }
  112. PluginReceiveResult UDPProxyClient::OnReceive(Packet *packet)
  113. {
  114. if (packet->data[0]==ID_UNCONNECTED_PONG)
  115. {
  116. unsigned int idx1, idx2;
  117. PingServerGroup *psg;
  118. for (idx1=0; idx1 < pingServerGroups.Size(); idx1++)
  119. {
  120. psg = pingServerGroups[idx1];
  121. for (idx2=0; idx2 < psg->serversToPing.Size(); idx2++)
  122. {
  123. if (psg->serversToPing[idx2].serverAddress==packet->systemAddress)
  124. {
  125. RakNet::BitStream bsIn(packet->data,packet->length,false);
  126. bsIn.IgnoreBytes(sizeof(MessageID));
  127. RakNet::TimeMS sentTime;
  128. bsIn.Read(sentTime);
  129. RakNet::TimeMS curTime=RakNet::GetTimeMS();
  130. int ping;
  131. if (curTime>sentTime)
  132. ping=(int) (curTime-sentTime);
  133. else
  134. ping=0;
  135. psg->serversToPing[idx2].ping=(unsigned short) ping;
  136. // If all servers to ping are now pinged, reply to coordinator
  137. if (psg->AreAllServersPinged())
  138. {
  139. psg->SendPingedServersToCoordinator(rakPeerInterface);
  140. RakNet::OP_DELETE(psg,_FILE_AND_LINE_);
  141. pingServerGroups.RemoveAtIndex(idx1);
  142. }
  143. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  144. }
  145. }
  146. }
  147. }
  148. else if (packet->data[0]==ID_UDP_PROXY_GENERAL && packet->length>1)
  149. {
  150. switch (packet->data[1])
  151. {
  152. case ID_UDP_PROXY_PING_SERVERS_FROM_COORDINATOR_TO_CLIENT:
  153. {
  154. OnPingServers(packet);
  155. }
  156. break;
  157. case ID_UDP_PROXY_FORWARDING_SUCCEEDED:
  158. case ID_UDP_PROXY_ALL_SERVERS_BUSY:
  159. case ID_UDP_PROXY_IN_PROGRESS:
  160. case ID_UDP_PROXY_NO_SERVERS_ONLINE:
  161. case ID_UDP_PROXY_RECIPIENT_GUID_NOT_CONNECTED_TO_COORDINATOR:
  162. case ID_UDP_PROXY_FORWARDING_NOTIFICATION:
  163. {
  164. RakNetGUID targetGuid;
  165. SystemAddress senderAddress, targetAddress;
  166. RakNet::BitStream incomingBs(packet->data, packet->length, false);
  167. incomingBs.IgnoreBytes(sizeof(MessageID)*2);
  168. incomingBs.Read(senderAddress);
  169. incomingBs.Read(targetAddress);
  170. incomingBs.Read(targetGuid);
  171. switch (packet->data[1])
  172. {
  173. case ID_UDP_PROXY_FORWARDING_NOTIFICATION:
  174. case ID_UDP_PROXY_FORWARDING_SUCCEEDED:
  175. case ID_UDP_PROXY_IN_PROGRESS:
  176. {
  177. unsigned short forwardingPort;
  178. RakNet::RakString serverIP;
  179. incomingBs.Read(serverIP);
  180. incomingBs.Read(forwardingPort);
  181. if (packet->data[1]==ID_UDP_PROXY_FORWARDING_SUCCEEDED)
  182. {
  183. if (resultHandler)
  184. resultHandler->OnForwardingSuccess(serverIP.C_String(), forwardingPort, packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
  185. }
  186. else if (packet->data[1]==ID_UDP_PROXY_IN_PROGRESS)
  187. {
  188. if (resultHandler)
  189. resultHandler->OnForwardingInProgress(serverIP.C_String(), forwardingPort, packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
  190. }
  191. else
  192. {
  193. // Send a datagram to the proxy, so if we are behind a router, that router adds an entry to the routing table.
  194. // Otherwise the router would block the incoming datagrams from source
  195. // It doesn't matter if the message actually arrives as long as it goes through the router
  196. rakPeerInterface->Ping(serverIP.C_String(), forwardingPort, false);
  197. if (resultHandler)
  198. resultHandler->OnForwardingNotification(serverIP.C_String(), forwardingPort, packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
  199. }
  200. }
  201. break;
  202. case ID_UDP_PROXY_ALL_SERVERS_BUSY:
  203. if (resultHandler)
  204. resultHandler->OnAllServersBusy(packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
  205. break;
  206. case ID_UDP_PROXY_NO_SERVERS_ONLINE:
  207. if (resultHandler)
  208. resultHandler->OnNoServersOnline(packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
  209. break;
  210. case ID_UDP_PROXY_RECIPIENT_GUID_NOT_CONNECTED_TO_COORDINATOR:
  211. {
  212. if (resultHandler)
  213. resultHandler->OnRecipientNotConnected(packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
  214. break;
  215. }
  216. }
  217. }
  218. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  219. }
  220. }
  221. return RR_CONTINUE_PROCESSING;
  222. }
  223. void UDPProxyClient::OnRakPeerShutdown(void)
  224. {
  225. Clear();
  226. }
  227. void UDPProxyClient::OnPingServers(Packet *packet)
  228. {
  229. RakNet::BitStream incomingBs(packet->data, packet->length, false);
  230. incomingBs.IgnoreBytes(2);
  231. PingServerGroup *psg = RakNet::OP_NEW<PingServerGroup>(_FILE_AND_LINE_);
  232. ServerWithPing swp;
  233. incomingBs.Read(psg->sata.senderClientAddress);
  234. incomingBs.Read(psg->sata.targetClientAddress);
  235. psg->startPingTime=RakNet::GetTimeMS();
  236. psg->coordinatorAddressForPings=packet->systemAddress;
  237. unsigned short serverListSize;
  238. incomingBs.Read(serverListSize);
  239. SystemAddress serverAddress;
  240. unsigned short serverListIndex;
  241. char ipStr[64];
  242. for (serverListIndex=0; serverListIndex<serverListSize; serverListIndex++)
  243. {
  244. incomingBs.Read(swp.serverAddress);
  245. swp.ping=DEFAULT_UNRESPONSIVE_PING_TIME_COORDINATOR;
  246. psg->serversToPing.Push(swp, _FILE_AND_LINE_ );
  247. swp.serverAddress.ToString(false,ipStr);
  248. rakPeerInterface->Ping(ipStr,swp.serverAddress.GetPort(),false,0);
  249. }
  250. pingServerGroups.Push(psg,_FILE_AND_LINE_);
  251. }
  252. bool UDPProxyClient::PingServerGroup::AreAllServersPinged(void) const
  253. {
  254. unsigned int serversToPingIndex;
  255. for (serversToPingIndex=0; serversToPingIndex < serversToPing.Size(); serversToPingIndex++)
  256. {
  257. if (serversToPing[serversToPingIndex].ping==DEFAULT_UNRESPONSIVE_PING_TIME_COORDINATOR)
  258. return false;
  259. }
  260. return true;
  261. }
  262. void UDPProxyClient::PingServerGroup::SendPingedServersToCoordinator(RakPeerInterface *rakPeerInterface)
  263. {
  264. BitStream outgoingBs;
  265. outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
  266. outgoingBs.Write((MessageID)ID_UDP_PROXY_PING_SERVERS_REPLY_FROM_CLIENT_TO_COORDINATOR);
  267. outgoingBs.Write(sata.senderClientAddress);
  268. outgoingBs.Write(sata.targetClientAddress);
  269. unsigned short serversToPingSize = (unsigned short) serversToPing.Size();
  270. outgoingBs.Write(serversToPingSize);
  271. unsigned int serversToPingIndex;
  272. for (serversToPingIndex=0; serversToPingIndex < serversToPingSize; serversToPingIndex++)
  273. {
  274. outgoingBs.Write(serversToPing[serversToPingIndex].serverAddress);
  275. outgoingBs.Write(serversToPing[serversToPingIndex].ping);
  276. }
  277. rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, coordinatorAddressForPings, false);
  278. }
  279. void UDPProxyClient::Clear(void)
  280. {
  281. for (unsigned int i=0; i < pingServerGroups.Size(); i++)
  282. RakNet::OP_DELETE(pingServerGroups[i],_FILE_AND_LINE_);
  283. pingServerGroups.Clear(false, _FILE_AND_LINE_);
  284. }
  285. #endif // _RAKNET_SUPPORT_*
粤ICP备19079148号