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
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
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
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
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
00192
00193
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