SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PacketizedTCP.cpp
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2018, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
16 #include "slikenet/NativeFeatureIncludes.h"
17 #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
18
19 #include <algorithm> // used for std::min
20 #include "slikenet/PacketizedTCP.h"
21 #include "slikenet/NativeTypes.h"
22 #include "slikenet/BitStream.h"
23 #include "slikenet/MessageIdentifiers.h"
24 #include "slikenet/alloca.h"
25
26 using namespace SLNet;
27
28 typedef uint32_t PTCPHeader;
29
30 STATIC_FACTORY_DEFINITIONS(PacketizedTCP,PacketizedTCP);
31
32 PacketizedTCP::PacketizedTCP()
33 {
34
35 }
36 PacketizedTCP::~PacketizedTCP()
37 {
38 ClearAllConnections();
39 }
40
41 void PacketizedTCP::Stop(void)
42 {
43 unsigned int i;
44 TCPInterface::Stop();
45 for (i=0; i < waitingPackets.Size(); i++)
46 DeallocatePacket(waitingPackets[i]);
47 ClearAllConnections();
48 }
49
50 void PacketizedTCP::Send( const char *data, unsigned length, const SystemAddress &systemAddress, bool broadcast )
51 {
52 PTCPHeader dataLength;
53 dataLength=length;
54 #ifndef __BITSTREAM_NATIVE_END
55 if (SLNet::BitStream::DoEndianSwap())
56 SLNet::BitStream::ReverseBytes((unsigned char*) &length,(unsigned char*) &dataLength,sizeof(dataLength));
57 #else
58 dataLength=length;
59 #endif
60
61 unsigned int lengthsArray[2];
62 const char *dataArray[2];
63 dataArray[0]=(char*) &dataLength;
64 dataArray[1]=data;
65 lengthsArray[0]=sizeof(dataLength);
66 lengthsArray[1]=length;
67 TCPInterface::SendList(dataArray,lengthsArray,2,systemAddress,broadcast);
68 }
69 bool PacketizedTCP::SendList( const char **data, const unsigned int *lengths, const int numParameters, const SystemAddress &systemAddress, bool broadcast )
70 {
71 if (isStarted.GetValue()==0)
72 return false;
73 if (data==0)
74 return false;
75 if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS && broadcast==false)
76 return false;
77 PTCPHeader totalLengthOfUserData=0;
78 int i;
79 for (i=0; i < numParameters; i++)
80 {
81 if (lengths[i]>0)
82 totalLengthOfUserData+=lengths[i];
83 }
84 if (totalLengthOfUserData==0)
85 return false;
86
87 PTCPHeader dataLength;
88 #ifndef __BITSTREAM_NATIVE_END
89 if (SLNet::BitStream::DoEndianSwap())
90 SLNet::BitStream::ReverseBytes((unsigned char*) &totalLengthOfUserData,(unsigned char*) &dataLength,sizeof(dataLength));
91 #else
92 dataLength=totalLengthOfUserData;
93 #endif
94
95
96 unsigned int lengthsArray[513];
97 const char *dataArray[513];
98 dataArray[0]=(char*) &dataLength;
99 lengthsArray[0]=sizeof(dataLength);
100 for (i=0; i < 512 && i < numParameters; i++)
101 {
102 dataArray[i+1]=data[i];
103 lengthsArray[i+1]=lengths[i];
104 }
105 return TCPInterface::SendList(dataArray,lengthsArray,std::min(numParameters, 511)+1,systemAddress,broadcast);
106 }
107 void PacketizedTCP::PushNotificationsToQueues(void)
108 {
109 SystemAddress sa;
110 sa = TCPInterface::HasNewIncomingConnection();
111 if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
112 {
113 _newIncomingConnections.Push(sa, _FILE_AND_LINE_ );
114 AddToConnectionList(sa);
115 }
116
117 sa = TCPInterface::HasFailedConnectionAttempt();
118 if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
119 {
120 _failedConnectionAttempts.Push(sa, _FILE_AND_LINE_ );
121 }
122
123 sa = TCPInterface::HasLostConnection();
124 if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
125 {
126 _lostConnections.Push(sa, _FILE_AND_LINE_ );
127 RemoveFromConnectionList(sa);
128 }
129
130 sa = TCPInterface::HasCompletedConnectionAttempt();
131 if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
132 {
133 _completedConnectionAttempts.Push(sa, _FILE_AND_LINE_ );
134 AddToConnectionList(sa);
135 }
136 }
137 Packet* PacketizedTCP::Receive( void )
138 {
139 PushNotificationsToQueues();
140
141 unsigned int i;
142 for (i=0; i < messageHandlerList.Size(); i++)
143 messageHandlerList[i]->Update();
144
145 Packet *outgoingPacket=ReturnOutgoingPacket();
146 if (outgoingPacket)
147 return outgoingPacket;
148
149 Packet *incomingPacket;
150 incomingPacket = TCPInterface::ReceiveInt();
151 unsigned int index;
152
153 while (incomingPacket)
154 {
155 if (connections.Has(incomingPacket->systemAddress))
156 index = connections.GetIndexAtKey(incomingPacket->systemAddress);
157 else
158 index=(unsigned int) -1;
159 if ((unsigned int)index==(unsigned int)-1)
160 {
161 DeallocatePacket(incomingPacket);
162 incomingPacket = TCPInterface::ReceiveInt();
163 continue;
164 }
165
166
167 if (incomingPacket->deleteData==true)
168 {
169 // Came from network
170 SystemAddress systemAddressFromPacket;
171 if (index < connections.Size())
172 {
173 DataStructures::ByteQueue *bq = connections[index];
174 // Buffer data
175 bq->WriteBytes((const char*) incomingPacket->data,incomingPacket->length, _FILE_AND_LINE_);
176 systemAddressFromPacket=incomingPacket->systemAddress;
177 PTCPHeader dataLength;
178
179 // Peek the header to see if a full message is waiting
180 bq->ReadBytes((char*) &dataLength,sizeof(PTCPHeader),true);
181 if (SLNet::BitStream::DoEndianSwap())
182 SLNet::BitStream::ReverseBytesInPlace((unsigned char*) &dataLength,sizeof(dataLength));
183 // Header indicates packet length. If enough data is available, read out and return one packet
184 if (bq->GetBytesWritten()>=dataLength+sizeof(PTCPHeader))
185 {
186 do
187 {
188 bq->IncrementReadOffset(sizeof(PTCPHeader));
189 outgoingPacket = SLNet::OP_NEW<Packet>(_FILE_AND_LINE_);
190 outgoingPacket->length=dataLength;
191 outgoingPacket->bitSize=BYTES_TO_BITS(dataLength);
192 outgoingPacket->guid=UNASSIGNED_RAKNET_GUID;
193 outgoingPacket->systemAddress=systemAddressFromPacket;
194 outgoingPacket->deleteData=false; // Did not come from the network
195 outgoingPacket->data=(unsigned char*) rakMalloc_Ex(dataLength, _FILE_AND_LINE_);
196 if (outgoingPacket->data==0)
197 {
198 notifyOutOfMemory(_FILE_AND_LINE_);
199 SLNet::OP_DELETE(outgoingPacket,_FILE_AND_LINE_);
200 return 0;
201 }
202 bq->ReadBytes((char*) outgoingPacket->data,dataLength,false);
203
204 waitingPackets.Push(outgoingPacket, _FILE_AND_LINE_ );
205
206 // Peek the header to see if a full message is waiting
207 if (bq->ReadBytes((char*) &dataLength,sizeof(PTCPHeader),true))
208 {
209 if (SLNet::BitStream::DoEndianSwap())
210 SLNet::BitStream::ReverseBytesInPlace((unsigned char*) &dataLength,sizeof(dataLength));
211 }
212 else
213 break;
214 } while (bq->GetBytesWritten()>=dataLength+sizeof(PTCPHeader));
215 }
216 else
217 {
218
219 unsigned int oldWritten = bq->GetBytesWritten()-incomingPacket->length;
220 unsigned int newWritten = bq->GetBytesWritten();
221
222 // Return ID_DOWNLOAD_PROGRESS
223 if (newWritten/65536!=oldWritten/65536)
224 {
225 outgoingPacket = SLNet::OP_NEW<Packet>(_FILE_AND_LINE_);
226 outgoingPacket->length=sizeof(MessageID) +
227 sizeof(unsigned int)*2 +
228 sizeof(unsigned int) +
229 65536;
230 outgoingPacket->bitSize=BYTES_TO_BITS(incomingPacket->length);
231 outgoingPacket->guid=UNASSIGNED_RAKNET_GUID;
232 outgoingPacket->systemAddress=incomingPacket->systemAddress;
233 outgoingPacket->deleteData=false;
234 outgoingPacket->data=(unsigned char*) rakMalloc_Ex(outgoingPacket->length, _FILE_AND_LINE_);
235 if (outgoingPacket->data==0)
236 {
237 notifyOutOfMemory(_FILE_AND_LINE_);
238 SLNet::OP_DELETE(outgoingPacket,_FILE_AND_LINE_);
239 return 0;
240 }
241
242 outgoingPacket->data[0]=(MessageID)ID_DOWNLOAD_PROGRESS;
243 unsigned int totalParts=dataLength/65536;
244 unsigned int partIndex=newWritten/65536;
245 unsigned int oneChunkSize=65536;
246 memcpy(outgoingPacket->data+sizeof(MessageID), &partIndex, sizeof(unsigned int));
247 memcpy(outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*1, &totalParts, sizeof(unsigned int));
248 memcpy(outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*2, &oneChunkSize, sizeof(unsigned int));
249 bq->IncrementReadOffset(sizeof(PTCPHeader));
250 bq->ReadBytes((char*) outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*3,oneChunkSize,true);
251 bq->DecrementReadOffset(sizeof(PTCPHeader));
252
253 waitingPackets.Push(outgoingPacket, _FILE_AND_LINE_ );
254 }
255 }
256
257 }
258
259 DeallocatePacket(incomingPacket);
260 incomingPacket=0;
261 }
262 else
263 waitingPackets.Push(incomingPacket, _FILE_AND_LINE_ );
264
265 incomingPacket = TCPInterface::ReceiveInt();
266 }
267
268 return ReturnOutgoingPacket();
269 }
270 Packet *PacketizedTCP::ReturnOutgoingPacket(void)
271 {
272 Packet *outgoingPacket=0;
273 unsigned int i;
274 while (outgoingPacket==0 && waitingPackets.IsEmpty()==false)
275 {
276 outgoingPacket=waitingPackets.Pop();
277 PluginReceiveResult pluginResult;
278 for (i=0; i < messageHandlerList.Size(); i++)
279 {
280 pluginResult=messageHandlerList[i]->OnReceive(outgoingPacket);
281 if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
282 {
283 DeallocatePacket( outgoingPacket );
284 outgoingPacket=0; // Will do the loop again and get another packet
285 break; // break out of the enclosing for
286 }
287 else if (pluginResult==RR_STOP_PROCESSING)
288 {
289 outgoingPacket=0;
290 break;
291 }
292 }
293 }
294
295 return outgoingPacket;
296 }
297 void PacketizedTCP::CloseConnection( SystemAddress systemAddress )
298 {
299 RemoveFromConnectionList(systemAddress);
300 TCPInterface::CloseConnection(systemAddress);
301 }
302 void PacketizedTCP::RemoveFromConnectionList(const SystemAddress &sa)
303 {
304 if (sa==UNASSIGNED_SYSTEM_ADDRESS)
305 return;
306 if (connections.Has(sa))
307 {
308 unsigned int index = connections.GetIndexAtKey(sa);
309 if (index!=(unsigned int)-1)
310 {
311 SLNet::OP_DELETE(connections[index],_FILE_AND_LINE_);
312 connections.RemoveAtIndex(index);
313 }
314 }
315 }
316 void PacketizedTCP::AddToConnectionList(const SystemAddress &sa)
317 {
318 if (sa==UNASSIGNED_SYSTEM_ADDRESS)
319 return;
320 connections.SetNew(sa, SLNet::OP_NEW<DataStructures::ByteQueue>(_FILE_AND_LINE_));
321 }
322 void PacketizedTCP::ClearAllConnections(void)
323 {
324 unsigned int i;
325 for (i=0; i < connections.Size(); i++)
326 SLNet::OP_DELETE(connections[i],_FILE_AND_LINE_);
327 connections.Clear();
328 }
329 SystemAddress PacketizedTCP::HasCompletedConnectionAttempt(void)
330 {
331 PushNotificationsToQueues();
332
333 if (_completedConnectionAttempts.IsEmpty()==false)
334 return _completedConnectionAttempts.Pop();
335 return UNASSIGNED_SYSTEM_ADDRESS;
336 }
337 SystemAddress PacketizedTCP::HasFailedConnectionAttempt(void)
338 {
339 PushNotificationsToQueues();
340
341 if (_failedConnectionAttempts.IsEmpty()==false)
342 return _failedConnectionAttempts.Pop();
343 return UNASSIGNED_SYSTEM_ADDRESS;
344 }
345 SystemAddress PacketizedTCP::HasNewIncomingConnection(void)
346 {
347 PushNotificationsToQueues();
348
349 if (_newIncomingConnections.IsEmpty()==false)
350 return _newIncomingConnections.Pop();
351 return UNASSIGNED_SYSTEM_ADDRESS;
352 }
353 SystemAddress PacketizedTCP::HasLostConnection(void)
354 {
355 PushNotificationsToQueues();
356
357 if (_lostConnections.IsEmpty()==false)
358 return _lostConnections.Pop();
359 return UNASSIGNED_SYSTEM_ADDRESS;
360 }
361
362 #endif // _RAKNET_SUPPORT_*