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