rev |
line source |
nuclear@0
|
1 /************************************************************************************
|
nuclear@0
|
2
|
nuclear@0
|
3 Filename : OVR_PacketizedTCPSocket.cpp
|
nuclear@0
|
4 Content : TCP with automated message framing.
|
nuclear@0
|
5 Created : June 10, 2014
|
nuclear@0
|
6 Authors : Kevin Jenkins
|
nuclear@0
|
7
|
nuclear@0
|
8 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
|
nuclear@0
|
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
|
nuclear@0
|
12 which is provided at the time of installation or download, or which
|
nuclear@0
|
13 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@0
|
14
|
nuclear@0
|
15 You may obtain a copy of the License at
|
nuclear@0
|
16
|
nuclear@0
|
17 http://www.oculusvr.com/licenses/LICENSE-3.2
|
nuclear@0
|
18
|
nuclear@0
|
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
|
nuclear@0
|
20 distributed under the License is distributed on an "AS IS" BASIS,
|
nuclear@0
|
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
nuclear@0
|
22 See the License for the specific language governing permissions and
|
nuclear@0
|
23 limitations under the License.
|
nuclear@0
|
24
|
nuclear@0
|
25 ************************************************************************************/
|
nuclear@0
|
26
|
nuclear@0
|
27 #include "OVR_PacketizedTCPSocket.h"
|
nuclear@0
|
28
|
nuclear@0
|
29 namespace OVR { namespace Net {
|
nuclear@0
|
30
|
nuclear@0
|
31
|
nuclear@0
|
32 //-----------------------------------------------------------------------------
|
nuclear@0
|
33 // Constants
|
nuclear@0
|
34
|
nuclear@0
|
35 static const int LENGTH_FIELD_BYTES = 4;
|
nuclear@0
|
36
|
nuclear@0
|
37
|
nuclear@0
|
38 //-----------------------------------------------------------------------------
|
nuclear@0
|
39 // PacketizedTCPSocket
|
nuclear@0
|
40
|
nuclear@0
|
41 PacketizedTCPSocket::PacketizedTCPSocket()
|
nuclear@0
|
42 {
|
nuclear@0
|
43 pRecvBuff = 0;
|
nuclear@0
|
44 pRecvBuffSize = 0;
|
nuclear@0
|
45 Transport = TransportType_PacketizedTCP;
|
nuclear@0
|
46 }
|
nuclear@0
|
47
|
nuclear@0
|
48 PacketizedTCPSocket::PacketizedTCPSocket(SocketHandle _sock, bool isListenSocket) : PacketizedTCPSocketBase(_sock, isListenSocket)
|
nuclear@0
|
49 {
|
nuclear@0
|
50 pRecvBuff = 0;
|
nuclear@0
|
51 pRecvBuffSize = 0;
|
nuclear@0
|
52 Transport = TransportType_PacketizedTCP;
|
nuclear@0
|
53 }
|
nuclear@0
|
54
|
nuclear@0
|
55 PacketizedTCPSocket::~PacketizedTCPSocket()
|
nuclear@0
|
56 {
|
nuclear@0
|
57 OVR_FREE(pRecvBuff);
|
nuclear@0
|
58 }
|
nuclear@0
|
59
|
nuclear@0
|
60 int PacketizedTCPSocket::Send(const void* pData, int bytes)
|
nuclear@0
|
61 {
|
nuclear@0
|
62 Lock::Locker locker(&sendLock);
|
nuclear@0
|
63
|
nuclear@0
|
64 if (bytes <= 0)
|
nuclear@0
|
65 {
|
nuclear@0
|
66 return -1;
|
nuclear@0
|
67 }
|
nuclear@0
|
68
|
nuclear@0
|
69 // Convert length to 4 endian-neutral bytes
|
nuclear@0
|
70 uint32_t lengthWord = bytes;
|
nuclear@0
|
71 uint8_t lengthBytes[LENGTH_FIELD_BYTES] = {
|
nuclear@0
|
72 (uint8_t)lengthWord,
|
nuclear@0
|
73 (uint8_t)(lengthWord >> 8),
|
nuclear@0
|
74 (uint8_t)(lengthWord >> 16),
|
nuclear@0
|
75 (uint8_t)(lengthWord >> 24)
|
nuclear@0
|
76 };
|
nuclear@0
|
77
|
nuclear@0
|
78 int s = PacketizedTCPSocketBase::Send(lengthBytes, LENGTH_FIELD_BYTES);
|
nuclear@0
|
79 if (s > 0)
|
nuclear@0
|
80 {
|
nuclear@0
|
81 return PacketizedTCPSocketBase::Send(pData,bytes);
|
nuclear@0
|
82 }
|
nuclear@0
|
83 else
|
nuclear@0
|
84 {
|
nuclear@0
|
85 return s;
|
nuclear@0
|
86 }
|
nuclear@0
|
87 }
|
nuclear@0
|
88
|
nuclear@0
|
89 int PacketizedTCPSocket::SendAndConcatenate(const void** pDataArray, int* dataLengthArray, int arrayCount)
|
nuclear@0
|
90 {
|
nuclear@0
|
91 Lock::Locker locker(&sendLock);
|
nuclear@0
|
92
|
nuclear@0
|
93 if (arrayCount == 0)
|
nuclear@0
|
94 return 0;
|
nuclear@0
|
95
|
nuclear@0
|
96 int totalBytes = 0;
|
nuclear@0
|
97 for (int i = 0; i < arrayCount; i++)
|
nuclear@0
|
98 totalBytes += dataLengthArray[i];
|
nuclear@0
|
99
|
nuclear@0
|
100 // Convert length to 4 endian-neutral bytes
|
nuclear@0
|
101 uint32_t lengthWord = totalBytes;
|
nuclear@0
|
102 uint8_t lengthBytes[LENGTH_FIELD_BYTES] = {
|
nuclear@0
|
103 (uint8_t)lengthWord,
|
nuclear@0
|
104 (uint8_t)(lengthWord >> 8),
|
nuclear@0
|
105 (uint8_t)(lengthWord >> 16),
|
nuclear@0
|
106 (uint8_t)(lengthWord >> 24)
|
nuclear@0
|
107 };
|
nuclear@0
|
108
|
nuclear@0
|
109 int s = PacketizedTCPSocketBase::Send(lengthBytes, LENGTH_FIELD_BYTES);
|
nuclear@0
|
110 if (s > 0)
|
nuclear@0
|
111 {
|
nuclear@0
|
112 for (int i = 0; i < arrayCount; i++)
|
nuclear@0
|
113 {
|
nuclear@0
|
114 PacketizedTCPSocketBase::Send(pDataArray[i], dataLengthArray[i]);
|
nuclear@0
|
115 }
|
nuclear@0
|
116 }
|
nuclear@0
|
117
|
nuclear@0
|
118 return s;
|
nuclear@0
|
119 }
|
nuclear@0
|
120
|
nuclear@0
|
121 void PacketizedTCPSocket::OnRecv(SocketEvent_TCP* eventHandler, uint8_t* pData, int bytesRead)
|
nuclear@0
|
122 {
|
nuclear@0
|
123 uint8_t* dataSource = NULL;
|
nuclear@0
|
124 int dataSourceSize = 0;
|
nuclear@0
|
125
|
nuclear@0
|
126 recvBuffLock.DoLock();
|
nuclear@0
|
127
|
nuclear@0
|
128 if (pRecvBuff == NULL)
|
nuclear@0
|
129 {
|
nuclear@0
|
130 dataSource = pData;
|
nuclear@0
|
131 dataSourceSize = bytesRead;
|
nuclear@0
|
132 }
|
nuclear@0
|
133 else
|
nuclear@0
|
134 {
|
nuclear@0
|
135 uint8_t* pRecvBuffNew = (uint8_t*)OVR_REALLOC(pRecvBuff, bytesRead + pRecvBuffSize);
|
nuclear@0
|
136 if (!pRecvBuffNew)
|
nuclear@0
|
137 {
|
nuclear@0
|
138 OVR_FREE(pRecvBuff);
|
nuclear@0
|
139 pRecvBuff = NULL;
|
nuclear@0
|
140 pRecvBuffSize = 0;
|
nuclear@0
|
141 recvBuffLock.Unlock();
|
nuclear@0
|
142 return;
|
nuclear@0
|
143 }
|
nuclear@0
|
144 else
|
nuclear@0
|
145 {
|
nuclear@0
|
146 pRecvBuff = pRecvBuffNew;
|
nuclear@0
|
147
|
nuclear@0
|
148 memcpy(pRecvBuff + pRecvBuffSize, pData, bytesRead);
|
nuclear@0
|
149
|
nuclear@0
|
150 dataSourceSize = pRecvBuffSize + bytesRead;
|
nuclear@0
|
151 dataSource = pRecvBuff;
|
nuclear@0
|
152 }
|
nuclear@0
|
153 }
|
nuclear@0
|
154
|
nuclear@0
|
155 int bytesReadFromStream;
|
nuclear@0
|
156 while (bytesReadFromStream = BytesFromStream(dataSource, dataSourceSize),
|
nuclear@0
|
157 LENGTH_FIELD_BYTES + bytesReadFromStream <= dataSourceSize)
|
nuclear@0
|
158 {
|
nuclear@0
|
159 dataSource += LENGTH_FIELD_BYTES;
|
nuclear@0
|
160 dataSourceSize -= LENGTH_FIELD_BYTES;
|
nuclear@0
|
161
|
nuclear@0
|
162 TCPSocket::OnRecv(eventHandler, dataSource, bytesReadFromStream);
|
nuclear@0
|
163
|
nuclear@0
|
164 dataSource += bytesReadFromStream;
|
nuclear@0
|
165 dataSourceSize -= bytesReadFromStream;
|
nuclear@0
|
166 }
|
nuclear@0
|
167
|
nuclear@0
|
168 if (dataSourceSize > 0)
|
nuclear@0
|
169 {
|
nuclear@0
|
170 if (dataSource != NULL)
|
nuclear@0
|
171 {
|
nuclear@0
|
172 if (pRecvBuff == NULL)
|
nuclear@0
|
173 {
|
nuclear@0
|
174 pRecvBuff = (uint8_t*)OVR_ALLOC(dataSourceSize);
|
nuclear@0
|
175 if (!pRecvBuff)
|
nuclear@0
|
176 {
|
nuclear@0
|
177 pRecvBuffSize = 0;
|
nuclear@0
|
178 recvBuffLock.Unlock();
|
nuclear@0
|
179 return;
|
nuclear@0
|
180 }
|
nuclear@0
|
181 else
|
nuclear@0
|
182 {
|
nuclear@0
|
183 memcpy(pRecvBuff, dataSource, dataSourceSize);
|
nuclear@0
|
184 }
|
nuclear@0
|
185 }
|
nuclear@0
|
186 else
|
nuclear@0
|
187 {
|
nuclear@0
|
188 memmove(pRecvBuff, dataSource, dataSourceSize);
|
nuclear@0
|
189 }
|
nuclear@0
|
190 }
|
nuclear@0
|
191 }
|
nuclear@0
|
192 else
|
nuclear@0
|
193 {
|
nuclear@0
|
194 if (pRecvBuff != NULL)
|
nuclear@0
|
195 OVR_FREE(pRecvBuff);
|
nuclear@0
|
196
|
nuclear@0
|
197 pRecvBuff = NULL;
|
nuclear@0
|
198 }
|
nuclear@0
|
199 pRecvBuffSize = dataSourceSize;
|
nuclear@0
|
200
|
nuclear@0
|
201 recvBuffLock.Unlock();
|
nuclear@0
|
202 }
|
nuclear@0
|
203
|
nuclear@0
|
204 int PacketizedTCPSocket::BytesFromStream(uint8_t* pData, int bytesRead)
|
nuclear@0
|
205 {
|
nuclear@0
|
206 if (pData != 0 && bytesRead >= LENGTH_FIELD_BYTES)
|
nuclear@0
|
207 {
|
nuclear@0
|
208 return pData[0] | ((uint32_t)pData[1] << 8) | ((uint32_t)pData[2] << 16) | ((uint32_t)pData[3] << 24);
|
nuclear@0
|
209 }
|
nuclear@0
|
210
|
nuclear@0
|
211 return 0;
|
nuclear@0
|
212 }
|
nuclear@0
|
213
|
nuclear@0
|
214
|
nuclear@0
|
215 }} // OVR::Net
|