| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- /*
- * 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_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
- #include "PacketizedTCP.h"
- #include "NativeTypes.h"
- #include "BitStream.h"
- #include "MessageIdentifiers.h"
- #include "RakAlloca.h"
- using namespace RakNet;
- typedef uint32_t PTCPHeader;
- STATIC_FACTORY_DEFINITIONS(PacketizedTCP,PacketizedTCP);
- PacketizedTCP::PacketizedTCP()
- {
- }
- PacketizedTCP::~PacketizedTCP()
- {
- ClearAllConnections();
- }
- void PacketizedTCP::Stop(void)
- {
- unsigned int i;
- TCPInterface::Stop();
- for (i=0; i < waitingPackets.Size(); i++)
- DeallocatePacket(waitingPackets[i]);
- ClearAllConnections();
- }
- void PacketizedTCP::Send( const char *data, unsigned length, const SystemAddress &systemAddress, bool broadcast )
- {
- PTCPHeader dataLength;
- dataLength=length;
- #ifndef __BITSTREAM_NATIVE_END
- if (RakNet::BitStream::DoEndianSwap())
- RakNet::BitStream::ReverseBytes((unsigned char*) &length,(unsigned char*) &dataLength,sizeof(dataLength));
- #else
- dataLength=length;
- #endif
- unsigned int lengthsArray[2];
- const char *dataArray[2];
- dataArray[0]=(char*) &dataLength;
- dataArray[1]=data;
- lengthsArray[0]=sizeof(dataLength);
- lengthsArray[1]=length;
- TCPInterface::SendList(dataArray,lengthsArray,2,systemAddress,broadcast);
- }
- bool PacketizedTCP::SendList( const char **data, const unsigned int *lengths, const int numParameters, const SystemAddress &systemAddress, bool broadcast )
- {
- if (isStarted.GetValue()==0)
- return false;
- if (data==0)
- return false;
- if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS && broadcast==false)
- return false;
- PTCPHeader totalLengthOfUserData=0;
- int i;
- for (i=0; i < numParameters; i++)
- {
- if (lengths[i]>0)
- totalLengthOfUserData+=lengths[i];
- }
- if (totalLengthOfUserData==0)
- return false;
- PTCPHeader dataLength;
- #ifndef __BITSTREAM_NATIVE_END
- if (RakNet::BitStream::DoEndianSwap())
- RakNet::BitStream::ReverseBytes((unsigned char*) &totalLengthOfUserData,(unsigned char*) &dataLength,sizeof(dataLength));
- #else
- dataLength=totalLengthOfUserData;
- #endif
-
- unsigned int lengthsArray[512];
- const char *dataArray[512];
- dataArray[0]=(char*) &dataLength;
- lengthsArray[0]=sizeof(dataLength);
- for (int i=0; i < 512 && i < numParameters; i++)
- {
- dataArray[i+1]=data[i];
- lengthsArray[i+1]=lengths[i];
- }
- return TCPInterface::SendList(dataArray,lengthsArray,numParameters+1,systemAddress,broadcast);
- }
- void PacketizedTCP::PushNotificationsToQueues(void)
- {
- SystemAddress sa;
- sa = TCPInterface::HasNewIncomingConnection();
- if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
- {
- _newIncomingConnections.Push(sa, _FILE_AND_LINE_ );
- AddToConnectionList(sa);
- }
- sa = TCPInterface::HasFailedConnectionAttempt();
- if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
- {
- _failedConnectionAttempts.Push(sa, _FILE_AND_LINE_ );
- }
- sa = TCPInterface::HasLostConnection();
- if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
- {
- _lostConnections.Push(sa, _FILE_AND_LINE_ );
- RemoveFromConnectionList(sa);
- }
- sa = TCPInterface::HasCompletedConnectionAttempt();
- if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
- {
- _completedConnectionAttempts.Push(sa, _FILE_AND_LINE_ );
- AddToConnectionList(sa);
- }
- }
- Packet* PacketizedTCP::Receive( void )
- {
- PushNotificationsToQueues();
- unsigned int i;
- for (i=0; i < messageHandlerList.Size(); i++)
- messageHandlerList[i]->Update();
- Packet *outgoingPacket=ReturnOutgoingPacket();
- if (outgoingPacket)
- return outgoingPacket;
- Packet *incomingPacket;
- incomingPacket = TCPInterface::ReceiveInt();
- unsigned int index;
- while (incomingPacket)
- {
- if (connections.Has(incomingPacket->systemAddress))
- index = connections.GetIndexAtKey(incomingPacket->systemAddress);
- else
- index=(unsigned int) -1;
- if ((unsigned int)index==(unsigned int)-1)
- {
- DeallocatePacket(incomingPacket);
- incomingPacket = TCPInterface::ReceiveInt();
- continue;
- }
- if (incomingPacket->deleteData==true)
- {
- // Came from network
- SystemAddress systemAddressFromPacket;
- if (index < connections.Size())
- {
- DataStructures::ByteQueue *bq = connections[index];
- // Buffer data
- bq->WriteBytes((const char*) incomingPacket->data,incomingPacket->length, _FILE_AND_LINE_);
- systemAddressFromPacket=incomingPacket->systemAddress;
- PTCPHeader dataLength;
- // Peek the header to see if a full message is waiting
- bq->ReadBytes((char*) &dataLength,sizeof(PTCPHeader),true);
- if (RakNet::BitStream::DoEndianSwap())
- RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &dataLength,sizeof(dataLength));
- // Header indicates packet length. If enough data is available, read out and return one packet
- if (bq->GetBytesWritten()>=dataLength+sizeof(PTCPHeader))
- {
- do
- {
- bq->IncrementReadOffset(sizeof(PTCPHeader));
- outgoingPacket = RakNet::OP_NEW<Packet>(_FILE_AND_LINE_);
- outgoingPacket->length=dataLength;
- outgoingPacket->bitSize=BYTES_TO_BITS(dataLength);
- outgoingPacket->guid=UNASSIGNED_RAKNET_GUID;
- outgoingPacket->systemAddress=systemAddressFromPacket;
- outgoingPacket->deleteData=false; // Did not come from the network
- outgoingPacket->data=(unsigned char*) rakMalloc_Ex(dataLength, _FILE_AND_LINE_);
- if (outgoingPacket->data==0)
- {
- notifyOutOfMemory(_FILE_AND_LINE_);
- RakNet::OP_DELETE(outgoingPacket,_FILE_AND_LINE_);
- return 0;
- }
- bq->ReadBytes((char*) outgoingPacket->data,dataLength,false);
- waitingPackets.Push(outgoingPacket, _FILE_AND_LINE_ );
- // Peek the header to see if a full message is waiting
- if (bq->ReadBytes((char*) &dataLength,sizeof(PTCPHeader),true))
- {
- if (RakNet::BitStream::DoEndianSwap())
- RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &dataLength,sizeof(dataLength));
- }
- else
- break;
- } while (bq->GetBytesWritten()>=dataLength+sizeof(PTCPHeader));
- }
- else
- {
- unsigned int oldWritten = bq->GetBytesWritten()-incomingPacket->length;
- unsigned int newWritten = bq->GetBytesWritten();
- // Return ID_DOWNLOAD_PROGRESS
- if (newWritten/65536!=oldWritten/65536)
- {
- outgoingPacket = RakNet::OP_NEW<Packet>(_FILE_AND_LINE_);
- outgoingPacket->length=sizeof(MessageID) +
- sizeof(unsigned int)*2 +
- sizeof(unsigned int) +
- 65536;
- outgoingPacket->bitSize=BYTES_TO_BITS(incomingPacket->length);
- outgoingPacket->guid=UNASSIGNED_RAKNET_GUID;
- outgoingPacket->systemAddress=incomingPacket->systemAddress;
- outgoingPacket->deleteData=false;
- outgoingPacket->data=(unsigned char*) rakMalloc_Ex(outgoingPacket->length, _FILE_AND_LINE_);
- if (outgoingPacket->data==0)
- {
- notifyOutOfMemory(_FILE_AND_LINE_);
- RakNet::OP_DELETE(outgoingPacket,_FILE_AND_LINE_);
- return 0;
- }
- outgoingPacket->data[0]=(MessageID)ID_DOWNLOAD_PROGRESS;
- unsigned int totalParts=dataLength/65536;
- unsigned int partIndex=newWritten/65536;
- unsigned int oneChunkSize=65536;
- memcpy(outgoingPacket->data+sizeof(MessageID), &partIndex, sizeof(unsigned int));
- memcpy(outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*1, &totalParts, sizeof(unsigned int));
- memcpy(outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*2, &oneChunkSize, sizeof(unsigned int));
- bq->IncrementReadOffset(sizeof(PTCPHeader));
- bq->ReadBytes((char*) outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*3,oneChunkSize,true);
- bq->DecrementReadOffset(sizeof(PTCPHeader));
- waitingPackets.Push(outgoingPacket, _FILE_AND_LINE_ );
- }
- }
- }
- DeallocatePacket(incomingPacket);
- incomingPacket=0;
- }
- else
- waitingPackets.Push(incomingPacket, _FILE_AND_LINE_ );
- incomingPacket = TCPInterface::ReceiveInt();
- }
- return ReturnOutgoingPacket();
- }
- Packet *PacketizedTCP::ReturnOutgoingPacket(void)
- {
- Packet *outgoingPacket=0;
- unsigned int i;
- while (outgoingPacket==0 && waitingPackets.IsEmpty()==false)
- {
- outgoingPacket=waitingPackets.Pop();
- PluginReceiveResult pluginResult;
- for (i=0; i < messageHandlerList.Size(); i++)
- {
- pluginResult=messageHandlerList[i]->OnReceive(outgoingPacket);
- if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
- {
- DeallocatePacket( outgoingPacket );
- outgoingPacket=0; // Will do the loop again and get another packet
- break; // break out of the enclosing for
- }
- else if (pluginResult==RR_STOP_PROCESSING)
- {
- outgoingPacket=0;
- break;
- }
- }
- }
- return outgoingPacket;
- }
- void PacketizedTCP::CloseConnection( SystemAddress systemAddress )
- {
- RemoveFromConnectionList(systemAddress);
- TCPInterface::CloseConnection(systemAddress);
- }
- void PacketizedTCP::RemoveFromConnectionList(const SystemAddress &sa)
- {
- if (sa==UNASSIGNED_SYSTEM_ADDRESS)
- return;
- if (connections.Has(sa))
- {
- unsigned int index = connections.GetIndexAtKey(sa);
- if (index!=(unsigned int)-1)
- {
- RakNet::OP_DELETE(connections[index],_FILE_AND_LINE_);
- connections.RemoveAtIndex(index);
- }
- }
- }
- void PacketizedTCP::AddToConnectionList(const SystemAddress &sa)
- {
- if (sa==UNASSIGNED_SYSTEM_ADDRESS)
- return;
- connections.SetNew(sa, RakNet::OP_NEW<DataStructures::ByteQueue>(_FILE_AND_LINE_));
- }
- void PacketizedTCP::ClearAllConnections(void)
- {
- unsigned int i;
- for (i=0; i < connections.Size(); i++)
- RakNet::OP_DELETE(connections[i],_FILE_AND_LINE_);
- connections.Clear();
- }
- SystemAddress PacketizedTCP::HasCompletedConnectionAttempt(void)
- {
- PushNotificationsToQueues();
- if (_completedConnectionAttempts.IsEmpty()==false)
- return _completedConnectionAttempts.Pop();
- return UNASSIGNED_SYSTEM_ADDRESS;
- }
- SystemAddress PacketizedTCP::HasFailedConnectionAttempt(void)
- {
- PushNotificationsToQueues();
- if (_failedConnectionAttempts.IsEmpty()==false)
- return _failedConnectionAttempts.Pop();
- return UNASSIGNED_SYSTEM_ADDRESS;
- }
- SystemAddress PacketizedTCP::HasNewIncomingConnection(void)
- {
- PushNotificationsToQueues();
- if (_newIncomingConnections.IsEmpty()==false)
- return _newIncomingConnections.Pop();
- return UNASSIGNED_SYSTEM_ADDRESS;
- }
- SystemAddress PacketizedTCP::HasLostConnection(void)
- {
- PushNotificationsToQueues();
- if (_lostConnections.IsEmpty()==false)
- return _lostConnections.Pop();
- return UNASSIGNED_SYSTEM_ADDRESS;
- }
- #endif // _RAKNET_SUPPORT_*
|