| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- #include "NativeFeatureIncludes.h"
- #if _RAKNET_SUPPORT_UDPProxyClient==1
- #include "UDPProxyClient.h"
- #include "BitStream.h"
- #include "UDPProxyCommon.h"
- #include "RakPeerInterface.h"
- #include "MessageIdentifiers.h"
- #include "GetTime.h"
- using namespace RakNet;
- static const int DEFAULT_UNRESPONSIVE_PING_TIME_COORDINATOR=1000;
- // bool operator<( const DataStructures::MLKeyRef<UDPProxyClient::ServerWithPing> &inputKey, const UDPProxyClient::ServerWithPing &cls ) {return inputKey.Get().serverAddress < cls.serverAddress;}
- // bool operator>( const DataStructures::MLKeyRef<UDPProxyClient::ServerWithPing> &inputKey, const UDPProxyClient::ServerWithPing &cls ) {return inputKey.Get().serverAddress > cls.serverAddress;}
- // bool operator==( const DataStructures::MLKeyRef<UDPProxyClient::ServerWithPing> &inputKey, const UDPProxyClient::ServerWithPing &cls ) {return inputKey.Get().serverAddress == cls.serverAddress;}
- STATIC_FACTORY_DEFINITIONS(UDPProxyClient,UDPProxyClient);
- UDPProxyClient::UDPProxyClient()
- {
- resultHandler=0;
- }
- UDPProxyClient::~UDPProxyClient()
- {
- Clear();
- }
- void UDPProxyClient::SetResultHandler(UDPProxyClientResultHandler *rh)
- {
- resultHandler=rh;
- }
- bool UDPProxyClient::RequestForwarding(SystemAddress proxyCoordinator, SystemAddress sourceAddress, RakNetGUID targetGuid, RakNet::TimeMS timeoutOnNoDataMS, RakNet::BitStream *serverSelectionBitstream)
- {
- // Return false if not connected
- ConnectionState cs = rakPeerInterface->GetConnectionState(proxyCoordinator);
- if (cs!=IS_CONNECTED)
- return false;
- // Pretty much a bug not to set the result handler, as otherwise you won't know if the operation succeeed or not
- RakAssert(resultHandler!=0);
- if (resultHandler==0)
- return false;
- BitStream outgoingBs;
- outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
- outgoingBs.Write((MessageID)ID_UDP_PROXY_FORWARDING_REQUEST_FROM_CLIENT_TO_COORDINATOR);
- outgoingBs.Write(sourceAddress);
- outgoingBs.Write(false);
- outgoingBs.Write(targetGuid);
- outgoingBs.Write(timeoutOnNoDataMS);
- if (serverSelectionBitstream && serverSelectionBitstream->GetNumberOfBitsUsed()>0)
- {
- outgoingBs.Write(true);
- outgoingBs.Write(serverSelectionBitstream);
- }
- else
- {
- outgoingBs.Write(false);
- }
- rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, proxyCoordinator, false);
- return true;
- }
- bool UDPProxyClient::RequestForwarding(SystemAddress proxyCoordinator, SystemAddress sourceAddress, SystemAddress targetAddressAsSeenFromCoordinator, RakNet::TimeMS timeoutOnNoDataMS, RakNet::BitStream *serverSelectionBitstream)
- {
- // Return false if not connected
- ConnectionState cs = rakPeerInterface->GetConnectionState(proxyCoordinator);
- if (cs!=IS_CONNECTED)
- return false;
- // Pretty much a bug not to set the result handler, as otherwise you won't know if the operation succeeed or not
- RakAssert(resultHandler!=0);
- if (resultHandler==0)
- return false;
- BitStream outgoingBs;
- outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
- outgoingBs.Write((MessageID)ID_UDP_PROXY_FORWARDING_REQUEST_FROM_CLIENT_TO_COORDINATOR);
- outgoingBs.Write(sourceAddress);
- outgoingBs.Write(true);
- outgoingBs.Write(targetAddressAsSeenFromCoordinator);
- outgoingBs.Write(timeoutOnNoDataMS);
- if (serverSelectionBitstream && serverSelectionBitstream->GetNumberOfBitsUsed()>0)
- {
- outgoingBs.Write(true);
- outgoingBs.Write(serverSelectionBitstream);
- }
- else
- {
- outgoingBs.Write(false);
- }
- rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, proxyCoordinator, false);
- return true;
- }
- void UDPProxyClient::Update(void)
- {
- unsigned int idx1=0;
- while (idx1 < pingServerGroups.Size())
- {
- PingServerGroup *psg = pingServerGroups[idx1];
- if (psg->serversToPing.Size() > 0 &&
- RakNet::GetTimeMS() > psg->startPingTime+DEFAULT_UNRESPONSIVE_PING_TIME_COORDINATOR)
- {
- // If they didn't reply within DEFAULT_UNRESPONSIVE_PING_TIME_COORDINATOR, just give up on them
- psg->SendPingedServersToCoordinator(rakPeerInterface);
- RakNet::OP_DELETE(psg,_FILE_AND_LINE_);
- pingServerGroups.RemoveAtIndex(idx1);
- }
- else
- idx1++;
- }
- }
- PluginReceiveResult UDPProxyClient::OnReceive(Packet *packet)
- {
- if (packet->data[0]==ID_UNCONNECTED_PONG)
- {
- unsigned int idx1, idx2;
- PingServerGroup *psg;
- for (idx1=0; idx1 < pingServerGroups.Size(); idx1++)
- {
- psg = pingServerGroups[idx1];
- for (idx2=0; idx2 < psg->serversToPing.Size(); idx2++)
- {
- if (psg->serversToPing[idx2].serverAddress==packet->systemAddress)
- {
- RakNet::BitStream bsIn(packet->data,packet->length,false);
- bsIn.IgnoreBytes(sizeof(MessageID));
- RakNet::TimeMS sentTime;
- bsIn.Read(sentTime);
- RakNet::TimeMS curTime=RakNet::GetTimeMS();
- int ping;
- if (curTime>sentTime)
- ping=(int) (curTime-sentTime);
- else
- ping=0;
- psg->serversToPing[idx2].ping=(unsigned short) ping;
- // If all servers to ping are now pinged, reply to coordinator
- if (psg->AreAllServersPinged())
- {
- psg->SendPingedServersToCoordinator(rakPeerInterface);
- RakNet::OP_DELETE(psg,_FILE_AND_LINE_);
- pingServerGroups.RemoveAtIndex(idx1);
- }
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- }
- }
- }
- else if (packet->data[0]==ID_UDP_PROXY_GENERAL && packet->length>1)
- {
- switch (packet->data[1])
- {
- case ID_UDP_PROXY_PING_SERVERS_FROM_COORDINATOR_TO_CLIENT:
- {
- OnPingServers(packet);
- }
- break;
- case ID_UDP_PROXY_FORWARDING_SUCCEEDED:
- case ID_UDP_PROXY_ALL_SERVERS_BUSY:
- case ID_UDP_PROXY_IN_PROGRESS:
- case ID_UDP_PROXY_NO_SERVERS_ONLINE:
- case ID_UDP_PROXY_RECIPIENT_GUID_NOT_CONNECTED_TO_COORDINATOR:
- case ID_UDP_PROXY_FORWARDING_NOTIFICATION:
- {
- RakNetGUID targetGuid;
- SystemAddress senderAddress, targetAddress;
- RakNet::BitStream incomingBs(packet->data, packet->length, false);
- incomingBs.IgnoreBytes(sizeof(MessageID)*2);
- incomingBs.Read(senderAddress);
- incomingBs.Read(targetAddress);
- incomingBs.Read(targetGuid);
- switch (packet->data[1])
- {
- case ID_UDP_PROXY_FORWARDING_NOTIFICATION:
- case ID_UDP_PROXY_FORWARDING_SUCCEEDED:
- case ID_UDP_PROXY_IN_PROGRESS:
- {
- unsigned short forwardingPort;
- RakNet::RakString serverIP;
- incomingBs.Read(serverIP);
- incomingBs.Read(forwardingPort);
- if (packet->data[1]==ID_UDP_PROXY_FORWARDING_SUCCEEDED)
- {
- if (resultHandler)
- resultHandler->OnForwardingSuccess(serverIP.C_String(), forwardingPort, packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
- }
- else if (packet->data[1]==ID_UDP_PROXY_IN_PROGRESS)
- {
- if (resultHandler)
- resultHandler->OnForwardingInProgress(serverIP.C_String(), forwardingPort, packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
- }
- else
- {
- // Send a datagram to the proxy, so if we are behind a router, that router adds an entry to the routing table.
- // Otherwise the router would block the incoming datagrams from source
- // It doesn't matter if the message actually arrives as long as it goes through the router
- rakPeerInterface->Ping(serverIP.C_String(), forwardingPort, false);
- if (resultHandler)
- resultHandler->OnForwardingNotification(serverIP.C_String(), forwardingPort, packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
- }
- }
- break;
- case ID_UDP_PROXY_ALL_SERVERS_BUSY:
- if (resultHandler)
- resultHandler->OnAllServersBusy(packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
- break;
- case ID_UDP_PROXY_NO_SERVERS_ONLINE:
- if (resultHandler)
- resultHandler->OnNoServersOnline(packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
- break;
- case ID_UDP_PROXY_RECIPIENT_GUID_NOT_CONNECTED_TO_COORDINATOR:
- {
- if (resultHandler)
- resultHandler->OnRecipientNotConnected(packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
- break;
- }
- }
-
- }
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- }
- return RR_CONTINUE_PROCESSING;
- }
- void UDPProxyClient::OnRakPeerShutdown(void)
- {
- Clear();
- }
- void UDPProxyClient::OnPingServers(Packet *packet)
- {
- RakNet::BitStream incomingBs(packet->data, packet->length, false);
- incomingBs.IgnoreBytes(2);
- PingServerGroup *psg = RakNet::OP_NEW<PingServerGroup>(_FILE_AND_LINE_);
-
- ServerWithPing swp;
- incomingBs.Read(psg->sata.senderClientAddress);
- incomingBs.Read(psg->sata.targetClientAddress);
- psg->startPingTime=RakNet::GetTimeMS();
- psg->coordinatorAddressForPings=packet->systemAddress;
- unsigned short serverListSize;
- incomingBs.Read(serverListSize);
- SystemAddress serverAddress;
- unsigned short serverListIndex;
- char ipStr[64];
- for (serverListIndex=0; serverListIndex<serverListSize; serverListIndex++)
- {
- incomingBs.Read(swp.serverAddress);
- swp.ping=DEFAULT_UNRESPONSIVE_PING_TIME_COORDINATOR;
- psg->serversToPing.Push(swp, _FILE_AND_LINE_ );
- swp.serverAddress.ToString(false,ipStr);
- rakPeerInterface->Ping(ipStr,swp.serverAddress.GetPort(),false,0);
- }
- pingServerGroups.Push(psg,_FILE_AND_LINE_);
- }
- bool UDPProxyClient::PingServerGroup::AreAllServersPinged(void) const
- {
- unsigned int serversToPingIndex;
- for (serversToPingIndex=0; serversToPingIndex < serversToPing.Size(); serversToPingIndex++)
- {
- if (serversToPing[serversToPingIndex].ping==DEFAULT_UNRESPONSIVE_PING_TIME_COORDINATOR)
- return false;
- }
- return true;
- }
- void UDPProxyClient::PingServerGroup::SendPingedServersToCoordinator(RakPeerInterface *rakPeerInterface)
- {
- BitStream outgoingBs;
- outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
- outgoingBs.Write((MessageID)ID_UDP_PROXY_PING_SERVERS_REPLY_FROM_CLIENT_TO_COORDINATOR);
- outgoingBs.Write(sata.senderClientAddress);
- outgoingBs.Write(sata.targetClientAddress);
- unsigned short serversToPingSize = (unsigned short) serversToPing.Size();
- outgoingBs.Write(serversToPingSize);
- unsigned int serversToPingIndex;
- for (serversToPingIndex=0; serversToPingIndex < serversToPingSize; serversToPingIndex++)
- {
- outgoingBs.Write(serversToPing[serversToPingIndex].serverAddress);
- outgoingBs.Write(serversToPing[serversToPingIndex].ping);
- }
- rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, coordinatorAddressForPings, false);
- }
- void UDPProxyClient::Clear(void)
- {
- for (unsigned int i=0; i < pingServerGroups.Size(); i++)
- RakNet::OP_DELETE(pingServerGroups[i],_FILE_AND_LINE_);
- pingServerGroups.Clear(false, _FILE_AND_LINE_);
- }
- #endif // _RAKNET_SUPPORT_*
|