| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368 |
- /*
- * 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_Router2==1 && _RAKNET_SUPPORT_UDPForwarder==1
- #include "Router2.h"
- #include "RakPeerInterface.h"
- #include "BitStream.h"
- #include "RakNetTime.h"
- #include "GetTime.h"
- #include "DS_OrderedList.h"
- #include "SocketLayer.h"
- #include "FormatString.h"
- #include "SocketDefines.h"
- using namespace RakNet;
- #ifndef INVALID_SOCKET
- #define INVALID_SOCKET -1
- #endif
- /*
- Algorithm:
- 1. Sender calls ConnectInternal(). A ConnnectRequest structure is allocated and stored in the connectionRequests list, containing a list of every system we are connected to. ID_ROUTER_2_QUERY_FORWARDING is sent to all connected systems.
- 2. Upon the router getting ID_ROUTER_2_QUERY_FORWARDING, ID_ROUTER_2_REPLY_FORWARDING is sent to the sender indicating if that router is connected to the endpoint, along with the ping from the router to the endpoint.
- 3. Upon the sender getting ID_ROUTER_2_REPLY_FORWARDING, the connection request structure is looked up in Router2::UpdateForwarding. The ping is stored in that structure. Once all systems have replied, the system continues to the next state. If every system in step 1 has been exhausted, and routing has occured at least once, then ID_CONNECTION_LOST is returned. If every system in step 1 has been exhausted and routing has never occured, then ID_ROUTER_2_FORWARDING_NO_PATH is returned. Otherwise, the router with the lowest ping is chosen, and RequestForwarding() is called with that system, which sends ID_ROUTER_2_REQUEST_FORWARDING to the router.
- 4. When the router gets ID_ROUTER_2_REQUEST_FORWARDING, a MiniPunchRequest structure is allocated and stored in the miniPunchesInProgress list. The function SendOOBMessages() sends ID_ROUTER_2_REPLY_TO_SENDER_PORT from the routing sockets to both the sender and endpoint. It also sends ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT through the regular RakNet connection.
- 5. The sender and endpoint should get ID_ROUTER_2_REPLY_TO_SENDER_PORT and/or ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT depending on what type of router they have. If ID_ROUTER_2_REPLY_TO_SENDER_PORT arrives, then this will reply back to the routing socket directly. If ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT arrives, then the reply port is modified to be the port specified by the router system. In both cases, ID_ROUTER_2_MINI_PUNCH_REPLY is sent. As the router has already setup the forwarding, ID_ROUTER_2_MINI_PUNCH_REPLY will actually arrive to the endpoint from the sender, and from the sender to the endpoint.
- 6. When ID_ROUTER_2_MINI_PUNCH_REPLY arrives, ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE will be sent to the router. This is to tell the router that the forwarding has succeeded.
- 7. When ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE arrives on the router, the router will find the two systems in the miniPunchesInProgress list, which was added in step 4 (See OnMiniPunchReplyBounce()). gotReplyFromSource or gotReplyFromEndpoint will be set to true, depending on the sender. When both gotReplyFromSource and gotReplyFromEndpoint have replied, then ID_ROUTER_2_REROUTE is sent to the endpoint, and ID_ROUTER_2_FORWARDING_ESTABLISHED is sent to the sender.
- 8. When the endpoint gets ID_ROUTER_2_REROUTE, the system address is updated for the guid of the sender using RakPeer::ChangeSystemAddress(). This happens in OnRerouted().
- 9. When the sender gets ID_ROUTER_2_FORWARDING_ESTABLISHED, then in OnForwardingSuccess() the endpoint is removed from the connectionRequest list and moved to the forwardedConnectionList.
- 10. In OnClosedConnection(), for the sender, if the closed connection is the endpoint, then the endpoint is removed from the forwardedConnectionList (this is a graceful disconnect). If the connection was instead lost to the router, then ConnectInternal() gets called, which goes back to step 1. If instead this was a connection requset in progress, then UpdateForwarding() gets called, which goes back to step 3.
- 11. When the user connects the endpoint and sender, then the sender will get ID_CONNECTION_REQUEST_ACCEPTED. The sender will look up the endpoint in the forwardedConnectionList, and send ID_ROUTER_2_INCREASE_TIMEOUT to the endpoint. This message will call SetTimeoutTime() on the endpoint, so that if the router disconnects, enough time is available for the reroute to complete.
- */
- #define MIN_MINIPUNCH_TIMEOUT 5000
- void Router2DebugInterface::ShowFailure(const char *message)
- {
- printf("%s", message);
- }
- void Router2DebugInterface::ShowDiagnostic(const char *message)
- {
- printf("%s", message);
- }
- enum Router2MessageIdentifiers
- {
- ID_ROUTER_2_QUERY_FORWARDING,
- ID_ROUTER_2_REPLY_FORWARDING,
- ID_ROUTER_2_REQUEST_FORWARDING,
- ID_ROUTER_2_INCREASE_TIMEOUT,
- };
- Router2::ConnnectRequest::ConnnectRequest()
- {
- }
- Router2::ConnnectRequest::~ConnnectRequest()
- {
- }
- STATIC_FACTORY_DEFINITIONS(Router2,Router2);
- Router2::Router2()
- {
- udpForwarder=0;
- maximumForwardingRequests=0;
- debugInterface=0;
- socketFamily=AF_INET;
- }
- Router2::~Router2()
- {
- ClearAll();
- if (udpForwarder)
- {
- udpForwarder->Shutdown();
- RakNet::OP_DELETE(udpForwarder,_FILE_AND_LINE_);
- }
- }
- void Router2::ClearMinipunches(void)
- {
- miniPunchesInProgressMutex.Lock();
- miniPunchesInProgress.Clear(false,_FILE_AND_LINE_);
- miniPunchesInProgressMutex.Unlock();
- }
- void Router2::ClearConnectionRequests(void)
- {
- connectionRequestsMutex.Lock();
- for (unsigned int i=0; i < connectionRequests.Size(); i++)
- {
- RakNet::OP_DELETE(connectionRequests[i],_FILE_AND_LINE_);
- }
- connectionRequests.Clear(false,_FILE_AND_LINE_);
- connectionRequestsMutex.Unlock();
- }
- bool Router2::ConnectInternal(RakNetGUID endpointGuid, bool returnConnectionLostOnFailure)
- {
- int largestPing = GetLargestPingAmongConnectedSystems();
- if (largestPing<0)
- {
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2: ConnectInternal(%I64d) failed at %s:%i\n", endpointGuid.g, __FILE__, __LINE__));
- // Not connected to anyone
- return false;
- }
- // ALready in progress?
- connectionRequestsMutex.Lock();
- if (GetConnectionRequestIndex(endpointGuid)!=(unsigned int)-1)
- {
- connectionRequestsMutex.Unlock();
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2: ConnectInternal(%I64d) failed at %s:%i\n", endpointGuid.g, __FILE__, __LINE__));
- return false;
- }
- connectionRequestsMutex.Unlock();
- // StoreRequest(endpointGuid, Largest(ping*2), systemsSentTo). Set state REQUEST_STATE_QUERY_FORWARDING
- Router2::ConnnectRequest *cr = RakNet::OP_NEW<Router2::ConnnectRequest>(_FILE_AND_LINE_);
- DataStructures::List<SystemAddress> addresses;
- DataStructures::List<RakNetGUID> guids;
- rakPeerInterface->GetSystemList(addresses, guids);
- if (guids.Size()==0)
- {
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i\n", _FILE_AND_LINE_));
- return false;
- }
- cr->requestState=R2RS_REQUEST_STATE_QUERY_FORWARDING;
- cr->pingTimeout=RakNet::GetTimeMS()+largestPing*2+1000;
- cr->endpointGuid=endpointGuid;
- cr->returnConnectionLostOnFailure=returnConnectionLostOnFailure;
- for (unsigned int i=0; i < guids.Size(); i++)
- {
- ConnectionRequestSystem crs;
- if (guids[i]!=endpointGuid)
- {
- crs.guid=guids[i];
- crs.pingToEndpoint=-1;
- cr->connectionRequestSystemsMutex.Lock();
- cr->connectionRequestSystems.Push(crs,_FILE_AND_LINE_);
- cr->connectionRequestSystemsMutex.Unlock();
- // Broadcast(ID_ROUTER_2_QUERY_FORWARDING, endpointGuid);
- RakNet::BitStream bsOut;
- bsOut.Write((MessageID)ID_ROUTER_2_INTERNAL);
- bsOut.Write((unsigned char) ID_ROUTER_2_QUERY_FORWARDING);
- bsOut.Write(endpointGuid);
- uint32_t pack_id = rakPeerInterface->Send(&bsOut,MEDIUM_PRIORITY,RELIABLE_ORDERED,0,crs.guid,false);
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Router2::ConnectInternal: at %s:%i, pack_id = %d", __FILE__, __LINE__,pack_id));
- }
- }
- else
- {
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Router2::ConnectInternal: at %s:%i [else ..].: %I64d==%I64d", __FILE__, __LINE__,
- guids[i].g,endpointGuid.g));
- }
- }
- }
- connectionRequestsMutex.Lock();
- connectionRequests.Push(cr,_FILE_AND_LINE_);
- connectionRequestsMutex.Unlock();
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Broadcasting ID_ROUTER_2_QUERY_FORWARDING to %I64d at %s:%i\n", endpointGuid.g , __FILE__, __LINE__));
- }
- return true;
- }
- void Router2::SetSocketFamily(unsigned short _socketFamily)
- {
- socketFamily=_socketFamily;
- }
- void Router2::EstablishRouting(RakNetGUID endpointGuid)
- {
- ConnectionState cs = rakPeerInterface->GetConnectionState(endpointGuid);
- if (cs!=IS_DISCONNECTED && cs!=IS_NOT_CONNECTED)
- {
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i "
- "(already connected to the %I64d)\n", __FILE__, __LINE__, endpointGuid.g ));
- return;
- }
- ConnectInternal(endpointGuid,false);
- }
- void Router2::SetMaximumForwardingRequests(int max)
- {
- if (max>0 && maximumForwardingRequests<=0)
- {
- udpForwarder = RakNet::OP_NEW<UDPForwarder>(_FILE_AND_LINE_);
- udpForwarder->Startup();
- }
- else if (max<=0 && maximumForwardingRequests>0)
- {
- udpForwarder->Shutdown();
- RakNet::OP_DELETE(udpForwarder,_FILE_AND_LINE_);
- udpForwarder=0;
- }
- maximumForwardingRequests=max;
- }
- PluginReceiveResult Router2::OnReceive(Packet *packet)
- {
- SystemAddress sa;
- RakNet::BitStream bs(packet->data,packet->length,false);
- if (packet->data[0]==ID_ROUTER_2_INTERNAL)
- {
- switch (packet->data[1])
- {
- case ID_ROUTER_2_QUERY_FORWARDING:
- {
- OnQueryForwarding(packet);
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- case ID_ROUTER_2_REPLY_FORWARDING:
- {
- OnQueryForwardingReply(packet);
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- case ID_ROUTER_2_REQUEST_FORWARDING:
- {
- if (debugInterface)
- {
- char buff[512];
- char buff2[32];
- packet->systemAddress.ToString(true,buff2);
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REQUEST_FORWARDING on ip %s from %I64d, ",
- buff2,packet->guid.g));
- }
- OnRequestForwarding(packet);
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- case ID_ROUTER_2_INCREASE_TIMEOUT:
- {
- /// The routed system wants more time to stay alive on no communication, in case the router drops or crashes
- rakPeerInterface->SetTimeoutTime(rakPeerInterface->GetTimeoutTime(packet->systemAddress)+10000, packet->systemAddress);
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- }
- }
- else if (packet->data[0]==ID_OUT_OF_BAND_INTERNAL && packet->length>=2)
- {
- switch (packet->data[1])
- {
- case ID_ROUTER_2_REPLY_TO_SENDER_PORT:
- {
- RakNet::BitStream bsOut;
- bsOut.Write(packet->guid);
- SendOOBFromRakNetPort(ID_ROUTER_2_MINI_PUNCH_REPLY, &bsOut, packet->systemAddress);
- if (debugInterface)
- {
- char buff[512];
- char buff2[32];
- sa.ToString(false,buff2);
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REPLY_TO_SENDER_PORT %i on address %s, replying with ID_ROUTER_2_MINI_PUNCH_REPLY at %s:%i\n", sa.GetPort(), buff2, _FILE_AND_LINE_));
- // packet->systemAddress.ToString(true,buff2);
- // debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REPLY_TO_SENDER_PORT on address %s (%I64d), "
- // "replying with ID_ROUTER_2_MINI_PUNCH_REPLY at %s:%i\n", buff2,packet->guid.g, __FILE__, __LINE__));
- }
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- case ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT:
- {
- RakNet::BitStream bsOut;
- bsOut.Write(packet->guid);
- bs.IgnoreBytes(2);
- sa=packet->systemAddress;
- unsigned short port;
- bs.Read(port);
- sa.SetPortHostOrder(port);
- RakAssert(sa.GetPort()!=0);
- SendOOBFromRakNetPort(ID_ROUTER_2_MINI_PUNCH_REPLY, &bsOut, sa);
- if (debugInterface)
- {
- char buff[512];
- char buff2[32];
- sa.ToString(false,buff2);
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT %i on address %s, "
- "replying with ID_ROUTER_2_MINI_PUNCH_REPLY at %s:%i\n", sa.GetPort(), buff2, __FILE__, __LINE__));
- }
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- case ID_ROUTER_2_MINI_PUNCH_REPLY:
- OnMiniPunchReply(packet);
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- case ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE:
- OnMiniPunchReplyBounce(packet);
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- }
- else if (packet->data[0]==ID_ROUTER_2_FORWARDING_ESTABLISHED)
- {
- // printf("Got ID_ROUTER_2_FORWARDING_ESTABLISHED\n");
- if (OnForwardingSuccess(packet)==false)
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- else if (packet->data[0]==ID_ROUTER_2_REROUTED)
- {
- OnRerouted(packet);
- }
- else if (packet->data[0]==ID_CONNECTION_REQUEST_ACCEPTED)
- {
- unsigned int forwardingIndex;
- forwardedConnectionListMutex.Lock();
- for (forwardingIndex=0; forwardingIndex < forwardedConnectionList.Size(); forwardingIndex++)
- {
- if (forwardedConnectionList[forwardingIndex].endpointGuid==packet->guid && forwardedConnectionList[forwardingIndex].weInitiatedForwarding)
- break;
- }
- if (forwardingIndex<forwardedConnectionList.Size())
- {
- forwardedConnectionListMutex.Unlock();
- // We connected to this system through a forwarding system
- // Have the endpoint take longer to drop us, in case the intermediary system drops
- RakNet::BitStream bsOut;
- bsOut.Write((MessageID)ID_ROUTER_2_INTERNAL);
- bsOut.Write((unsigned char) ID_ROUTER_2_INCREASE_TIMEOUT);
- rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE,0,packet->guid,false);
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_CONNECTION_REQUEST_ACCEPTED, "
- "sending ID_ROUTER_2_INCREASE_TIMEOUT to the %I64d at %s:%i\n", packet->guid.g, __FILE__, __LINE__));
- }
- // Also take longer ourselves
- rakPeerInterface->SetTimeoutTime(rakPeerInterface->GetTimeoutTime(packet->systemAddress)+10000, packet->systemAddress);
- }
- else {
- // ~Gwynn: Fix for Receive hanging up problem on Windows XP
- // See http://blog.delphi-jedi.net/2008/04/23/the-case-of-the-unexplained-dead-lock-in-a-single-thread/ for details
- forwardedConnectionListMutex.Unlock();
- }
- }
- else if (packet->data[0]==ID_ROUTER_2_FORWARDING_NO_PATH)
- {
- if (packet->wasGeneratedLocally==false)
- return RR_STOP_PROCESSING_AND_DEALLOCATE;
- }
- return RR_CONTINUE_PROCESSING;
- }
- void Router2::Update(void)
- {
- RakNet::TimeMS curTime = RakNet::GetTimeMS();
- unsigned int connectionRequestIndex=0;
- connectionRequestsMutex.Lock();
- while (connectionRequestIndex < connectionRequests.Size())
- {
- ConnnectRequest* connectionRequest = connectionRequests[connectionRequestIndex];
- // pingTimeout is only used with R2RS_REQUEST_STATE_QUERY_FORWARDING
- if (connectionRequest->requestState==R2RS_REQUEST_STATE_QUERY_FORWARDING &&
- connectionRequest->pingTimeout < curTime)
- {
- bool anyRemoved=false;
- unsigned int connectionRequestGuidIndex=0;
- connectionRequest->connectionRequestSystemsMutex.Lock();
- while (connectionRequestGuidIndex < connectionRequest->connectionRequestSystems.Size())
- {
- if (connectionRequest->connectionRequestSystems[connectionRequestGuidIndex].pingToEndpoint<0)
- {
- anyRemoved=true;
- connectionRequest->connectionRequestSystems.RemoveAtIndexFast(connectionRequestGuidIndex);
- }
- else
- {
- connectionRequestGuidIndex++;
- }
- }
- connectionRequest->connectionRequestSystemsMutex.Unlock();
- if (anyRemoved)
- {
- if (connectionRequestIndex!=(unsigned int)-1)
- {
- // connectionRequestsMutex should be locked before calling this function
- if (UpdateForwarding(connectionRequest)==false)
- {
- RemoveConnectionRequest(connectionRequestIndex);
- }
- else
- {
- connectionRequestIndex++;
- }
- }
- else
- {
- connectionRequestIndex++;
- }
- }
- else
- {
- connectionRequestIndex++;
- }
- }
- else
- {
- connectionRequestIndex++;
- }
- }
- connectionRequestsMutex.Unlock();
- unsigned int i=0;
- miniPunchesInProgressMutex.Lock();
- while (i < miniPunchesInProgress.Size())
- {
- if (miniPunchesInProgress[i].timeout<curTime)
- {
- SendFailureOnCannotForward(miniPunchesInProgress[i].sourceGuid, miniPunchesInProgress[i].endpointGuid);
- miniPunchesInProgress.RemoveAtIndexFast(i);
- }
- else if (curTime>miniPunchesInProgress[i].nextAction)
- {
- miniPunchesInProgress[i].nextAction=curTime+100;
- SendOOBMessages(&miniPunchesInProgress[i]);
- }
- else
- i++;
- }
- miniPunchesInProgressMutex.Unlock();
- }
- void Router2::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
- {
- (void) lostConnectionReason;
- (void) systemAddress;
- unsigned int forwardedConnectionIndex=0;
- forwardedConnectionListMutex.Lock();
- while (forwardedConnectionIndex<forwardedConnectionList.Size())
- {
- if (forwardedConnectionList[forwardedConnectionIndex].endpointGuid==rakNetGUID)
- {
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Closed connection to the %I64d, removing forwarding from list at %s:%i\n", rakNetGUID.g, __FILE__, __LINE__));
- }
- // No longer need forwarding
- forwardedConnectionList.RemoveAtIndexFast(forwardedConnectionIndex);
- }
- else if (forwardedConnectionList[forwardedConnectionIndex].intermediaryGuid==rakNetGUID && forwardedConnectionList[forwardedConnectionIndex].weInitiatedForwarding)
- {
- // Lost connection to intermediary. Restart process to connect to endpoint. If failed, push ID_CONNECTION_LOST. Also remove connection request if it already is in the list, to restart it
- connectionRequestsMutex.Lock();
- unsigned int pos = GetConnectionRequestIndex(forwardedConnectionList[forwardedConnectionIndex].endpointGuid);
- if((unsigned int)-1 != pos) {RakNet::OP_DELETE(connectionRequests[pos], __FILE__, __LINE__); connectionRequests.RemoveAtIndexFast(pos);}
- connectionRequestsMutex.Unlock();
-
- ConnectInternal(forwardedConnectionList[forwardedConnectionIndex].endpointGuid, true);
- forwardedConnectionIndex++;
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Closed connection %I64d, restarting forwarding at %s:%i\n",rakNetGUID.g, __FILE__, __LINE__));
- }
- // This should not be removed - the connection is still forwarded, but perhaps through another system
- // forwardedConnectionList.RemoveAtIndexFast(forwardedConnectionIndex);
- }
- else
- forwardedConnectionIndex++;
- }
- forwardedConnectionListMutex.Unlock();
- unsigned int connectionRequestIndex=0;
- connectionRequestsMutex.Lock();
- while (connectionRequestIndex < connectionRequests.Size())
- {
- ConnnectRequest *cr = connectionRequests[connectionRequestIndex];
- cr->connectionRequestSystemsMutex.Lock();
- unsigned int connectionRequestGuidIndex = cr->GetGuidIndex(rakNetGUID);
- if (connectionRequestGuidIndex!=(unsigned int)-1)
- {
- cr->connectionRequestSystems.RemoveAtIndexFast(connectionRequestGuidIndex);
- cr->connectionRequestSystemsMutex.Unlock();
- if (UpdateForwarding(cr)==false) // If returns false, no connection request systems left
- {
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Aborted connection to the %I64d, aborted forwarding at %s:%i\n", rakNetGUID.g, __FILE__, __LINE__));
- }
- RemoveConnectionRequest(connectionRequestIndex);
- }
- else // Else a system in the connection request list dropped. If cr->requestState==R2RS_REQUEST_STATE_QUERY_FORWARDING then we are still waiting for other systems to respond.
- {
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Aborted connection attempt to %I64d, restarting forwarding to %I64d at %s:%i\n", rakNetGUID.g,cr->endpointGuid.g,__FILE__, __LINE__));
- }
- // if(volatile bool is_my_fix_a_truth = true) { // A system in the list of potential systems to try routing to dropped. There is no need to restart the whole process.
- // connectionRequestsMutex.Lock();
- // connectionRequests.RemoveAtIndexFast(connectionRequestIndex);
- // connectionRequestsMutex.Unlock();
- //
- // if(false == ConnectInternal(cr->endpointGuid,cr->returnConnectionLostOnFailure))
- // if (debugInterface)
- // {
- // char buff[512];
- // debugInterface->ShowDiagnostic(FormatStringTS(buff,"ConnectInternal(cr->endpointGuid,cr->returnConnectionLostOnFailure) is false. at %s:%i\n", __FILE__, __LINE__));
- // }
- // }
-
- connectionRequestIndex++;
- }
- }
- else
- {
- cr->connectionRequestSystemsMutex.Unlock();
- connectionRequestIndex++;
- }
- }
- connectionRequestsMutex.Unlock();
- unsigned int i=0;
- miniPunchesInProgressMutex.Lock();
- while (i < miniPunchesInProgress.Size())
- {
- if (miniPunchesInProgress[i].sourceGuid==rakNetGUID || miniPunchesInProgress[i].endpointGuid==rakNetGUID)
- {
- if (miniPunchesInProgress[i].sourceGuid!=rakNetGUID)
- {
- SendFailureOnCannotForward(miniPunchesInProgress[i].sourceGuid, miniPunchesInProgress[i].endpointGuid);
- }
- miniPunchesInProgress.RemoveAtIndexFast(i);
- }
- else
- i++;
- }
- miniPunchesInProgressMutex.Unlock();
- }
- void Router2::OnFailedConnectionAttempt(Packet *packet, PI2_FailedConnectionAttemptReason failedConnectionAttemptReason)
- {
- (void) failedConnectionAttemptReason;
- (void) packet;
- unsigned int forwardedConnectionIndex=0;
- forwardedConnectionListMutex.Lock();
- while (forwardedConnectionIndex<forwardedConnectionList.Size())
- {
- if (forwardedConnectionList[forwardedConnectionIndex].intermediaryAddress==packet->systemAddress)
- {
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Failed connection attempt to forwarded system (%I64d : %s) at %s:%i\n",
- forwardedConnectionList[forwardedConnectionIndex].endpointGuid.g, packet->systemAddress.ToString(true), __FILE__, __LINE__));
- }
- packet->guid=forwardedConnectionList[forwardedConnectionIndex].endpointGuid;
- forwardedConnectionList.RemoveAtIndexFast(forwardedConnectionIndex);
- }
- else
- forwardedConnectionIndex++;
- }
- forwardedConnectionListMutex.Unlock();
- }
- void Router2::OnRakPeerShutdown(void)
- {
- ClearAll();
- }
- // connectionRequestsMutex should already be locked
- bool Router2::UpdateForwarding(ConnnectRequest* connectionRequest)
- {
- connectionRequest->connectionRequestSystemsMutex.Lock();
- // RAKNET_DEBUG_PRINTF(__FUNCTION__": connectionRequest->connectionRequestSystems.Size = %d", connectionRequest->connectionRequestSystems.Size());
- if (connectionRequest->connectionRequestSystems.Size()==0)
- {
- connectionRequest->connectionRequestSystemsMutex.Unlock();
- // printf("Router2 failed at %s:%i\n", __FILE__, __LINE__);
- if (connectionRequest->returnConnectionLostOnFailure) {
- ReturnToUser(ID_CONNECTION_LOST, connectionRequest->endpointGuid, UNASSIGNED_SYSTEM_ADDRESS, true); // This is a connection which was previously established. Rerouting is not possible.
- // bool sendDisconnectionNotification = false;
- // rakPeerInterface->CloseConnection(rakPeerInterface->GetSystemAddressFromGuid(connectionRequest->endpointGuid), sendDisconnectionNotification);
- // RAKNET_DEBUG_PRINTF(__FUNCTION__": call rakPeerInterface->CloseConnection(%I64d)" , connectionRequest->endpointGuid.g);
- }
- else
- ReturnToUser(ID_ROUTER_2_FORWARDING_NO_PATH, connectionRequest->endpointGuid, UNASSIGNED_SYSTEM_ADDRESS, false);
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Forwarding failed, no remaining systems at %s:%i\n", _FILE_AND_LINE_));
- }
- forwardedConnectionListMutex.Lock();
- for (unsigned int forwardedConnectionIndex=0; forwardedConnectionIndex < forwardedConnectionList.Size(); forwardedConnectionIndex++)
- {
- if (forwardedConnectionList[forwardedConnectionIndex].endpointGuid==connectionRequest->endpointGuid && forwardedConnectionList[forwardedConnectionIndex].weInitiatedForwarding)
- {
- forwardedConnectionList.RemoveAtIndexFast(forwardedConnectionIndex);
- break;
- }
- }
- forwardedConnectionListMutex.Unlock();
- return false;
- }
- connectionRequest->connectionRequestSystemsMutex.Unlock();
- if (connectionRequest->requestState==R2RS_REQUEST_STATE_QUERY_FORWARDING)
- {
- connectionRequest->connectionRequestSystemsMutex.Lock();
- for (unsigned int i=0; i < connectionRequest->connectionRequestSystems.Size(); i++)
- {
- if (connectionRequest->connectionRequestSystems[i].pingToEndpoint<0)
- {
- connectionRequest->connectionRequestSystemsMutex.Unlock();
- return true; // Forward query still in progress, just return
- }
- }
- connectionRequest->connectionRequestSystemsMutex.Unlock();
- RequestForwarding(connectionRequest);
- }
- // else if (connectionRequest->requestState==REQUEST_STATE_REQUEST_FORWARDING)
- // {
- // RequestForwarding(connectionRequestIndex);
- // }
- return true;
- }
- // connectionRequestsMutex should already be locked
- void Router2::RemoveConnectionRequest(unsigned int connectionRequestIndex)
- {
- RakNet::OP_DELETE(connectionRequests[connectionRequestIndex],_FILE_AND_LINE_);
- connectionRequests.RemoveAtIndexFast(connectionRequestIndex);
- }
- int ConnectionRequestSystemComp( const Router2::ConnectionRequestSystem & key, const Router2::ConnectionRequestSystem &data )
- {
- if (key.pingToEndpoint * (key.usedForwardingEntries+1) < data.pingToEndpoint * (data.usedForwardingEntries+1))
- return -1;
- if (key.pingToEndpoint * (key.usedForwardingEntries+1) == data.pingToEndpoint * (data.usedForwardingEntries+1))
- return 1;
- if (key.guid < data.guid)
- return -1;
- if (key.guid > data.guid)
- return -1;
- return 0;
- }
- // connectionRequestsMutex should already be locked
- void Router2::RequestForwarding(ConnnectRequest* connectionRequest)
- {
- RakAssert(connectionRequest->requestState==R2RS_REQUEST_STATE_QUERY_FORWARDING);
- connectionRequest->requestState=REQUEST_STATE_REQUEST_FORWARDING;
- if (connectionRequest->GetGuidIndex(connectionRequest->lastRequestedForwardingSystem)!=(unsigned int)-1)
- {
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i\n", _FILE_AND_LINE_));
- return;
- }
- // Prioritize systems to request forwarding
- DataStructures::OrderedList<ConnectionRequestSystem, ConnectionRequestSystem, ConnectionRequestSystemComp> commandList;
- unsigned int connectionRequestGuidIndex;
- connectionRequest->connectionRequestSystemsMutex.Lock();
- for (connectionRequestGuidIndex=0; connectionRequestGuidIndex < connectionRequest->connectionRequestSystems.Size(); connectionRequestGuidIndex++)
- {
- RakAssert(connectionRequest->connectionRequestSystems[connectionRequestGuidIndex].pingToEndpoint>=0);
- commandList.Insert(connectionRequest->connectionRequestSystems[connectionRequestGuidIndex],
- connectionRequest->connectionRequestSystems[connectionRequestGuidIndex],
- true,
- _FILE_AND_LINE_);
- }
- connectionRequest->connectionRequestSystemsMutex.Unlock();
- connectionRequest->lastRequestedForwardingSystem=commandList[0].guid;
- RakNet::BitStream bsOut;
- bsOut.Write((MessageID)ID_ROUTER_2_INTERNAL);
- bsOut.Write((unsigned char) ID_ROUTER_2_REQUEST_FORWARDING);
- bsOut.Write(connectionRequest->endpointGuid);
- rakPeerInterface->Send(&bsOut,MEDIUM_PRIORITY,RELIABLE_ORDERED,0,connectionRequest->lastRequestedForwardingSystem,false);
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Sending ID_ROUTER_2_REQUEST_FORWARDING "
- "(connectionRequest->lastRequestedForwardingSystem = %I64d, connectionRequest->endpointGuid = %I64d) at %s:%i\n",
- connectionRequest->lastRequestedForwardingSystem.g,connectionRequest->endpointGuid.g, __FILE__, __LINE__));
- }
- }
- void Router2::SendFailureOnCannotForward(RakNetGUID sourceGuid, RakNetGUID endpointGuid)
- {
- RakNet::BitStream bsOut;
- bsOut.Write((MessageID)ID_ROUTER_2_INTERNAL);
- bsOut.Write((unsigned char) ID_ROUTER_2_REPLY_FORWARDING);
- bsOut.Write(endpointGuid);
- bsOut.Write(false);
- rakPeerInterface->Send(&bsOut,MEDIUM_PRIORITY,RELIABLE_ORDERED,0,sourceGuid,false);
- }
- int Router2::ReturnFailureOnCannotForward(RakNetGUID sourceGuid, RakNetGUID endpointGuid)
- {
- // If the number of systems we are currently forwarding>=maxForwarding, return ID_ROUTER_2_REPLY_FORWARDING,endpointGuid,false
- if (udpForwarder==0 || udpForwarder->GetUsedForwardEntries()/2>maximumForwardingRequests)
- {
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (%I64d -> %I64d) at %s:%i\n",
- sourceGuid.g, endpointGuid.g,__FILE__, __LINE__));
- SendFailureOnCannotForward(sourceGuid,endpointGuid);
- return -1;
- }
- // We cannot forward connections which are themselves forwarded. Return fail in that case
- forwardedConnectionListMutex.Lock();
- for (unsigned int i=0; i < forwardedConnectionList.Size(); i++)
- {
- if ((forwardedConnectionList[i].endpointGuid==endpointGuid)
- || (forwardedConnectionList[i].endpointGuid==sourceGuid)) // sourceGuid is here so you do not respond to routing requests from systems you are already routing through.
- {
- forwardedConnectionListMutex.Unlock();
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i\n", __FILE__, __LINE__));
- SendFailureOnCannotForward(sourceGuid,endpointGuid);
- return -1;
- }
- }
- forwardedConnectionListMutex.Unlock();
- int pingToEndpoint;
- pingToEndpoint = rakPeerInterface->GetAveragePing(endpointGuid);
- if (pingToEndpoint==-1)
- {
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (%I64d -> %I64d) at %s:%i\n",
- sourceGuid.g, endpointGuid.g,__FILE__, __LINE__));
- SendFailureOnCannotForward(sourceGuid,endpointGuid);
- return -1;
- }
- return pingToEndpoint;
- }
- void Router2::OnQueryForwarding(Packet *packet)
- {
- RakNet::BitStream bs(packet->data, packet->length, false);
- bs.IgnoreBytes(sizeof(MessageID) + sizeof(unsigned char));
- RakNetGUID endpointGuid;
- // Read endpointGuid
- bs.Read(endpointGuid);
- int pingToEndpoint = ReturnFailureOnCannotForward(packet->guid, endpointGuid);
- if (pingToEndpoint==-1)
- {
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (%I64d) at %s:%i\n", packet->guid.g, __FILE__, __LINE__));
- return;
- }
- // If we are connected to endpointGuid, reply ID_ROUTER_2_REPLY_FORWARDING,endpointGuid,true,ping,numCurrentlyForwarding
- RakNet::BitStream bsOut;
- bsOut.Write((MessageID)ID_ROUTER_2_INTERNAL);
- bsOut.Write((unsigned char) ID_ROUTER_2_REPLY_FORWARDING);
- bsOut.Write(endpointGuid);
- bsOut.Write(true);
- bsOut.Write((unsigned short) pingToEndpoint);
- bsOut.Write((unsigned short) udpForwarder->GetUsedForwardEntries()/2);
- rakPeerInterface->Send(&bsOut,MEDIUM_PRIORITY,RELIABLE_ORDERED,0,packet->guid,false);
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Sending ID_ROUTER_2_REPLY_FORWARDING to the %I64d at %s:%i\n", packet->guid.g, __FILE__, __LINE__));
- }
- }
- void Router2::OnQueryForwardingReply(Packet *packet)
- {
- RakNet::BitStream bs(packet->data, packet->length, false);
- bs.IgnoreBytes(sizeof(MessageID) + sizeof(unsigned char));
- RakNetGUID endpointGuid;
- bs.Read(endpointGuid);
- // Find endpointGuid among stored requests
- bool canForward=false;
- bs.Read(canForward);
- connectionRequestsMutex.Lock();
- unsigned int connectionRequestIndex = GetConnectionRequestIndex(endpointGuid);
- if (connectionRequestIndex==(unsigned int)-1)
- {
- connectionRequestsMutex.Unlock();
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (%I64d) at %s:%i\n", endpointGuid.g, __FILE__, __LINE__));
- return;
- }
- connectionRequests[connectionRequestIndex]->connectionRequestSystemsMutex.Lock();
- unsigned int connectionRequestGuidIndex = connectionRequests[connectionRequestIndex]->GetGuidIndex(packet->guid);
- if (connectionRequestGuidIndex==(unsigned int)-1)
- {
- connectionRequests[connectionRequestIndex]->connectionRequestSystemsMutex.Unlock();
- connectionRequestsMutex.Unlock();
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (%I64d) at %s:%i\n", endpointGuid.g, __FILE__, __LINE__));
- return;
- }
- if (debugInterface)
- {
- char buff[512];
- char buff2[512];
- packet->systemAddress.ToString(true,buff2);
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REPLY_FORWARDING on address %s(%I64d -> %I64d) canForward=%i at %s:%i\n",
- buff2, packet->guid.g, endpointGuid.g, canForward, __FILE__, __LINE__));
- }
- if (canForward)
- {
- unsigned short pingToEndpoint;
- unsigned short usedEntries;
- bs.Read(pingToEndpoint);
- bs.Read(usedEntries);
- connectionRequests[connectionRequestIndex]->connectionRequestSystems[connectionRequestGuidIndex].usedForwardingEntries=usedEntries;
- connectionRequests[connectionRequestIndex]->connectionRequestSystems[connectionRequestGuidIndex].pingToEndpoint=rakPeerInterface->GetAveragePing(packet->guid)+pingToEndpoint;
- }
- else
- {
- connectionRequests[connectionRequestIndex]->connectionRequestSystems.RemoveAtIndex(connectionRequestGuidIndex);
- }
- connectionRequests[connectionRequestIndex]->connectionRequestSystemsMutex.Unlock();
- if (UpdateForwarding(connectionRequests[connectionRequestIndex])==false)
- {
- RemoveConnectionRequest(connectionRequestIndex);
- }
- connectionRequestsMutex.Unlock();
- }
- void Router2::SendForwardingSuccess(MessageID messageId, RakNetGUID sourceGuid, RakNetGUID endpointGuid, unsigned short sourceToDstPort)
- {
- RakNet::BitStream bsOut;
- bsOut.Write(messageId);
- bsOut.Write(endpointGuid);
- bsOut.Write(sourceToDstPort);
- rakPeerInterface->Send(&bsOut,MEDIUM_PRIORITY,RELIABLE_ORDERED,0,sourceGuid,false);
- if (debugInterface)
- {
- char buff[512];
- if (messageId==ID_ROUTER_2_FORWARDING_ESTABLISHED)
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Sending ID_ROUTER_2_FORWARDING_ESTABLISHED at %s:%i\n", _FILE_AND_LINE_ ));
- else
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Sending ID_ROUTER_2_REROUTED at %s:%i\n", _FILE_AND_LINE_ ));
- }
- }
- void Router2::SendOOBFromRakNetPort(OutOfBandIdentifiers oob, BitStream *extraData, SystemAddress sa)
- {
- RakNet::BitStream oobBs;
- oobBs.Write((unsigned char)oob);
- if (extraData)
- {
- extraData->ResetReadPointer();
- oobBs.Write(*extraData);
- }
- char ipAddressString[32];
- sa.ToString(false, ipAddressString);
- rakPeerInterface->SendOutOfBand((const char*) ipAddressString,sa.GetPort(),(const char*) oobBs.GetData(),oobBs.GetNumberOfBytesUsed());
- }
- void Router2::SendOOBFromSpecifiedSocket(OutOfBandIdentifiers oob, SystemAddress sa, __UDPSOCKET__ socket)
- {
- RakNet::BitStream bs;
- rakPeerInterface->WriteOutOfBandHeader(&bs);
- bs.Write((unsigned char) oob);
- // SocketLayer::SendTo_PC( socket, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), sa, __FILE__, __LINE__ );
- if (sa.address.addr4.sin_family==AF_INET)
- {
- sendto__( socket, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), 0, ( const sockaddr* ) & sa.address.addr4, sizeof( sockaddr_in ) );
- }
- else
- {
- #if RAKNET_SUPPORT_IPV6==1
- sendto__( socket, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), 0, ( const sockaddr* ) & sa.address.addr6, sizeof( sockaddr_in6 ) );
- #endif
- }
- }
- void Router2::SendOOBMessages(Router2::MiniPunchRequest *mpr)
- {
- // Mini NAT punch
- // Send from srcToDestPort to packet->systemAddress (source). If the message arrives, the remote system should reply.
- SendOOBFromSpecifiedSocket(ID_ROUTER_2_REPLY_TO_SENDER_PORT, mpr->sourceAddress, mpr->forwardingSocket);
- // Send from destToSourcePort to endpointSystemAddress (destination). If the message arrives, the remote system should reply.
- SendOOBFromSpecifiedSocket(ID_ROUTER_2_REPLY_TO_SENDER_PORT, mpr->endpointAddress, mpr->forwardingSocket);
- if (debugInterface) {
- char buff [512];
- char buff2[128];
- mpr->sourceAddress .ToString(true,buff2);
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"call SendOOBFromSpecifiedSocket(...,%s,...)", buff2));
- mpr->endpointAddress .ToString(true,buff2);
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"call SendOOBFromSpecifiedSocket(...,%s,...)", buff2));
- }
- // Tell source to send to forwardingPort
- RakNet::BitStream extraData;
- extraData.Write(mpr->forwardingPort);
- RakAssert(mpr->forwardingPort!=0);
- SendOOBFromRakNetPort(ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT, &extraData, mpr->sourceAddress);
- // Tell destination to send to forwardingPort
- extraData.Reset();
- extraData.Write(mpr->forwardingPort);
- RakAssert(mpr->forwardingPort);
- SendOOBFromRakNetPort(ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT, &extraData, mpr->endpointAddress);
- }
- void Router2::OnRequestForwarding(Packet *packet)
- {
- RakNet::BitStream bs(packet->data, packet->length, false);
- bs.IgnoreBytes(sizeof(MessageID) + sizeof(unsigned char));
- RakNetGUID endpointGuid;
- bs.Read(endpointGuid);
- int pingToEndpoint = ReturnFailureOnCannotForward(packet->guid, endpointGuid);
- if (pingToEndpoint==-1)
- {
- char buff[512];
- if (debugInterface) debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed (packet->guid =%I64d, endpointGuid = %I64d) at %s:%i\n",
- packet->guid.g, endpointGuid.g, __FILE__, __LINE__));
- return;
- }
- unsigned short forwardingPort=0;
- __UDPSOCKET__ forwardingSocket=INVALID_SOCKET;
- SystemAddress endpointSystemAddress = rakPeerInterface->GetSystemAddressFromGuid(endpointGuid);
- UDPForwarderResult result = udpForwarder->StartForwarding(
- packet->systemAddress, endpointSystemAddress, 30000, 0, socketFamily,
- &forwardingPort, &forwardingSocket);
- if (result==UDPFORWARDER_FORWARDING_ALREADY_EXISTS)
- {
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REQUEST_FORWARDING, result=UDPFORWARDER_FORWARDING_ALREADY_EXISTS "
- "(packet->guid =%I64d, endpointGuid = %I64d) at %s:%i\n",
- packet->guid.g, endpointGuid.g,__FILE__, __LINE__));
- }
- SendForwardingSuccess(ID_ROUTER_2_FORWARDING_ESTABLISHED, packet->guid, endpointGuid, forwardingPort);
- }
- else if (result==UDPFORWARDER_NO_SOCKETS)
- {
- char buff[512];
- char buff2[64];
- char buff3[64];
- packet->systemAddress.ToString(true,buff2);
- endpointSystemAddress.ToString(true,buff3);
- if (debugInterface)
- debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i with UDPFORWARDER_NO_SOCKETS, packet->systemAddress=%s, endpointSystemAddress=%s, forwardingPort=%i, forwardingSocket=%i\n",
- __FILE__, __LINE__, buff2, buff3, forwardingPort, forwardingSocket));
- SendFailureOnCannotForward(packet->guid, endpointGuid);
- }
- else if (result==UDPFORWARDER_INVALID_PARAMETERS)
- {
- char buff[512];
- char buff2[64];
- char buff3[64];
- packet->systemAddress.ToString(true,buff2);
- endpointSystemAddress.ToString(true,buff3);
- if (debugInterface)
- debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i with UDPFORWARDER_INVALID_PARAMETERS, packet->systemAddress=%s, endpointSystemAddress=%s, forwardingPort=%i, forwardingSocket=%i\n",
- __FILE__, __LINE__, buff2, buff3, forwardingPort, forwardingSocket));
- SendFailureOnCannotForward(packet->guid, endpointGuid);
- }
- else if (result==UDPFORWARDER_BIND_FAILED)
- {
- char buff[512];
- char buff2[64];
- char buff3[64];
- packet->systemAddress.ToString(true,buff2);
- endpointSystemAddress.ToString(true,buff3);
- if (debugInterface)
- debugInterface->ShowFailure(FormatStringTS(buff,"Router2 failed at %s:%i with UDPFORWARDER_BIND_FAILED, packet->systemAddress=%s, endpointSystemAddress=%s, forwardingPort=%i, forwardingSocket=%i\n",
- __FILE__, __LINE__, buff2, buff3, forwardingPort, forwardingSocket));
- SendFailureOnCannotForward(packet->guid, endpointGuid);
- }
- else
- {
- if (debugInterface)
- {
- char buff2[32];
- char buff3[32];
- endpointSystemAddress.ToString(true,buff2);
- packet->systemAddress.ToString(true,buff3);
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REQUEST_FORWARDING.\n"
- "endpointAddress=%s\nsourceAddress=%s\nforwardingPort=%i\n "
- "calling SendOOBMessages at %s:%i\n", buff2,buff3,forwardingPort,_FILE_AND_LINE_));
- }
- // Store the punch request
- MiniPunchRequest miniPunchRequest;
- miniPunchRequest.endpointAddress=endpointSystemAddress;
- miniPunchRequest.endpointGuid=endpointGuid;
- miniPunchRequest.gotReplyFromEndpoint=false;
- miniPunchRequest.gotReplyFromSource=false;
- miniPunchRequest.sourceGuid=packet->guid;
- miniPunchRequest.sourceAddress=packet->systemAddress;
- miniPunchRequest.forwardingPort=forwardingPort;
- miniPunchRequest.forwardingSocket=forwardingSocket;
- int ping1 = rakPeerInterface->GetAveragePing(packet->guid);
- int ping2 = rakPeerInterface->GetAveragePing(endpointGuid);
- if (ping1>ping2)
- miniPunchRequest.timeout=RakNet::GetTimeMS() + ping1*8+300;
- else
- miniPunchRequest.timeout=RakNet::GetTimeMS() + ping2*8+300;
- miniPunchRequest.nextAction=RakNet::GetTimeMS()+100;
- SendOOBMessages(&miniPunchRequest);
- miniPunchesInProgressMutex.Lock();
- miniPunchesInProgress.Push(miniPunchRequest,_FILE_AND_LINE_);
- miniPunchesInProgressMutex.Unlock();
- }
- }
- void Router2::OnMiniPunchReplyBounce(Packet *packet)
- {
- // Find stored punch request
- unsigned int i=0;
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE from guid=%I64d (miniPunchesInProgress.Size() = %d)",
- packet->guid.g, miniPunchesInProgress.Size()));
- }
- miniPunchesInProgressMutex.Lock();
- while (i < miniPunchesInProgress.Size())
- {
- if (miniPunchesInProgress[i].sourceGuid==packet->guid || miniPunchesInProgress[i].endpointGuid==packet->guid)
- {
- if (miniPunchesInProgress[i].sourceGuid==packet->guid)
- miniPunchesInProgress[i].gotReplyFromSource=true;
- if (miniPunchesInProgress[i].endpointGuid==packet->guid)
- miniPunchesInProgress[i].gotReplyFromEndpoint=true;
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Processing ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE, gotReplyFromSource=%i gotReplyFromEndpoint=%i at %s:%i\n", miniPunchesInProgress[i].gotReplyFromSource, miniPunchesInProgress[i].gotReplyFromEndpoint, __FILE__, __LINE__));
- }
- if (miniPunchesInProgress[i].gotReplyFromEndpoint==true &&
- miniPunchesInProgress[i].gotReplyFromSource==true)
- {
- SendForwardingSuccess(ID_ROUTER_2_REROUTED, miniPunchesInProgress[i].endpointGuid, miniPunchesInProgress[i].sourceGuid, miniPunchesInProgress[i].forwardingPort);
- SendForwardingSuccess(ID_ROUTER_2_FORWARDING_ESTABLISHED, miniPunchesInProgress[i].sourceGuid, miniPunchesInProgress[i].endpointGuid, miniPunchesInProgress[i].forwardingPort);
- miniPunchesInProgress.RemoveAtIndexFast(i);
- }
- else
- {
- i++;
- }
- }
- else
- i++;
- }
- miniPunchesInProgressMutex.Unlock();
- }
- void Router2::OnMiniPunchReply(Packet *packet)
- {
- RakNet::BitStream bs(packet->data, packet->length, false);
- bs.IgnoreBytes(sizeof(MessageID) + sizeof(unsigned char));
- RakNetGUID routerGuid;
- bs.Read(routerGuid);
- SendOOBFromRakNetPort(ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE, 0, rakPeerInterface->GetSystemAddressFromGuid(routerGuid));
- if (debugInterface)
- {
- char buff[512];
- char buff2[512];
- rakPeerInterface->GetSystemAddressFromGuid(routerGuid).ToString(true,buff2);
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Sending ID_ROUTER_2_MINI_PUNCH_REPLY_BOUNCE (%s) at %s:%i\n", buff2, __FILE__, __LINE__));
- }
- }
- void Router2::OnRerouted(Packet *packet)
- {
- RakNet::BitStream bs(packet->data, packet->length, false);
- bs.IgnoreBytes(sizeof(MessageID));
- RakNetGUID endpointGuid;
- bs.Read(endpointGuid);
- unsigned short sourceToDestPort;
- bs.Read(sourceToDestPort);
- // Return rerouted notice
- SystemAddress intermediaryAddress=packet->systemAddress;
- intermediaryAddress.SetPortHostOrder(sourceToDestPort);
- rakPeerInterface->ChangeSystemAddress(endpointGuid, intermediaryAddress);
- unsigned int forwardingIndex;
- forwardedConnectionListMutex.Lock();
- for (forwardingIndex=0; forwardingIndex < forwardedConnectionList.Size(); forwardingIndex++)
- {
- if (forwardedConnectionList[forwardingIndex].endpointGuid==endpointGuid)
- break;
- }
- if (forwardingIndex<forwardedConnectionList.Size())
- {
- ForwardedConnection& ref_fc = forwardedConnectionList[forwardingIndex];
- forwardedConnectionListMutex.Unlock();
- ref_fc.intermediaryAddress = packet->systemAddress;
- ref_fc.intermediaryAddress.SetPortHostOrder(sourceToDestPort);
- ref_fc.intermediaryGuid = packet->guid;
- rakPeerInterface->ChangeSystemAddress(endpointGuid, intermediaryAddress);
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"FIX: Got ID_ROUTER_2_REROUTE, returning ID_ROUTER_2_REROUTED,"
- " Calling RakPeer::ChangeSystemAddress(%I64d, %s) at %s:%i\n",endpointGuid.g, intermediaryAddress.ToString(true), __FILE__, __LINE__));
- }
- }
- else
- {
- ForwardedConnection fc;
- fc.endpointGuid=endpointGuid;
- fc.intermediaryAddress=packet->systemAddress;
- fc.intermediaryAddress.SetPortHostOrder(sourceToDestPort);
- fc.intermediaryGuid=packet->guid;
- fc.weInitiatedForwarding=false;
- // add to forwarding list. This is only here to avoid reporting direct connections in Router2::ReturnFailureOnCannotForward
- forwardedConnectionList.Push (fc,__FILE__, __LINE__);
- forwardedConnectionListMutex.Unlock();
- rakPeerInterface->ChangeSystemAddress(endpointGuid, intermediaryAddress);
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_REROUTE, returning ID_ROUTER_2_REROUTED, Calling RakPeer::ChangeSystemAddress at %s:%i\n", __FILE__, __LINE__));
- }
- }
- }
- bool Router2::OnForwardingSuccess(Packet *packet)
- {
- RakNet::BitStream bs(packet->data, packet->length, false);
- bs.IgnoreBytes(sizeof(MessageID));
- RakNetGUID endpointGuid;
- bs.Read(endpointGuid);
- unsigned short sourceToDestPort;
- bs.Read(sourceToDestPort);
- unsigned int forwardingIndex;
- forwardedConnectionListMutex.Lock();
- for (forwardingIndex=0; forwardingIndex < forwardedConnectionList.Size(); forwardingIndex++)
- {
- if (forwardedConnectionList[forwardingIndex].endpointGuid==endpointGuid)
- break;
- }
- if (forwardingIndex<forwardedConnectionList.Size())
- {
- // Return rerouted notice
- SystemAddress intermediaryAddress=packet->systemAddress;
- intermediaryAddress.SetPortHostOrder(sourceToDestPort);
- rakPeerInterface->ChangeSystemAddress(endpointGuid, intermediaryAddress);
- ////////////////////////////////////////////////////////////////////////////
- ForwardedConnection& ref_fc = forwardedConnectionList[forwardingIndex];
- ref_fc.intermediaryAddress = packet->systemAddress;
- ref_fc.intermediaryAddress.SetPortHostOrder(sourceToDestPort);
- ref_fc.intermediaryGuid = packet->guid;
- ////////////////////////////////////////////////////////////////////////////
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got ID_ROUTER_2_FORWARDING_ESTABLISHED, returning ID_ROUTER_2_REROUTED, Calling RakPeer::ChangeSystemAddress at %s:%i\n", _FILE_AND_LINE_));
- }
- packet->data[0]=ID_ROUTER_2_REROUTED;
- forwardedConnectionListMutex.Unlock();
- return true; // Return packet to user
- }
- else
- {
- forwardedConnectionListMutex.Unlock();
- // removeFrom connectionRequests;
- ForwardedConnection fc;
- connectionRequestsMutex.Lock();
- unsigned int connectionRequestIndex = GetConnectionRequestIndex(endpointGuid);
- fc.returnConnectionLostOnFailure=connectionRequests[connectionRequestIndex]->returnConnectionLostOnFailure;
- connectionRequests.RemoveAtIndexFast(connectionRequestIndex);
- connectionRequestsMutex.Unlock();
- fc.endpointGuid=endpointGuid;
- fc.intermediaryAddress=packet->systemAddress;
- fc.intermediaryAddress.SetPortHostOrder(sourceToDestPort);
- fc.intermediaryGuid=packet->guid;
- fc.weInitiatedForwarding=true;
- // add to forwarding list
- forwardedConnectionListMutex.Lock();
- forwardedConnectionList.Push (fc,_FILE_AND_LINE_);
- forwardedConnectionListMutex.Unlock();
- if (debugInterface)
- {
- char buff[512];
- debugInterface->ShowDiagnostic(FormatStringTS(buff,"Got and returning to user ID_ROUTER_2_FORWARDING_ESTABLISHED at %s:%i\n", _FILE_AND_LINE_));
- }
- }
- return true; // Return packet to user
- }
- int Router2::GetLargestPingAmongConnectedSystems(void) const
- {
- int avePing;
- int largestPing=-1;
- unsigned int maxPeers = rakPeerInterface->GetMaximumNumberOfPeers();
- if (maxPeers==0)
- return 9999;
- unsigned int index;
- for (index=0; index < rakPeerInterface->GetMaximumNumberOfPeers(); index++)
- {
- RakNetGUID g = rakPeerInterface->GetGUIDFromIndex(index);
- if (g!=UNASSIGNED_RAKNET_GUID)
- {
- avePing=rakPeerInterface->GetAveragePing(rakPeerInterface->GetGUIDFromIndex(index));
- if (avePing>largestPing)
- largestPing=avePing;
- }
- }
- return largestPing;
- }
- unsigned int Router2::GetConnectionRequestIndex(RakNetGUID endpointGuid)
- {
- unsigned int i;
- for (i=0; i < connectionRequests.Size(); i++)
- {
- if (connectionRequests[i]->endpointGuid==endpointGuid)
- return i;
- }
- return (unsigned int) -1;
- }
- unsigned int Router2::ConnnectRequest::GetGuidIndex(RakNetGUID guid)
- {
- unsigned int i;
- for (i=0; i < connectionRequestSystems.Size(); i++)
- {
- if (connectionRequestSystems[i].guid==guid)
- return i;
- }
- return (unsigned int) -1;
- }
- void Router2::ReturnToUser(MessageID messageId, RakNetGUID endpointGuid, const SystemAddress &systemAddress, bool wasGeneratedLocally)
- {
- Packet *p = AllocatePacketUnified(sizeof(MessageID)+sizeof(unsigned char));
- p->data[0]=messageId;
- p->systemAddress=systemAddress;
- p->systemAddress.systemIndex=(SystemIndex)-1;
- p->guid=endpointGuid;
- p->wasGeneratedLocally=wasGeneratedLocally;
- rakPeerInterface->PushBackPacket(p, true);
- }
- void Router2::ClearForwardedConnections(void)
- {
- forwardedConnectionListMutex.Lock();
- forwardedConnectionList.Clear(false,_FILE_AND_LINE_);
- forwardedConnectionListMutex.Unlock();
- }
- void Router2::ClearAll(void)
- {
- ClearConnectionRequests();
- ClearMinipunches();
- ClearForwardedConnections();
- }
- void Router2::SetDebugInterface(Router2DebugInterface *_debugInterface)
- {
- debugInterface=_debugInterface;
- }
- Router2DebugInterface *Router2::GetDebugInterface(void) const
- {
- return debugInterface;
- }
- #endif // _RAKNET_SUPPORT_*
|