• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

UDPProxyClient.cpp

Go to the documentation of this file.
00001 #include "NativeFeatureIncludes.h"
00002 #if _RAKNET_SUPPORT_UDPProxyClient==1
00003 
00004 #include "UDPProxyClient.h"
00005 #include "BitStream.h"
00006 #include "UDPProxyCommon.h"
00007 #include "RakPeerInterface.h"
00008 #include "MessageIdentifiers.h"
00009 #include "GetTime.h"
00010 
00011 using namespace RakNet;
00012 static const int DEFAULT_UNRESPONSIVE_PING_TIME=1000;
00013 
00014 bool operator<( const DataStructures::MLKeyRef<UDPProxyClient::ServerWithPing> &inputKey, const UDPProxyClient::ServerWithPing &cls ) {return inputKey.Get().serverAddress < cls.serverAddress;}
00015 bool operator>( const DataStructures::MLKeyRef<UDPProxyClient::ServerWithPing> &inputKey, const UDPProxyClient::ServerWithPing &cls ) {return inputKey.Get().serverAddress > cls.serverAddress;}
00016 bool operator==( const DataStructures::MLKeyRef<UDPProxyClient::ServerWithPing> &inputKey, const UDPProxyClient::ServerWithPing &cls ) {return inputKey.Get().serverAddress == cls.serverAddress;}
00017 
00018 
00019 UDPProxyClient::UDPProxyClient()
00020 {
00021         resultHandler=0;
00022 }
00023 UDPProxyClient::~UDPProxyClient()
00024 {
00025         Clear();
00026 }
00027 void UDPProxyClient::SetResultHandler(UDPProxyClientResultHandler *rh)
00028 {
00029         resultHandler=rh;
00030 }
00031 bool UDPProxyClient::RequestForwarding(SystemAddress proxyCoordinator, SystemAddress sourceAddress, RakNetGUID targetGuid, RakNetTimeMS timeoutOnNoDataMS, RakNet::BitStream *serverSelectionBitstream)
00032 {
00033         if (rakPeerInterface->IsConnected(proxyCoordinator,false,false)==false)
00034                 return false;
00035 
00036         // Pretty much a bug not to set the result handler, as otherwise you won't know if the operation succeeed or not
00037         RakAssert(resultHandler!=0);
00038         if (resultHandler==0)
00039                 return false;
00040 
00041         BitStream outgoingBs;
00042         outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
00043         outgoingBs.Write((MessageID)ID_UDP_PROXY_FORWARDING_REQUEST_FROM_CLIENT_TO_COORDINATOR);
00044         outgoingBs.Write(sourceAddress);
00045         outgoingBs.Write(false);
00046         outgoingBs.Write(targetGuid);
00047         outgoingBs.Write(timeoutOnNoDataMS);
00048         if (serverSelectionBitstream && serverSelectionBitstream->GetNumberOfBitsUsed()>0)
00049         {
00050                 outgoingBs.Write(true);
00051                 outgoingBs.Write(serverSelectionBitstream);
00052         }
00053         else
00054         {
00055                 outgoingBs.Write(false);
00056         }
00057         rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, proxyCoordinator, false);
00058 
00059         return true;
00060 }
00061 bool UDPProxyClient::RequestForwarding(SystemAddress proxyCoordinator, SystemAddress sourceAddress, SystemAddress targetAddressAsSeenFromCoordinator, RakNetTimeMS timeoutOnNoDataMS, RakNet::BitStream *serverSelectionBitstream)
00062 {
00063         if (rakPeerInterface->IsConnected(proxyCoordinator,false,false)==false)
00064                 return false;
00065 
00066         // Pretty much a bug not to set the result handler, as otherwise you won't know if the operation succeeed or not
00067         RakAssert(resultHandler!=0);
00068         if (resultHandler==0)
00069                 return false;
00070 
00071         BitStream outgoingBs;
00072         outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
00073         outgoingBs.Write((MessageID)ID_UDP_PROXY_FORWARDING_REQUEST_FROM_CLIENT_TO_COORDINATOR);
00074         outgoingBs.Write(sourceAddress);
00075         outgoingBs.Write(true);
00076                 outgoingBs.Write(targetAddressAsSeenFromCoordinator);
00077         outgoingBs.Write(timeoutOnNoDataMS);
00078         if (serverSelectionBitstream && serverSelectionBitstream->GetNumberOfBitsUsed()>0)
00079         {
00080                 outgoingBs.Write(true);
00081                 outgoingBs.Write(serverSelectionBitstream);
00082         }
00083         else
00084         {
00085                 outgoingBs.Write(false);
00086         }
00087         rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, proxyCoordinator, false);
00088 
00089         return true;
00090 }
00091 void UDPProxyClient::Update(void)
00092 {
00093         DataStructures::DefaultIndexType idx1=0;
00094         while (idx1 < pingServerGroups.GetSize())
00095         {
00096                 PingServerGroup *psg = pingServerGroups[idx1];
00097 
00098                 if (psg->serversToPing.GetSize() > 0 && 
00099                         RakNet::GetTime() > psg->startPingTime+DEFAULT_UNRESPONSIVE_PING_TIME)
00100                 {
00101                         // If they didn't reply within DEFAULT_UNRESPONSIVE_PING_TIME, just give up on them
00102                         psg->SendPingedServersToCoordinator(rakPeerInterface);
00103 
00104                         RakNet::OP_DELETE(psg,__FILE__,__LINE__);
00105                         pingServerGroups.RemoveAtIndex(idx1, __FILE__, __LINE__ );
00106                 }
00107                 else
00108                         idx1++;
00109         }
00110 
00111 }
00112 PluginReceiveResult UDPProxyClient::OnReceive(Packet *packet)
00113 {
00114         if (packet->data[0]==ID_PONG)
00115         {
00116                 DataStructures::DefaultIndexType idx1, idx2;
00117                 PingServerGroup *psg;
00118                 for (idx1=0; idx1 < pingServerGroups.GetSize(); idx1++)
00119                 {
00120                         psg = pingServerGroups[idx1];
00121                         for (idx2=0; idx2 < psg->serversToPing.GetSize(); idx2++)
00122                         {
00123                                 if (psg->serversToPing[idx2].serverAddress==packet->systemAddress)
00124                                 {
00125                                         RakNet::BitStream bsIn(packet->data,packet->length,false);
00126                                         bsIn.IgnoreBytes(sizeof(MessageID));
00127                                         RakNetTime sentTime;
00128                                         bsIn.Read(sentTime);
00129                                         RakNetTime curTime=RakNet::GetTime();
00130                                         int ping;
00131                                         if (curTime>sentTime)
00132                                                 ping=(int) (curTime-sentTime);
00133                                         else
00134                                                 ping=0;
00135                                         psg->serversToPing[idx2].ping=(unsigned short) ping;
00136 
00137                                         // If all servers to ping are now pinged, reply to coordinator
00138                                         if (psg->AreAllServersPinged())
00139                                         {
00140                                                 psg->SendPingedServersToCoordinator(rakPeerInterface);
00141                                                 RakNet::OP_DELETE(psg,__FILE__,__LINE__);
00142                                                 pingServerGroups.RemoveAtIndex(idx1, __FILE__, __LINE__ );
00143                                         }
00144 
00145                                         return RR_STOP_PROCESSING_AND_DEALLOCATE;
00146                                 }
00147                         }
00148 
00149                 }
00150         }
00151         else if (packet->data[0]==ID_UDP_PROXY_GENERAL && packet->length>1)
00152         {
00153                 switch (packet->data[1])
00154                 {
00155                 case ID_UDP_PROXY_PING_SERVERS_FROM_COORDINATOR_TO_CLIENT:
00156                         {
00157                                 OnPingServers(packet);
00158                         }
00159                 break;
00160                 case ID_UDP_PROXY_FORWARDING_SUCCEEDED:
00161                 case ID_UDP_PROXY_ALL_SERVERS_BUSY:
00162                 case ID_UDP_PROXY_IN_PROGRESS:
00163                 case ID_UDP_PROXY_NO_SERVERS_ONLINE:
00164                 case ID_UDP_PROXY_RECIPIENT_GUID_NOT_CONNECTED_TO_COORDINATOR:
00165                 case ID_UDP_PROXY_FORWARDING_NOTIFICATION:
00166                         {
00167                                 SystemAddress senderAddress, targetAddress;
00168                                 RakNet::BitStream incomingBs(packet->data, packet->length, false);
00169                                 incomingBs.IgnoreBytes(sizeof(MessageID)*2);
00170                                 incomingBs.Read(senderAddress);
00171                                 incomingBs.Read(targetAddress);
00172 
00173                                 switch (packet->data[1])
00174                                 {
00175                                 case ID_UDP_PROXY_FORWARDING_NOTIFICATION:
00176                                 case ID_UDP_PROXY_FORWARDING_SUCCEEDED:
00177                                         {
00178                                                 unsigned short srcToDestPort;
00179                                                 unsigned short destToSourcePort;
00180                                                 RakNet::RakString serverIP;
00181                                                 incomingBs.Read(serverIP);
00182                                                 incomingBs.Read(srcToDestPort);
00183                                                 incomingBs.Read(destToSourcePort);
00184                                                 if (packet->data[1]==ID_UDP_PROXY_FORWARDING_SUCCEEDED)
00185                                                 {
00186                                                         if (resultHandler)
00187                                                                 resultHandler->OnForwardingSuccess(serverIP.C_String(), srcToDestPort, destToSourcePort, packet->systemAddress, senderAddress, targetAddress, this);
00188                                                 }
00189                                                 else
00190                                                 {
00191                                                         // Send a datagram to the proxy, so if we are behind a router, that router adds an entry to the routing table.
00192                                                         // Otherwise the router would block the incoming datagrams from source
00193                                                         // It doesn't matter if the message actually arrives as long as it goes through the router
00194                                                         rakPeerInterface->Ping(serverIP.C_String(), destToSourcePort, false);
00195 
00196                                                         if (resultHandler)
00197                                                                 resultHandler->OnForwardingNotification(serverIP.C_String(), srcToDestPort, destToSourcePort, packet->systemAddress, senderAddress, targetAddress, this);
00198                                                 }
00199                                         }
00200                                         break;
00201                                 case ID_UDP_PROXY_ALL_SERVERS_BUSY:
00202                                         if (resultHandler)
00203                                                 resultHandler->OnAllServersBusy(packet->systemAddress, senderAddress, targetAddress, this);
00204                                         break;
00205                                 case ID_UDP_PROXY_IN_PROGRESS:
00206                                         if (resultHandler)
00207                                                 resultHandler->OnForwardingInProgress(packet->systemAddress, senderAddress, targetAddress, this);
00208                                         break;
00209                                 case ID_UDP_PROXY_NO_SERVERS_ONLINE:
00210                                         if (resultHandler)
00211                                                 resultHandler->OnNoServersOnline(packet->systemAddress, senderAddress, targetAddress, this);
00212                                         break;
00213                                 case ID_UDP_PROXY_RECIPIENT_GUID_NOT_CONNECTED_TO_COORDINATOR:
00214                                         {
00215                                                 RakNetGUID targetGuid;
00216                                                 incomingBs.Read(targetGuid);
00217                                                 if (resultHandler)
00218                                                         resultHandler->OnRecipientNotConnected(packet->systemAddress, senderAddress, targetAddress, targetGuid, this);
00219                                                 break;
00220                                         }
00221                                 }
00222                         
00223                         }
00224                         return RR_STOP_PROCESSING_AND_DEALLOCATE;
00225                 }
00226         }
00227         return RR_CONTINUE_PROCESSING;
00228 }
00229 void UDPProxyClient::OnRakPeerShutdown(void)
00230 {
00231         Clear();
00232 }
00233 void UDPProxyClient::OnPingServers(Packet *packet)
00234 {
00235         RakNet::BitStream incomingBs(packet->data, packet->length, false);
00236         incomingBs.IgnoreBytes(2);
00237 
00238         PingServerGroup *psg = RakNet::OP_NEW<PingServerGroup>(__FILE__,__LINE__);
00239         
00240         ServerWithPing swp;
00241         incomingBs.Read(psg->sata.senderClientAddress);
00242         incomingBs.Read(psg->sata.targetClientAddress);
00243         psg->startPingTime=RakNet::GetTime();
00244         psg->coordinatorAddressForPings=packet->systemAddress;
00245         unsigned short serverListSize;
00246         incomingBs.Read(serverListSize);
00247         SystemAddress serverAddress;
00248         unsigned short serverListIndex;
00249         char ipStr[64];
00250         for (serverListIndex=0; serverListIndex<serverListSize; serverListIndex++)
00251         {
00252                 incomingBs.Read(swp.serverAddress);
00253                 swp.ping=DEFAULT_UNRESPONSIVE_PING_TIME;
00254                 psg->serversToPing.Push(swp, __FILE__, __LINE__ );
00255                 swp.serverAddress.ToString(false,ipStr);
00256                 rakPeerInterface->Ping(ipStr,swp.serverAddress.port,false,0);
00257         }
00258         pingServerGroups.Push(psg,__FILE__,__LINE__);
00259 }
00260 
00261 bool UDPProxyClient::PingServerGroup::AreAllServersPinged(void) const
00262 {
00263         DataStructures::DefaultIndexType serversToPingIndex;
00264         for (serversToPingIndex=0; serversToPingIndex < serversToPing.GetSize(); serversToPingIndex++)
00265         {
00266                 if (serversToPing[serversToPingIndex].ping==DEFAULT_UNRESPONSIVE_PING_TIME)
00267                         return false;
00268         }
00269         return true;
00270 }
00271 
00272 void UDPProxyClient::PingServerGroup::SendPingedServersToCoordinator(RakPeerInterface *rakPeerInterface)
00273 {
00274         BitStream outgoingBs;
00275         outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
00276         outgoingBs.Write((MessageID)ID_UDP_PROXY_PING_SERVERS_REPLY_FROM_CLIENT_TO_COORDINATOR);
00277         outgoingBs.Write(sata.senderClientAddress);
00278         outgoingBs.Write(sata.targetClientAddress);
00279         unsigned short serversToPingSize = (unsigned short) serversToPing.GetSize();
00280         outgoingBs.Write(serversToPingSize);
00281         DataStructures::DefaultIndexType serversToPingIndex;
00282         for (serversToPingIndex=0; serversToPingIndex < serversToPingSize; serversToPingIndex++)
00283         {
00284                 outgoingBs.Write(serversToPing[serversToPingIndex].serverAddress);
00285                 outgoingBs.Write(serversToPing[serversToPingIndex].ping);
00286         }
00287         rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, coordinatorAddressForPings, false);
00288 }
00289 void UDPProxyClient::Clear(void)
00290 {
00291         pingServerGroups.ClearPointers(false,__FILE__,__LINE__);
00292 }
00293 
00294 
00295 #endif // _RAKNET_SUPPORT_*
00296 

Generated on Thu Sep 30 2010 01:27:29 for RakNet by  doxygen 1.7.1