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
TCPInterface.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_TCPInterface==1
18
22
23
24
25 #include "slikenet/TCPInterface.h"
26 #ifdef _WIN32
27 #if !defined (WINDOWS_STORE_RT)
28 typedef int socklen_t;
29 #endif
30
31
32 #else
33 #include <sys/time.h>
34 #include <unistd.h>
35 #include <pthread.h>
36 #endif
37 #include <string.h>
38 #include "slikenet/assert.h"
39 #include <stdio.h>
40 #include "slikenet/assert.h"
41 #include "slikenet/sleep.h"
42 #include "slikenet/StringCompressor.h"
43 #include "slikenet/StringTable.h"
44 #include "slikenet/Itoa.h"
45 #include "slikenet/SocketLayer.h"
46 #include "slikenet/SocketDefines.h"
47 #if (defined(__GNUC__) || defined(__GCCXML__)) && !defined(__WIN32__)
48 #include <netdb.h>
49 #endif
50
51 #ifdef _DO_PRINTF
52 #endif
53
54 #ifdef _WIN32
55 #include "slikenet/WSAStartupSingleton.h"
56 #endif
57 namespace SLNet
58 {
59 RAK_THREAD_DECLARATION(UpdateTCPInterfaceLoop);
60 RAK_THREAD_DECLARATION(ConnectionAttemptLoop);
61 }
62 #ifdef _MSC_VER
63 #pragma warning( push )
64 #endif
65 #include "slikenet/linux_adapter.h"
66 #include "slikenet/osx_adapter.h"
67
68 using namespace SLNet;
69
70 STATIC_FACTORY_DEFINITIONS(TCPInterface,TCPInterface);
71
72 TCPInterface::TCPInterface()
73 {
74 #if !defined(WINDOWS_STORE_RT)
75 listenSocket=0;
76 #endif
77 remoteClients=0;
78 remoteClientsLength=0;
79
80 StringCompressor::AddReference();
81 SLNet::StringTable::AddReference();
82
83 #if OPEN_SSL_CLIENT_SUPPORT==1
84 ctx=0;
85 meth=0;
86 #endif
87
88 #ifdef _WIN32
89 WSAStartupSingleton::AddRef();
90 #endif
91 }
92 TCPInterface::~TCPInterface()
93 {
94 Stop();
95 #ifdef _WIN32
96 WSAStartupSingleton::Deref();
97 #endif
98
99 SLNet::OP_DELETE_ARRAY(remoteClients,_FILE_AND_LINE_);
100
101 StringCompressor::RemoveReference();
102 SLNet::StringTable::RemoveReference();
103 }
104 #if !defined(WINDOWS_STORE_RT)
105 bool TCPInterface::CreateListenSocket(unsigned short port, unsigned short maxIncomingConnections, unsigned short socketFamily, const char *bindAddress)
106 {
107 (void) maxIncomingConnections;
108 (void) socketFamily;
109 #if RAKNET_SUPPORT_IPV6!=1
110 listenSocket = socket__(AF_INET, SOCK_STREAM, 0);
111 if ((int)listenSocket ==-1)
112 return false;
113
114 struct sockaddr_in serverAddress;
115 memset(&serverAddress,0,sizeof(sockaddr_in));
116 serverAddress.sin_family = AF_INET;
117 if ( bindAddress && bindAddress[0] )
118 {
119
120
121
122
123
124 inet_pton(AF_INET, bindAddress, &serverAddress.sin_addr.s_addr);
125
126 }
127 else
128 serverAddress.sin_addr.s_addr = INADDR_ANY;
129
130 serverAddress.sin_port = htons(port);
131
132 SocketLayer::SetSocketOptions(listenSocket, false, false);
133
134 if (bind__(listenSocket,(struct sockaddr *) &serverAddress,sizeof(serverAddress)) < 0)
135 return false;
136
137 listen__(listenSocket, maxIncomingConnections);
138 #else
139 (void)bindAddress;
140 struct addrinfo hints;
141 memset(&hints, 0, sizeof (addrinfo)); // make sure the struct is empty
142 hints.ai_family = socketFamily; // don't care IPv4 or IPv6
143 hints.ai_socktype = SOCK_STREAM; // TCP sockets
144 hints.ai_flags = AI_PASSIVE; // fill in my IP for me
145 struct addrinfo *servinfo=0, *aip; // will point to the results
146 char portStr[32];
147 Itoa(port,portStr,10);
148
149 getaddrinfo(0, portStr, &hints, &servinfo);
150 for (aip = servinfo; aip != NULL; aip = aip->ai_next)
151 {
152 // Open socket. The address type depends on what
153 // getaddrinfo() gave us.
154 listenSocket = socket__(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
155 if (listenSocket != 0)
156 {
157 int ret = bind__( listenSocket, aip->ai_addr, (int) aip->ai_addrlen );
158 if (ret>=0)
159 {
160 break;
161 }
162 else
163 {
164 closesocket__(listenSocket);
165 listenSocket=0;
166 }
167 }
168 }
169
170 if (listenSocket==0)
171 return false;
172
173 SocketLayer::SetSocketOptions(listenSocket, false, false);
174
175 listen__(listenSocket, maxIncomingConnections);
176 #endif // #if RAKNET_SUPPORT_IPV6!=1
177
178 return true;
179 }
180 #endif
181
182 #if defined(WINDOWS_STORE_RT)
183 bool TCPInterface::CreateListenSocket_WinStore8(unsigned short port, unsigned short maxIncomingConnections, unsigned short socketFamily, const char *bindAddress)
184 {
185 listenSocket = WinRTCreateStreamSocket(AF_INET, SOCK_STREAM, 0);
186 return true;
187 }
188 #endif
189 bool TCPInterface::Start(unsigned short port, unsigned short maxIncomingConnections, unsigned short maxConnections, int _threadPriority, unsigned short socketFamily, const char *bindAddress)
190 {
191 #ifdef __native_client__
192 return false;
193 #else
194 (void) socketFamily;
195
196 if (isStarted.GetValue()>0)
197 return false;
198
199 threadPriority=_threadPriority;
200
201 if (threadPriority==-99999)
202 {
203
204
205 #if defined(_WIN32)
206 threadPriority=0;
207
208
209 #else
210 threadPriority=1000;
211 #endif
212 }
213
214 isStarted.Increment();
215 if (maxConnections==0)
216 maxConnections=maxIncomingConnections;
217 if (maxConnections==0)
218 maxConnections=1;
219 remoteClientsLength=maxConnections;
220 remoteClients= SLNet::OP_NEW_ARRAY<RemoteClient>(maxConnections,_FILE_AND_LINE_);
221
222
223 listenSocket=0;
224 if (maxIncomingConnections>0)
225 {
226 #if defined(WINDOWS_STORE_RT)
227 CreateListenSocket_WinStore8(port, maxIncomingConnections, socketFamily, bindAddress);
228 #else
229 CreateListenSocket(port, maxIncomingConnections, socketFamily, bindAddress);
230 #endif
231 }
232
233
234 // Start the update thread
235 int errorCode;
236
237
238
239
240
241 errorCode = SLNet::RakThread::Create(UpdateTCPInterfaceLoop, this, threadPriority);
242
243
244 if (errorCode!=0)
245 return false;
246
247 while (threadRunning.GetValue()==0)
248 RakSleep(0);
249
250 unsigned int i;
251 for (i=0; i < messageHandlerList.Size(); i++)
252 messageHandlerList[i]->OnRakPeerStartup();
253
254 return true;
255 #endif // __native_client__
256 }
257 void TCPInterface::Stop(void)
258 {
259 unsigned int i;
260 for (i=0; i < messageHandlerList.Size(); i++)
261 messageHandlerList[i]->OnRakPeerShutdown();
262
263 #ifndef __native_client__
264 if (isStarted.GetValue()==0)
265 return;
266
267 #if OPEN_SSL_CLIENT_SUPPORT==1
268 for (i=0; i < remoteClientsLength; i++)
269 remoteClients[i].DisconnectSSL();
270 #endif
271
272 isStarted.Decrement();
273
274 #if !defined(WINDOWS_STORE_RT)
275 if (listenSocket!=0)
276 #endif
277 {
278 #ifdef _WIN32
279 shutdown__(listenSocket, SD_BOTH);
280
281 #else
282 shutdown__(listenSocket, SHUT_RDWR);
283 #endif
284 closesocket__(listenSocket);
285 }
286
287 // Abort waiting connect calls
288 blockingSocketListMutex.Lock();
289 for (i=0; i < blockingSocketList.Size(); i++)
290 {
291 closesocket__(blockingSocketList[i]);
292 }
293 blockingSocketListMutex.Unlock();
294
295 // Wait for the thread to stop
296 while ( threadRunning.GetValue()>0 )
297 RakSleep(15);
298
299 RakSleep(100);
300
301 #if !defined(WINDOWS_STORE_RT)
302 listenSocket=0;
303 #endif
304
305 // Stuff from here on to the end of the function is not threadsafe
306 for (i=0; i < remoteClientsLength; i++)
307 {
308 closesocket__(remoteClients[i].socket);
309 #if OPEN_SSL_CLIENT_SUPPORT==1
310 remoteClients[i].FreeSSL();
311 #endif
312 }
313 remoteClientsLength=0;
314 SLNet::OP_DELETE_ARRAY(remoteClients,_FILE_AND_LINE_);
315 remoteClients=0;
316
317 // #low review whether we'd rather use PopInaccurate() here (i.e. check whether related threads accessing the queue terminated already)
318 // consider even adding a dtor to Packet which would then clear its data (at this point drop this explicit packet deallocation here)
319 SLNet::Packet* packet = incomingMessages.Pop();
320 while (packet != nullptr) {
321 DeallocatePacket(packet);
322 packet = incomingMessages.Pop();
323 }
324 incomingMessages.Clear(_FILE_AND_LINE_);
325 newIncomingConnections.Clear(_FILE_AND_LINE_);
326 newRemoteClients.Clear(_FILE_AND_LINE_);
327 lostConnections.Clear(_FILE_AND_LINE_);
328 requestedCloseConnections.Clear(_FILE_AND_LINE_);
329 failedConnectionAttempts.Clear(_FILE_AND_LINE_);
330 completedConnectionAttempts.Clear(_FILE_AND_LINE_);
331 failedConnectionAttempts.Clear(_FILE_AND_LINE_);
332 for (i=0; i < headPush.Size(); i++)
333 DeallocatePacket(headPush[i]);
334 headPush.Clear(_FILE_AND_LINE_);
335 for (i=0; i < tailPush.Size(); i++)
336 DeallocatePacket(tailPush[i]);
337 tailPush.Clear(_FILE_AND_LINE_);
338
339 #if OPEN_SSL_CLIENT_SUPPORT==1
340 SSL_CTX_free (ctx);
341 startSSL.Clear(_FILE_AND_LINE_);
342 activeSSLConnections.Clear(false, _FILE_AND_LINE_);
343 #endif
344
345
346
347
348
349 #endif // __native_client__
350 }
351 SystemAddress TCPInterface::Connect(const char* host, unsigned short remotePort, bool block, unsigned short socketFamily, const char *bindAddress)
352 {
353 if (threadRunning.GetValue()==0)
354 return UNASSIGNED_SYSTEM_ADDRESS;
355
356 int newRemoteClientIndex=-1;
357 for (newRemoteClientIndex=0; newRemoteClientIndex < remoteClientsLength; newRemoteClientIndex++)
358 {
359 remoteClients[newRemoteClientIndex].isActiveMutex.Lock();
360 if (remoteClients[newRemoteClientIndex].isActive==false)
361 {
362 remoteClients[newRemoteClientIndex].SetActive(true);
363 remoteClients[newRemoteClientIndex].isActiveMutex.Unlock();
364 break;
365 }
366 remoteClients[newRemoteClientIndex].isActiveMutex.Unlock();
367 }
368 if (newRemoteClientIndex==-1)
369 return UNASSIGNED_SYSTEM_ADDRESS;
370
371 if (block)
372 {
373 SystemAddress systemAddress;
374 systemAddress.FromString(host);
375 systemAddress.SetPortHostOrder(remotePort);
376 systemAddress.systemIndex=(SystemIndex) newRemoteClientIndex;
377 char buffout[128];
378 systemAddress.ToString(false,buffout, static_cast<size_t>(128));
379
380 __TCPSOCKET__ sockfd = SocketConnect(buffout, remotePort, socketFamily, bindAddress);
381 // Windows RT TODO
382 #if !defined(WINDOWS_STORE_RT)
383 if (sockfd==0)
384 #endif
385 {
386 remoteClients[newRemoteClientIndex].isActiveMutex.Lock();
387 remoteClients[newRemoteClientIndex].SetActive(false);
388 remoteClients[newRemoteClientIndex].isActiveMutex.Unlock();
389
390 failedConnectionAttemptMutex.Lock();
391 failedConnectionAttempts.Push(systemAddress, _FILE_AND_LINE_ );
392 failedConnectionAttemptMutex.Unlock();
393
394 return UNASSIGNED_SYSTEM_ADDRESS;
395 }
396
397 remoteClients[newRemoteClientIndex].socket=sockfd;
398 remoteClients[newRemoteClientIndex].systemAddress=systemAddress;
399
400 completedConnectionAttemptMutex.Lock();
401 completedConnectionAttempts.Push(remoteClients[newRemoteClientIndex].systemAddress, _FILE_AND_LINE_ );
402 completedConnectionAttemptMutex.Unlock();
403
404 return remoteClients[newRemoteClientIndex].systemAddress;
405 }
406 else
407 {
408 ThisPtrPlusSysAddr *s = SLNet::OP_NEW<ThisPtrPlusSysAddr>( _FILE_AND_LINE_ );
409 s->systemAddress.FromStringExplicitPort(host,remotePort);
410 s->systemAddress.systemIndex=(SystemIndex) newRemoteClientIndex;
411 if (bindAddress)
412 strcpy_s(s->bindAddress, bindAddress);
413 else
414 s->bindAddress[0]=0;
415 s->tcpInterface=this;
416 s->socketFamily=socketFamily;
417
418 // Start the connection thread
419 int errorCode;
420
421
422
423
424 errorCode = SLNet::RakThread::Create(ConnectionAttemptLoop, s, threadPriority);
425
426 if (errorCode!=0)
427 {
428 SLNet::OP_DELETE(s, _FILE_AND_LINE_);
429 failedConnectionAttempts.Push(s->systemAddress, _FILE_AND_LINE_ );
430 }
431 return UNASSIGNED_SYSTEM_ADDRESS;
432 }
433 }
434 #if OPEN_SSL_CLIENT_SUPPORT==1
435 void TCPInterface::StartSSLClient(SystemAddress systemAddress)
436 {
437 if (ctx==0)
438 {
439 sharedSslMutex.Lock();
440 SSLeay_add_ssl_algorithms();
441 meth = (SSL_METHOD*) SSLv23_client_method();
442 SSL_load_error_strings();
443 ctx = SSL_CTX_new (meth);
444 RakAssert(ctx!=0);
445 sharedSslMutex.Unlock();
446 }
447
448 SystemAddress *id = startSSL.Allocate( _FILE_AND_LINE_ );
449 *id=systemAddress;
450 startSSL.Push(id);
451 unsigned index = activeSSLConnections.GetIndexOf(systemAddress);
452 if (index==(unsigned)-1)
453 activeSSLConnections.Insert(systemAddress,_FILE_AND_LINE_);
454 }
455 bool TCPInterface::IsSSLActive(SystemAddress systemAddress)
456 {
457 return activeSSLConnections.GetIndexOf(systemAddress)!=-1;
458 }
459 #endif
460 void TCPInterface::Send( const char *data, unsigned length, const SystemAddress &systemAddress, bool broadcast )
461 {
462 SendList( &data, &length, 1, systemAddress,broadcast );
463 }
464 bool TCPInterface::SendList( const char **data, const unsigned int *lengths, const int numParameters, const SystemAddress &systemAddress, bool broadcast )
465 {
466 if (isStarted.GetValue()==0)
467 return false;
468 if (data==0)
469 return false;
470 if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS && broadcast==false)
471 return false;
472 unsigned int totalLength=0;
473 int i;
474 for (i=0; i < numParameters; i++)
475 {
476 if (lengths[i]>0)
477 totalLength+=lengths[i];
478 }
479 if (totalLength==0)
480 return false;
481
482 if (broadcast)
483 {
484 // Send to all, possible exception system
485 for (i=0; i < remoteClientsLength; i++)
486 {
487 if (remoteClients[i].systemAddress!=systemAddress)
488 {
489 remoteClients[i].SendOrBuffer(data, lengths, numParameters);
490 }
491 }
492 }
493 else
494 {
495 // Send to this player
496 if (systemAddress.systemIndex<remoteClientsLength &&
497 remoteClients[systemAddress.systemIndex].systemAddress==systemAddress)
498 {
499 remoteClients[systemAddress.systemIndex].SendOrBuffer(data, lengths, numParameters);
500 }
501 else
502 {
503 for (i=0; i < remoteClientsLength; i++)
504 {
505 if (remoteClients[i].systemAddress==systemAddress )
506 {
507 remoteClients[i].SendOrBuffer(data, lengths, numParameters);
508 }
509 }
510 }
511 }
512
513
514 return true;
515 }
516 bool TCPInterface::ReceiveHasPackets( void )
517 {
518 return headPush.IsEmpty()==false || incomingMessages.IsEmpty()==false || tailPush.IsEmpty()==false;
519 }
520 Packet* TCPInterface::Receive( void )
521 {
522 unsigned int i;
523 for (i=0; i < messageHandlerList.Size(); i++)
524 messageHandlerList[i]->Update();
525
526 Packet* outgoingPacket = ReceiveInt();
527
528 if (outgoingPacket)
529 {
530 PluginReceiveResult pluginResult;
531 for (i=0; i < messageHandlerList.Size(); i++)
532 {
533 pluginResult=messageHandlerList[i]->OnReceive(outgoingPacket);
534 if (pluginResult==RR_STOP_PROCESSING_AND_DEALLOCATE)
535 {
536 DeallocatePacket( outgoingPacket );
537 outgoingPacket=0; // Will do the loop again and get another packet
538 break; // break out of the enclosing for
539 }
540 else if (pluginResult==RR_STOP_PROCESSING)
541 {
542 outgoingPacket=0;
543 break;
544 }
545 }
546 }
547
548
549 return outgoingPacket;
550 }
551 Packet* TCPInterface::ReceiveInt( void )
552 {
553 if (isStarted.GetValue()==0)
554 return 0;
555 if (headPush.IsEmpty()==false)
556 return headPush.Pop();
557 Packet *p = incomingMessages.PopInaccurate();
558 if (p)
559 return p;
560 if (tailPush.IsEmpty()==false)
561 return tailPush.Pop();
562 return 0;
563 }
564
565
566 void TCPInterface::AttachPlugin( PluginInterface2 *plugin )
567 {
568 if (messageHandlerList.GetIndexOf(plugin)==MAX_UNSIGNED_LONG)
569 {
570 messageHandlerList.Insert(plugin, _FILE_AND_LINE_);
571 plugin->SetTCPInterface(this);
572 plugin->OnAttach();
573 }
574 }
575 void TCPInterface::DetachPlugin( PluginInterface2 *plugin )
576 {
577 if (plugin==0)
578 return;
579
580 unsigned int index;
581 index = messageHandlerList.GetIndexOf(plugin);
582 if (index!=MAX_UNSIGNED_LONG)
583 {
584 messageHandlerList[index]->OnDetach();
585 // Unordered list so delete from end for speed
586 messageHandlerList[index]=messageHandlerList[messageHandlerList.Size()-1];
587 messageHandlerList.RemoveFromEnd();
588 plugin->SetTCPInterface(0);
589 }
590 }
591 void TCPInterface::CloseConnection( SystemAddress systemAddress )
592 {
593 if (isStarted.GetValue()==0)
594 return;
595 if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
596 return;
597
598 unsigned int i;
599 for (i=0; i < messageHandlerList.Size(); i++)
600 messageHandlerList[i]->OnClosedConnection(systemAddress, UNASSIGNED_RAKNET_GUID, LCR_CLOSED_BY_USER);
601
602 if (systemAddress.systemIndex<remoteClientsLength && remoteClients[systemAddress.systemIndex].systemAddress==systemAddress)
603 {
604 remoteClients[systemAddress.systemIndex].isActiveMutex.Lock();
605 remoteClients[systemAddress.systemIndex].SetActive(false);
606 remoteClients[systemAddress.systemIndex].isActiveMutex.Unlock();
607 }
608 else
609 {
610 for (i=0; i < remoteClientsLength; i++)
611 {
612 remoteClients[i].isActiveMutex.Lock();
613 if (remoteClients[i].isActive && remoteClients[i].systemAddress==systemAddress)
614 {
615 remoteClients[systemAddress.systemIndex].SetActive(false);
616 remoteClients[i].isActiveMutex.Unlock();
617 break;
618 }
619 remoteClients[i].isActiveMutex.Unlock();
620 }
621 }
622
623
624 #if OPEN_SSL_CLIENT_SUPPORT==1
625 unsigned index = activeSSLConnections.GetIndexOf(systemAddress);
626 if (index!=(unsigned)-1)
627 activeSSLConnections.RemoveAtIndex(index);
628 #endif
629 }
630 void TCPInterface::DeallocatePacket( Packet *packet )
631 {
632 if (packet==0)
633 return;
634 if (packet->deleteData)
635 {
636 rakFree_Ex(packet->data, _FILE_AND_LINE_ );
637 incomingMessages.Deallocate(packet, _FILE_AND_LINE_);
638 }
639 else
640 {
641 // Came from userspace AllocatePacket
642 rakFree_Ex(packet->data, _FILE_AND_LINE_ );
643 SLNet::OP_DELETE(packet, _FILE_AND_LINE_);
644 }
645 }
646 Packet* TCPInterface::AllocatePacket(unsigned dataSize)
647 {
648 Packet*p = SLNet::OP_NEW<Packet>(_FILE_AND_LINE_);
649 p->data=(unsigned char*) rakMalloc_Ex(dataSize,_FILE_AND_LINE_);
650 p->length=dataSize;
651 p->bitSize=BYTES_TO_BITS(dataSize);
652 p->deleteData=false;
653 p->guid=UNASSIGNED_RAKNET_GUID;
654 p->systemAddress=UNASSIGNED_SYSTEM_ADDRESS;
655 p->systemAddress.systemIndex=(SystemIndex)-1;
656 return p;
657 }
658 void TCPInterface::PushBackPacket( Packet *packet, bool pushAtHead )
659 {
660 if (pushAtHead)
661 headPush.Push(packet, _FILE_AND_LINE_ );
662 else
663 tailPush.Push(packet, _FILE_AND_LINE_ );
664 }
665 bool TCPInterface::WasStarted(void) const
666 {
667 return threadRunning.GetValue()>0;
668 }
669 SystemAddress TCPInterface::HasCompletedConnectionAttempt(void)
670 {
671 SystemAddress sysAddr=UNASSIGNED_SYSTEM_ADDRESS;
672 completedConnectionAttemptMutex.Lock();
673 if (completedConnectionAttempts.IsEmpty()==false)
674 sysAddr=completedConnectionAttempts.Pop();
675 completedConnectionAttemptMutex.Unlock();
676
677 if (sysAddr!=UNASSIGNED_SYSTEM_ADDRESS)
678 {
679 unsigned int i;
680 for (i=0; i < messageHandlerList.Size(); i++)
681 messageHandlerList[i]->OnNewConnection(sysAddr, UNASSIGNED_RAKNET_GUID, true);
682 }
683
684 return sysAddr;
685 }
686 SystemAddress TCPInterface::HasFailedConnectionAttempt(void)
687 {
688 SystemAddress sysAddr=UNASSIGNED_SYSTEM_ADDRESS;
689 failedConnectionAttemptMutex.Lock();
690 if (failedConnectionAttempts.IsEmpty()==false)
691 sysAddr=failedConnectionAttempts.Pop();
692 failedConnectionAttemptMutex.Unlock();
693
694 if (sysAddr!=UNASSIGNED_SYSTEM_ADDRESS)
695 {
696 unsigned int i;
697 for (i=0; i < messageHandlerList.Size(); i++)
698 {
699 Packet p;
700 p.systemAddress=sysAddr;
701 p.data=0;
702 p.length=0;
703 p.bitSize=0;
704 messageHandlerList[i]->OnFailedConnectionAttempt(&p, FCAR_CONNECTION_ATTEMPT_FAILED);
705 }
706 }
707
708 return sysAddr;
709 }
710 SystemAddress TCPInterface::HasNewIncomingConnection(void)
711 {
712 SystemAddress *out, out2;
713 out = newIncomingConnections.PopInaccurate();
714 if (out)
715 {
716 out2=*out;
717 newIncomingConnections.Deallocate(out, _FILE_AND_LINE_);
718
719 unsigned int i;
720 for (i=0; i < messageHandlerList.Size(); i++)
721 messageHandlerList[i]->OnNewConnection(out2, UNASSIGNED_RAKNET_GUID, true);
722
723 return *out;
724 }
725 else
726 {
727 return UNASSIGNED_SYSTEM_ADDRESS;
728 }
729 }
730 SystemAddress TCPInterface::HasLostConnection(void)
731 {
732 SystemAddress *out, out2;
733 out = lostConnections.PopInaccurate();
734 if (out)
735 {
736 out2=*out;
737 lostConnections.Deallocate(out, _FILE_AND_LINE_);
738
739 unsigned int i;
740 for (i=0; i < messageHandlerList.Size(); i++)
741 messageHandlerList[i]->OnClosedConnection(out2, UNASSIGNED_RAKNET_GUID, LCR_DISCONNECTION_NOTIFICATION);
742
743 return *out;
744 }
745 else
746 {
747 return UNASSIGNED_SYSTEM_ADDRESS;
748 }
749 }
750 void TCPInterface::GetConnectionList( SystemAddress *remoteSystems, unsigned short *numberOfSystems ) const
751 {
752 unsigned short systemCount=0;
753 unsigned short maxToWrite=*numberOfSystems;
754 for (int i=0; i < remoteClientsLength; i++)
755 {
756 if (remoteClients[i].isActive)
757 {
758 if (systemCount < maxToWrite)
759 remoteSystems[systemCount]=remoteClients[i].systemAddress;
760 systemCount++;
761 }
762 }
763 *numberOfSystems=systemCount;
764 }
765 unsigned short TCPInterface::GetConnectionCount(void) const
766 {
767 unsigned short systemCount=0;
768 for (int i=0; i < remoteClientsLength; i++)
769 {
770 if (remoteClients[i].isActive)
771 systemCount++;
772 }
773 return systemCount;
774 }
775
776 unsigned int TCPInterface::GetOutgoingDataBufferSize(SystemAddress systemAddress) const
777 {
778 unsigned bytesWritten=0;
779 if (systemAddress.systemIndex<remoteClientsLength &&
780 remoteClients[systemAddress.systemIndex].isActive &&
781 remoteClients[systemAddress.systemIndex].systemAddress==systemAddress)
782 {
783 remoteClients[systemAddress.systemIndex].outgoingDataMutex.Lock();
784 bytesWritten=remoteClients[systemAddress.systemIndex].outgoingData.GetBytesWritten();
785 remoteClients[systemAddress.systemIndex].outgoingDataMutex.Unlock();
786 return bytesWritten;
787 }
788
789 for (int i=0; i < remoteClientsLength; i++)
790 {
791 if (remoteClients[i].isActive && remoteClients[i].systemAddress==systemAddress)
792 {
793 remoteClients[i].outgoingDataMutex.Lock();
794 bytesWritten+=remoteClients[i].outgoingData.GetBytesWritten();
795 remoteClients[i].outgoingDataMutex.Unlock();
796 }
797 }
798 return bytesWritten;
799 }
800 __TCPSOCKET__ TCPInterface::SocketConnect(const char* host, unsigned short remotePort, unsigned short socketFamily, const char *bindAddress)
801 {
802 #ifdef __native_client__
803 return 0;
804 #else
805 int connectResult;
806 (void) connectResult;
807 (void) socketFamily;
808
809 #if RAKNET_SUPPORT_IPV6!=1
810 sockaddr_in serverAddress;
811
812 struct addrinfo *curAddress = NULL;
813 int err = getaddrinfo(host, NULL, NULL, &curAddress);
814
815 // #med This should also work with IPv6 addresses in principle. However the old code in RakNet only worked with IPv4. Hence this behavior change won't be in MaxNet 0.1.
816 // get the (first) IPv4 address
817 while(curAddress != NULL) {
818 if (curAddress->ai_family == AF_INET) {
819 break; // found an IPv4 address
820 }
821 curAddress = curAddress->ai_next;
822 }
823
824 if (curAddress == NULL)
825 return 0;
826
827 if (err != 0)
828 return 0;
829
830
831 #if defined(WINDOWS_STORE_RT)
832 __TCPSOCKET__ sockfd = WinRTCreateStreamSocket(AF_INET, SOCK_STREAM, 0);
833 #else
834 __TCPSOCKET__ sockfd = socket__(AF_INET, SOCK_STREAM, 0);
835 if (sockfd < 0)
836 return 0;
837 #endif
838
839 memset(&serverAddress, 0, sizeof(serverAddress));
840 serverAddress.sin_family = AF_INET;
841 serverAddress.sin_port = htons( remotePort );
842
843
844 if ( bindAddress && bindAddress[0] )
845 {
846
847
848
849
850
851 inet_pton(AF_INET, bindAddress, &serverAddress.sin_addr.s_addr);
852
853 }
854 else
855 serverAddress.sin_addr.s_addr = INADDR_ANY;
856
857 int sock_opt=1024*256;
858 setsockopt__(sockfd, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
859
860 serverAddress.sin_addr = ((struct sockaddr_in *)curAddress->ai_addr)->sin_addr;
861
862
863
864
865
866
867
868
869
870
871 blockingSocketListMutex.Lock();
872 blockingSocketList.Insert(sockfd, _FILE_AND_LINE_);
873 blockingSocketListMutex.Unlock();
874
875 // This is blocking
876 connectResult = connect__( sockfd, ( struct sockaddr * ) &serverAddress, sizeof( struct sockaddr ) );
877
878 #else
879
880 (void)bindAddress;
881 struct addrinfo hints, *res;
882 __TCPSOCKET__ sockfd;
883 memset(&hints, 0, sizeof hints);
884 hints.ai_family = socketFamily;
885 hints.ai_socktype = SOCK_STREAM;
886 char portStr[32];
887 Itoa(remotePort,portStr,10);
888 getaddrinfo(host, portStr, &hints, &res);
889 sockfd = socket__(res->ai_family, res->ai_socktype, res->ai_protocol);
890 blockingSocketListMutex.Lock();
891 blockingSocketList.Insert(sockfd, _FILE_AND_LINE_);
892 blockingSocketListMutex.Unlock();
893 // #low - review usage of static cast here
894 connectResult=connect__(sockfd, res->ai_addr, static_cast<int>(res->ai_addrlen));
895 freeaddrinfo(res); // free the linked-list
896
897 #endif // #if RAKNET_SUPPORT_IPV6!=1
898
899 if (connectResult==-1)
900 {
901 unsigned sockfdIndex;
902 blockingSocketListMutex.Lock();
903 sockfdIndex=blockingSocketList.GetIndexOf(sockfd);
904 if (sockfdIndex!=(unsigned)-1)
905 blockingSocketList.RemoveAtIndexFast(sockfdIndex);
906 blockingSocketListMutex.Unlock();
907
908 closesocket__(sockfd);
909 return 0;
910 }
911
912 return sockfd;
913 #endif // __native_client__
914 }
915
916 RAK_THREAD_DECLARATION(SLNet::ConnectionAttemptLoop)
917 {
918
919
920
921 TCPInterface::ThisPtrPlusSysAddr *s = (TCPInterface::ThisPtrPlusSysAddr *) arguments;
922
923
924
925 SystemAddress systemAddress = s->systemAddress;
926 TCPInterface *tcpInterface = s->tcpInterface;
927 int newRemoteClientIndex=systemAddress.systemIndex;
928 unsigned short socketFamily = s->socketFamily;
929 SLNet::OP_DELETE(s, _FILE_AND_LINE_);
930
931 char str1[64];
932 systemAddress.ToString(false, str1, static_cast<size_t>(64));
933 __TCPSOCKET__ sockfd = tcpInterface->SocketConnect(str1, systemAddress.GetPort(), socketFamily, s->bindAddress);
934 if (sockfd==0)
935 {
936 tcpInterface->remoteClients[newRemoteClientIndex].isActiveMutex.Lock();
937 tcpInterface->remoteClients[newRemoteClientIndex].SetActive(false);
938 tcpInterface->remoteClients[newRemoteClientIndex].isActiveMutex.Unlock();
939
940 tcpInterface->failedConnectionAttemptMutex.Lock();
941 tcpInterface->failedConnectionAttempts.Push(systemAddress, _FILE_AND_LINE_ );
942 tcpInterface->failedConnectionAttemptMutex.Unlock();
943 return 0;
944 }
945
946 tcpInterface->remoteClients[newRemoteClientIndex].socket=sockfd;
947 tcpInterface->remoteClients[newRemoteClientIndex].systemAddress=systemAddress;
948
949 // Notify user that the connection attempt has completed.
950 if (tcpInterface->threadRunning.GetValue()>0)
951 {
952 tcpInterface->completedConnectionAttemptMutex.Lock();
953 tcpInterface->completedConnectionAttempts.Push(systemAddress, _FILE_AND_LINE_ );
954 tcpInterface->completedConnectionAttemptMutex.Unlock();
955 }
956
957
958
959
960 return 0;
961
962 }
963
964 RAK_THREAD_DECLARATION(SLNet::UpdateTCPInterfaceLoop)
965 {
966
967
968
969 TCPInterface * sts = ( TCPInterface * ) arguments;
970
971
972 // const int BUFF_SIZE=8096;
973 const unsigned int BUFF_SIZE=1048576;
974 //char data[ BUFF_SIZE ];
975 char * data = (char*) rakMalloc_Ex(BUFF_SIZE,_FILE_AND_LINE_);
976 Packet *incomingMessage;
977 fd_set readFD, exceptionFD, writeFD;
978 sts->threadRunning.Increment();
979
980 #if RAKNET_SUPPORT_IPV6!=1
981 sockaddr_in sockAddr;
982 int sockAddrSize = sizeof(sockAddr);
983 #else
984 struct sockaddr_storage sockAddr;
985 socklen_t sockAddrSize = sizeof(sockAddr);
986 #endif
987
988 int len;
989 __TCPSOCKET__ newSock;
990 int selectResult;
991
992
993 timeval tv;
994 tv.tv_sec=0;
995 tv.tv_usec=30000;
996
997
998 while (sts->isStarted.GetValue()>0)
999 {
1000 #if OPEN_SSL_CLIENT_SUPPORT==1
1001 SystemAddress *sslSystemAddress;
1002 sslSystemAddress = sts->startSSL.PopInaccurate();
1003 if (sslSystemAddress)
1004 {
1005 if (sslSystemAddress->systemIndex>=0 &&
1006 sslSystemAddress->systemIndex<sts->remoteClientsLength &&
1007 sts->remoteClients[sslSystemAddress->systemIndex].systemAddress==*sslSystemAddress)
1008 {
1009 sts->remoteClients[sslSystemAddress->systemIndex].InitSSL(sts->ctx,sts->meth);
1010 }
1011 else
1012 {
1013 for (int i=0; i < sts->remoteClientsLength; i++)
1014 {
1015 sts->remoteClients[i].isActiveMutex.Lock();
1016 if (sts->remoteClients[i].isActive && sts->remoteClients[i].systemAddress==*sslSystemAddress)
1017 {
1018 if (sts->remoteClients[i].ssl==0)
1019 sts->remoteClients[i].InitSSL(sts->ctx,sts->meth);
1020 }
1021 sts->remoteClients[i].isActiveMutex.Unlock();
1022 }
1023 }
1024 sts->startSSL.Deallocate(sslSystemAddress,_FILE_AND_LINE_);
1025 }
1026 #endif
1027
1028
1029 __TCPSOCKET__ largestDescriptor=0; // see select__()'s first parameter's documentation under linux
1030
1031
1032 // Linux' select__() implementation changes the timeout
1033
1034 tv.tv_sec=0;
1035 tv.tv_usec=30000;
1036
1037
1038 #ifdef _MSC_VER
1039 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
1040 #endif
1041 for(;;)
1042 {
1043 // Reset readFD, writeFD, and exceptionFD since select seems to clear it
1044 FD_ZERO(&readFD);
1045 FD_ZERO(&exceptionFD);
1046 FD_ZERO(&writeFD);
1047 largestDescriptor=0;
1048 if (sts->listenSocket!=0)
1049 {
1050 FD_SET(sts->listenSocket, &readFD);
1051 FD_SET(sts->listenSocket, &exceptionFD);
1052 largestDescriptor = sts->listenSocket; // @see largestDescriptor def
1053 }
1054
1055 unsigned i;
1056 for (i=0; i < sts->remoteClientsLength; i++)
1057 {
1058 sts->remoteClients[i].isActiveMutex.Lock();
1059 if (sts->remoteClients[i].isActive)
1060 {
1061 // calling FD_ISSET with -1 as socket (that’s what 0 is set to) produces a bus error under Linux 64-Bit
1062 __TCPSOCKET__ socketCopy = sts->remoteClients[i].socket;
1063 if (socketCopy != 0)
1064 {
1065 FD_SET(socketCopy, &readFD);
1066 FD_SET(socketCopy, &exceptionFD);
1067 if (sts->remoteClients[i].outgoingData.GetBytesWritten()>0)
1068 FD_SET(socketCopy, &writeFD);
1069 if(socketCopy > largestDescriptor) // @see largestDescriptorDef
1070 largestDescriptor = socketCopy;
1071 }
1072 }
1073 sts->remoteClients[i].isActiveMutex.Unlock();
1074 }
1075
1076 #ifdef _MSC_VER
1077 #pragma warning( disable : 4244 ) // warning C4127: conditional expression is constant
1078 #endif
1079
1080
1081 selectResult=(int) select__(largestDescriptor+1, &readFD, &writeFD, &exceptionFD, &tv);
1082
1083
1084
1085
1086 if (selectResult<=0)
1087 break;
1088
1089 if (sts->listenSocket!=0 && FD_ISSET(sts->listenSocket, &readFD))
1090 {
1091 newSock = accept__(sts->listenSocket, (sockaddr*)&sockAddr, (socklen_t*)&sockAddrSize);
1092
1093 if (newSock != 0)
1094 {
1095 int newRemoteClientIndex=-1;
1096 for (newRemoteClientIndex=0; newRemoteClientIndex < sts->remoteClientsLength; newRemoteClientIndex++)
1097 {
1098 sts->remoteClients[newRemoteClientIndex].isActiveMutex.Lock();
1099 if (sts->remoteClients[newRemoteClientIndex].isActive==false)
1100 {
1101 sts->remoteClients[newRemoteClientIndex].socket=newSock;
1102
1103 #if RAKNET_SUPPORT_IPV6!=1
1104 sts->remoteClients[newRemoteClientIndex].systemAddress.address.addr4.sin_addr.s_addr=sockAddr.sin_addr.s_addr;
1105 sts->remoteClients[newRemoteClientIndex].systemAddress.SetPortNetworkOrder( sockAddr.sin_port);
1106 sts->remoteClients[newRemoteClientIndex].systemAddress.systemIndex=newRemoteClientIndex;
1107 #else
1108 if (sockAddr.ss_family==AF_INET)
1109 {
1110 memcpy(&sts->remoteClients[newRemoteClientIndex].systemAddress.address.addr4,(sockaddr_in *)&sockAddr,sizeof(sockaddr_in));
1111 // sts->remoteClients[newRemoteClientIndex].systemAddress.address.addr4.sin_port=ntohs( sts->remoteClients[newRemoteClientIndex].systemAddress.address.addr4.sin_port );
1112 }
1113 else
1114 {
1115 memcpy(&sts->remoteClients[newRemoteClientIndex].systemAddress.address.addr6,(sockaddr_in6 *)&sockAddr,sizeof(sockaddr_in6));
1116 // sts->remoteClients[newRemoteClientIndex].systemAddress.address.addr6.sin6_port=ntohs( sts->remoteClients[newRemoteClientIndex].systemAddress.address.addr6.sin6_port );
1117 }
1118
1119 #endif // #if RAKNET_SUPPORT_IPV6!=1
1120 sts->remoteClients[newRemoteClientIndex].SetActive(true);
1121 sts->remoteClients[newRemoteClientIndex].isActiveMutex.Unlock();
1122
1123
1124 SystemAddress *newConnectionSystemAddress=sts->newIncomingConnections.Allocate( _FILE_AND_LINE_ );
1125 *newConnectionSystemAddress=sts->remoteClients[newRemoteClientIndex].systemAddress;
1126 sts->newIncomingConnections.Push(newConnectionSystemAddress);
1127
1128 break;
1129 }
1130 sts->remoteClients[newRemoteClientIndex].isActiveMutex.Unlock();
1131 }
1132 if (newRemoteClientIndex==-1)
1133 {
1134 closesocket__(sts->listenSocket);
1135 }
1136 }
1137 else
1138 {
1139 #ifdef _DO_PRINTF
1140 RAKNET_DEBUG_PRINTF("Error: connection failed\n");
1141 #endif
1142 }
1143 }
1144 else if (sts->listenSocket!=0 && FD_ISSET(sts->listenSocket, &exceptionFD))
1145 {
1146 #ifdef _DO_PRINTF
1147 int err;
1148 int errlen = sizeof(err);
1149 getsockopt__(sts->listenSocket, SOL_SOCKET, SO_ERROR,(char*)&err, &errlen);
1150 RAKNET_DEBUG_PRINTF("Socket error %s on listening socket\n", err);
1151 #endif
1152 }
1153
1154 {
1155 i=0;
1156 while (i < sts->remoteClientsLength)
1157 {
1158 if (sts->remoteClients[i].isActive==false)
1159 {
1160 i++;
1161 continue;
1162 }
1163 // calling FD_ISSET with -1 as socket (that’s what 0 is set to) produces a bus error under Linux 64-Bit
1164 __TCPSOCKET__ socketCopy = sts->remoteClients[i].socket;
1165 if (socketCopy == 0)
1166 {
1167 i++;
1168 continue;
1169 }
1170
1171 if (FD_ISSET(socketCopy, &exceptionFD))
1172 {
1173 // #ifdef _DO_PRINTF
1174 // if (sts->listenSocket!=-1)
1175 // {
1176 // int err;
1177 // int errlen = sizeof(err);
1178 // getsockopt__(sts->listenSocket, SOL_SOCKET, SO_ERROR,(char*)&err, &errlen);
1179 // in_addr in;
1180 // in.s_addr = sts->remoteClients[i].systemAddress.binaryAddress;
1181 // char ip[65];
1182 // inet_ntop(sts->remoteClients[i].systemAddress.address.addr4.sin_family, &in, ip, 65);
1183 // RAKNET_DEBUG_PRINTF("Socket error %i on %s:%i\n", err,ip, sts->remoteClients[i].systemAddress.GetPort() );
1184 // }
1185 //
1186 // #endif
1187 // Connection lost abruptly
1188 SystemAddress *lostConnectionSystemAddress=sts->lostConnections.Allocate( _FILE_AND_LINE_ );
1189 *lostConnectionSystemAddress=sts->remoteClients[i].systemAddress;
1190 sts->lostConnections.Push(lostConnectionSystemAddress);
1191 sts->remoteClients[i].isActiveMutex.Lock();
1192 sts->remoteClients[i].SetActive(false);
1193 sts->remoteClients[i].isActiveMutex.Unlock();
1194 }
1195 else
1196 {
1197 if (FD_ISSET(socketCopy, &readFD))
1198 {
1199 // if recv returns 0 this was a graceful close
1200 len = sts->remoteClients[i].Recv(data,BUFF_SIZE);
1201
1202
1203 // removeme
1204 // data[len]=0;
1205 // printf(data);
1206
1207 if (len>0)
1208 {
1209 incomingMessage=sts->incomingMessages.Allocate( _FILE_AND_LINE_ );
1210 incomingMessage->data = (unsigned char*) rakMalloc_Ex( len+1, _FILE_AND_LINE_ );
1211 memcpy(incomingMessage->data, data, len);
1212 incomingMessage->data[len]=0; // Null terminate this so we can print it out as regular strings. This is different from RakNet which does not do this.
1213 // printf("RECV: %s\n",incomingMessage->data);
1214 /*
1215 if (1)
1216 {
1217 static FILE *fp=0;
1218 if (fp==0)
1219 {
1220 fopen_s(&fp, "tcpRcv.txt", "wb");
1221 }
1222 fwrite(data,1,len,fp);
1223 }
1224 */
1225 incomingMessage->length=len;
1226 incomingMessage->deleteData=true; // actually means came from SPSC, rather than AllocatePacket
1227 incomingMessage->systemAddress=sts->remoteClients[i].systemAddress;
1228 sts->incomingMessages.Push(incomingMessage);
1229 }
1230 else
1231 {
1232 // Connection lost gracefully
1233 SystemAddress *lostConnectionSystemAddress=sts->lostConnections.Allocate( _FILE_AND_LINE_ );
1234 *lostConnectionSystemAddress=sts->remoteClients[i].systemAddress;
1235 sts->lostConnections.Push(lostConnectionSystemAddress);
1236 sts->remoteClients[i].isActiveMutex.Lock();
1237 sts->remoteClients[i].SetActive(false);
1238 sts->remoteClients[i].isActiveMutex.Unlock();
1239 continue;
1240 }
1241 }
1242 if (FD_ISSET(socketCopy, &writeFD))
1243 {
1244 RemoteClient *rc = &sts->remoteClients[i];
1245 unsigned int bytesInBuffer;
1246 int bytesAvailable;
1247 int bytesSent;
1248 rc->outgoingDataMutex.Lock();
1249 bytesInBuffer=rc->outgoingData.GetBytesWritten();
1250 if (bytesInBuffer>0)
1251 {
1252 unsigned int contiguousLength;
1253 char* contiguousBytesPointer = rc->outgoingData.PeekContiguousBytes(&contiguousLength);
1254 if (contiguousLength < (unsigned int) BUFF_SIZE && contiguousLength<bytesInBuffer)
1255 {
1256 if (bytesInBuffer > BUFF_SIZE)
1257 bytesAvailable=BUFF_SIZE;
1258 else
1259 bytesAvailable=bytesInBuffer;
1260 rc->outgoingData.ReadBytes(data,bytesAvailable,true);
1261 bytesSent=rc->Send(data,bytesAvailable);
1262 }
1263 else
1264 {
1265 bytesSent=rc->Send(contiguousBytesPointer,contiguousLength);
1266 }
1267
1268 if (bytesSent>0)
1269 rc->outgoingData.IncrementReadOffset(bytesSent);
1270 bytesInBuffer=rc->outgoingData.GetBytesWritten();
1271 }
1272 rc->outgoingDataMutex.Unlock();
1273 }
1274
1275 i++; // Nothing deleted so increment the index
1276 }
1277 }
1278 }
1279 }
1280
1281 // Sleep 0 on Linux monopolizes the CPU
1282 RakSleep(30);
1283 }
1284 sts->threadRunning.Decrement();
1285
1286 rakFree_Ex(data,_FILE_AND_LINE_);
1287
1288
1289
1290
1291 return 0;
1292
1293 }
1294
1295 void RemoteClient::SetActive(bool a)
1296 {
1297 if (isActive != a)
1298 {
1299 isActive=a;
1300 Reset();
1301 if (isActive==false && socket!=0)
1302 {
1303 closesocket__(socket);
1304 socket=0;
1305 }
1306 }
1307 }
1308 void RemoteClient::SendOrBuffer(const char **data, const unsigned int *lengths, const int numParameters)
1309 {
1310 // True can save memory and buffer copies, but gives worse performance overall
1311 // Do not use true for the XBOX, as it just locks up
1312 const bool ALLOW_SEND_FROM_USER_THREAD=false;
1313
1314 int parameterIndex;
1315 if (isActive==false)
1316 return;
1317 parameterIndex=0;
1318 for (; parameterIndex < numParameters; parameterIndex++)
1319 {
1320 outgoingDataMutex.Lock();
1321 if (ALLOW_SEND_FROM_USER_THREAD && outgoingData.GetBytesWritten()==0)
1322 {
1323 outgoingDataMutex.Unlock();
1324 int bytesSent = Send(data[parameterIndex],lengths[parameterIndex]);
1325 if (bytesSent<(int) lengths[parameterIndex])
1326 {
1327 // Push remainder
1328 outgoingDataMutex.Lock();
1329 outgoingData.WriteBytes(data[parameterIndex]+bytesSent,lengths[parameterIndex]-bytesSent,_FILE_AND_LINE_);
1330 outgoingDataMutex.Unlock();
1331 }
1332 }
1333 else
1334 {
1335 outgoingData.WriteBytes(data[parameterIndex],lengths[parameterIndex],_FILE_AND_LINE_);
1336 outgoingDataMutex.Unlock();
1337 }
1338 }
1339 }
1340 #if OPEN_SSL_CLIENT_SUPPORT==1
1341 bool RemoteClient::InitSSL(SSL_CTX* ctx, SSL_METHOD *meth)
1342 {
1343 (void) meth;
1344
1345 ssl = SSL_new (ctx);
1346 RakAssert(ssl);
1347 int res;
1348 res = SSL_set_fd (ssl, socket);
1349 if (res!=1)
1350 {
1351 printf("SSL_set_fd error: %s\n", ERR_reason_error_string(ERR_get_error()));
1352 SSL_free(ssl);
1353 ssl=0;
1354 return false;
1355 }
1356 RakAssert(res==1);
1357 res = SSL_connect (ssl);
1358 if (res<0)
1359 {
1360 unsigned long err = ERR_get_error();
1361 printf("SSL_connect error: %s\n", ERR_reason_error_string(err));
1362 SSL_free(ssl);
1363 ssl=0;
1364 return false;
1365 }
1366 else if (res==0)
1367 {
1368 // The TLS/SSL handshake was not successful but was shut down controlled and by the specifications of the TLS/SSL protocol. Call SSL_get_error() with the return value ret to find out the reason.
1369 int err = SSL_get_error(ssl, res);
1370 switch (err)
1371 {
1372 case SSL_ERROR_NONE:
1373 printf("SSL_ERROR_NONE\n");
1374 break;
1375 case SSL_ERROR_ZERO_RETURN:
1376 printf("SSL_ERROR_ZERO_RETURN\n");
1377 break;
1378 case SSL_ERROR_WANT_READ:
1379 printf("SSL_ERROR_WANT_READ\n");
1380 break;
1381 case SSL_ERROR_WANT_WRITE:
1382 printf("SSL_ERROR_WANT_WRITE\n");
1383 break;
1384 case SSL_ERROR_WANT_CONNECT:
1385 printf("SSL_ERROR_WANT_CONNECT\n");
1386 break;
1387 case SSL_ERROR_WANT_ACCEPT:
1388 printf("SSL_ERROR_WANT_ACCEPT\n");
1389 break;
1390 case SSL_ERROR_WANT_X509_LOOKUP:
1391 printf("SSL_ERROR_WANT_X509_LOOKUP\n");
1392 break;
1393 case SSL_ERROR_SYSCALL:
1394 {
1395 // http://www.openssl.org/docs/ssl/SSL_get_error.html
1396 char buff[1024];
1397 unsigned long ege = ERR_get_error();
1398 if (ege==0 && res==0)
1399 printf("SSL_ERROR_SYSCALL EOF in violation of the protocol\n");
1400 else if (ege==0 && res==-1) {
1401 strerror_s(buff, errno);
1402 printf("SSL_ERROR_SYSCALL %s\n", buff);
1403 }
1404 else
1405 printf("SSL_ERROR_SYSCALL %s\n", ERR_error_string(ege, buff));
1406 }
1407 break;
1408 case SSL_ERROR_SSL:
1409 printf("SSL_ERROR_SSL\n");
1410 break;
1411 }
1412
1413 }
1414
1415 if (res!=1)
1416 {
1417 SSL_free(ssl);
1418 ssl=0;
1419 return false;
1420 }
1421 return true;
1422 }
1423 void RemoteClient::DisconnectSSL(void)
1424 {
1425 if (ssl)
1426 SSL_shutdown (ssl); /* send SSL/TLS close_notify */
1427 }
1428 void RemoteClient::FreeSSL(void)
1429 {
1430 if (ssl)
1431 SSL_free (ssl);
1432 }
1433 int RemoteClient::Send(const char *data, unsigned int length)
1434 {
1435 if (ssl)
1436 return SSL_write (ssl, data, length);
1437 else
1438 return send__(socket, data, length, 0);
1439 }
1440 int RemoteClient::Recv(char *data, const int dataSize)
1441 {
1442 if (ssl)
1443 return SSL_read (ssl, data, dataSize);
1444 else
1445 return recv__(socket, data, dataSize, 0);
1446 }
1447 #else
1448 int RemoteClient::Send(const char *data, unsigned int length)
1449 {
1450 #ifdef __native_client__
1451 return -1;
1452 #else
1453 return send__(socket, data, length, 0);
1454 #endif
1455 }
1456 int RemoteClient::Recv(char *data, const int dataSize)
1457 {
1458 #ifdef __native_client__
1459 return -1;
1460 #else
1461 return recv__(socket, data, dataSize, 0);
1462 #endif
1463 }
1464 #endif
1465
1466 #ifdef _MSC_VER
1467 #pragma warning( pop )
1468 #endif
1469
1470 #endif // _RAKNET_SUPPORT_*