nuclear@0: /************************************************************************************ nuclear@0: nuclear@0: Filename : OVR_PacketizedTCPSocket.cpp nuclear@0: Content : TCP with automated message framing. nuclear@0: Created : June 10, 2014 nuclear@0: Authors : Kevin Jenkins nuclear@0: nuclear@0: Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. nuclear@0: nuclear@0: Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); nuclear@0: you may not use the Oculus VR Rift SDK except in compliance with the License, nuclear@0: which is provided at the time of installation or download, or which nuclear@0: otherwise accompanies this software in either electronic or hard copy form. nuclear@0: nuclear@0: You may obtain a copy of the License at nuclear@0: nuclear@0: http://www.oculusvr.com/licenses/LICENSE-3.2 nuclear@0: nuclear@0: Unless required by applicable law or agreed to in writing, the Oculus VR SDK nuclear@0: distributed under the License is distributed on an "AS IS" BASIS, nuclear@0: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. nuclear@0: See the License for the specific language governing permissions and nuclear@0: limitations under the License. nuclear@0: nuclear@0: ************************************************************************************/ nuclear@0: nuclear@0: #include "OVR_PacketizedTCPSocket.h" nuclear@0: nuclear@0: namespace OVR { namespace Net { nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------- nuclear@0: // Constants nuclear@0: nuclear@0: static const int LENGTH_FIELD_BYTES = 4; nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------- nuclear@0: // PacketizedTCPSocket nuclear@0: nuclear@0: PacketizedTCPSocket::PacketizedTCPSocket() nuclear@0: { nuclear@0: pRecvBuff = 0; nuclear@0: pRecvBuffSize = 0; nuclear@0: Transport = TransportType_PacketizedTCP; nuclear@0: } nuclear@0: nuclear@0: PacketizedTCPSocket::PacketizedTCPSocket(SocketHandle _sock, bool isListenSocket) : PacketizedTCPSocketBase(_sock, isListenSocket) nuclear@0: { nuclear@0: pRecvBuff = 0; nuclear@0: pRecvBuffSize = 0; nuclear@0: Transport = TransportType_PacketizedTCP; nuclear@0: } nuclear@0: nuclear@0: PacketizedTCPSocket::~PacketizedTCPSocket() nuclear@0: { nuclear@0: OVR_FREE(pRecvBuff); nuclear@0: } nuclear@0: nuclear@0: int PacketizedTCPSocket::Send(const void* pData, int bytes) nuclear@0: { nuclear@0: Lock::Locker locker(&sendLock); nuclear@0: nuclear@0: if (bytes <= 0) nuclear@0: { nuclear@0: return -1; nuclear@0: } nuclear@0: nuclear@0: // Convert length to 4 endian-neutral bytes nuclear@0: uint32_t lengthWord = bytes; nuclear@0: uint8_t lengthBytes[LENGTH_FIELD_BYTES] = { nuclear@0: (uint8_t)lengthWord, nuclear@0: (uint8_t)(lengthWord >> 8), nuclear@0: (uint8_t)(lengthWord >> 16), nuclear@0: (uint8_t)(lengthWord >> 24) nuclear@0: }; nuclear@0: nuclear@0: int s = PacketizedTCPSocketBase::Send(lengthBytes, LENGTH_FIELD_BYTES); nuclear@0: if (s > 0) nuclear@0: { nuclear@0: return PacketizedTCPSocketBase::Send(pData,bytes); nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: return s; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: int PacketizedTCPSocket::SendAndConcatenate(const void** pDataArray, int* dataLengthArray, int arrayCount) nuclear@0: { nuclear@0: Lock::Locker locker(&sendLock); nuclear@0: nuclear@0: if (arrayCount == 0) nuclear@0: return 0; nuclear@0: nuclear@0: int totalBytes = 0; nuclear@0: for (int i = 0; i < arrayCount; i++) nuclear@0: totalBytes += dataLengthArray[i]; nuclear@0: nuclear@0: // Convert length to 4 endian-neutral bytes nuclear@0: uint32_t lengthWord = totalBytes; nuclear@0: uint8_t lengthBytes[LENGTH_FIELD_BYTES] = { nuclear@0: (uint8_t)lengthWord, nuclear@0: (uint8_t)(lengthWord >> 8), nuclear@0: (uint8_t)(lengthWord >> 16), nuclear@0: (uint8_t)(lengthWord >> 24) nuclear@0: }; nuclear@0: nuclear@0: int s = PacketizedTCPSocketBase::Send(lengthBytes, LENGTH_FIELD_BYTES); nuclear@0: if (s > 0) nuclear@0: { nuclear@0: for (int i = 0; i < arrayCount; i++) nuclear@0: { nuclear@0: PacketizedTCPSocketBase::Send(pDataArray[i], dataLengthArray[i]); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: return s; nuclear@0: } nuclear@0: nuclear@0: void PacketizedTCPSocket::OnRecv(SocketEvent_TCP* eventHandler, uint8_t* pData, int bytesRead) nuclear@0: { nuclear@0: uint8_t* dataSource = NULL; nuclear@0: int dataSourceSize = 0; nuclear@0: nuclear@0: recvBuffLock.DoLock(); nuclear@0: nuclear@0: if (pRecvBuff == NULL) nuclear@0: { nuclear@0: dataSource = pData; nuclear@0: dataSourceSize = bytesRead; nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: uint8_t* pRecvBuffNew = (uint8_t*)OVR_REALLOC(pRecvBuff, bytesRead + pRecvBuffSize); nuclear@0: if (!pRecvBuffNew) nuclear@0: { nuclear@0: OVR_FREE(pRecvBuff); nuclear@0: pRecvBuff = NULL; nuclear@0: pRecvBuffSize = 0; nuclear@0: recvBuffLock.Unlock(); nuclear@0: return; nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: pRecvBuff = pRecvBuffNew; nuclear@0: nuclear@0: memcpy(pRecvBuff + pRecvBuffSize, pData, bytesRead); nuclear@0: nuclear@0: dataSourceSize = pRecvBuffSize + bytesRead; nuclear@0: dataSource = pRecvBuff; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: int bytesReadFromStream; nuclear@0: while (bytesReadFromStream = BytesFromStream(dataSource, dataSourceSize), nuclear@0: LENGTH_FIELD_BYTES + bytesReadFromStream <= dataSourceSize) nuclear@0: { nuclear@0: dataSource += LENGTH_FIELD_BYTES; nuclear@0: dataSourceSize -= LENGTH_FIELD_BYTES; nuclear@0: nuclear@0: TCPSocket::OnRecv(eventHandler, dataSource, bytesReadFromStream); nuclear@0: nuclear@0: dataSource += bytesReadFromStream; nuclear@0: dataSourceSize -= bytesReadFromStream; nuclear@0: } nuclear@0: nuclear@0: if (dataSourceSize > 0) nuclear@0: { nuclear@0: if (dataSource != NULL) nuclear@0: { nuclear@0: if (pRecvBuff == NULL) nuclear@0: { nuclear@0: pRecvBuff = (uint8_t*)OVR_ALLOC(dataSourceSize); nuclear@0: if (!pRecvBuff) nuclear@0: { nuclear@0: pRecvBuffSize = 0; nuclear@0: recvBuffLock.Unlock(); nuclear@0: return; nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: memcpy(pRecvBuff, dataSource, dataSourceSize); nuclear@0: } nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: memmove(pRecvBuff, dataSource, dataSourceSize); nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: if (pRecvBuff != NULL) nuclear@0: OVR_FREE(pRecvBuff); nuclear@0: nuclear@0: pRecvBuff = NULL; nuclear@0: } nuclear@0: pRecvBuffSize = dataSourceSize; nuclear@0: nuclear@0: recvBuffLock.Unlock(); nuclear@0: } nuclear@0: nuclear@0: int PacketizedTCPSocket::BytesFromStream(uint8_t* pData, int bytesRead) nuclear@0: { nuclear@0: if (pData != 0 && bytesRead >= LENGTH_FIELD_BYTES) nuclear@0: { nuclear@0: return pData[0] | ((uint32_t)pData[1] << 8) | ((uint32_t)pData[2] << 16) | ((uint32_t)pData[3] << 24); nuclear@0: } nuclear@0: nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: nuclear@0: }} // OVR::Net