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
UDPForwarder.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/UDPForwarder.h"
17
18 #if _RAKNET_SUPPORT_UDPForwarder==1
19
20 #include "slikenet/GetTime.h"
21 #include "slikenet/MTUSize.h"
22 #include "slikenet/SocketLayer.h"
23 #include "slikenet/WSAStartupSingleton.h"
24 #include "slikenet/sleep.h"
25 #include "slikenet/DS_OrderedList.h"
26 #include "slikenet/LinuxStrings.h"
27 #include "slikenet/SocketDefines.h"
28 #include "slikenet/VitaIncludes.h"
29 #include "errno.h"
30
31 #ifdef _WIN32
32 #include <tchar.h>
33 #else
34 #ifndef _T
35 #define _T(x) (x)
36 #endif
37 #include <sys/types.h> // used for getaddrinfo()
38 #include <sys/socket.h> // used for getaddrinfo()
39 #include <netdb.h> // used for getaddrinfo()
40 #endif
41
42 #ifndef INVALID_SOCKET
43 #define INVALID_SOCKET -1
44 #endif
45
46 using namespace SLNet;
47 static const unsigned short DEFAULT_MAX_FORWARD_ENTRIES=64;
48
49 namespace SLNet
50 {
51 RAK_THREAD_DECLARATION(UpdateUDPForwarderGlobal);
52 }
53
54 UDPForwarder::ForwardEntry::ForwardEntry()
55 {
56 socket=INVALID_SOCKET;
57 timeLastDatagramForwarded= SLNet::GetTimeMS();
58 addr1Confirmed=UNASSIGNED_SYSTEM_ADDRESS;
59 addr2Confirmed=UNASSIGNED_SYSTEM_ADDRESS;
60 }
61 UDPForwarder::ForwardEntry::~ForwardEntry() {
62 if (socket!=INVALID_SOCKET)
63 closesocket__(socket);
64 }
65
66 UDPForwarder::UDPForwarder()
67 {
68 #ifdef _WIN32
69 WSAStartupSingleton::AddRef();
70 #endif
71
72 maxForwardEntries=DEFAULT_MAX_FORWARD_ENTRIES;
73 nextInputId=0;
74 startForwardingInput.SetPageSize(sizeof(StartForwardingInputStruct)*16);
75 stopForwardingCommands.SetPageSize(sizeof(StopForwardingStruct)*16);
76 }
77 UDPForwarder::~UDPForwarder()
78 {
79 Shutdown();
80
81 #ifdef _WIN32
82 WSAStartupSingleton::Deref();
83 #endif
84 }
85 void UDPForwarder::Startup(void)
86 {
87 if (isRunning.GetValue()>0)
88 return;
89
90 isRunning.Increment();
91
92 int errorCode;
93
94
95
96 errorCode = SLNet::RakThread::Create(UpdateUDPForwarderGlobal, this);
97
98 if ( errorCode != 0 )
99 {
100 RakAssert(0);
101 return;
102 }
103
104 while (threadRunning.GetValue()==0)
105 RakSleep(30);
106 }
107 void UDPForwarder::Shutdown(void)
108 {
109 if (isRunning.GetValue()==0)
110 return;
111 isRunning.Decrement();
112
113 while (threadRunning.GetValue()>0)
114 RakSleep(30);
115
116 unsigned int j;
117 for (j=0; j < forwardListNotUpdated.Size(); j++)
118 SLNet::OP_DELETE(forwardListNotUpdated[j],_FILE_AND_LINE_);
119 forwardListNotUpdated.Clear(false, _FILE_AND_LINE_);
120 }
121 void UDPForwarder::SetMaxForwardEntries(unsigned short maxEntries)
122 {
123 RakAssert(maxEntries>0 && maxEntries<65535/2);
124 maxForwardEntries=maxEntries;
125 }
126 int UDPForwarder::GetMaxForwardEntries(void) const
127 {
128 return maxForwardEntries;
129 }
130 int UDPForwarder::GetUsedForwardEntries(void) const
131 {
132 return (int) forwardListNotUpdated.Size();
133 }
134 UDPForwarderResult UDPForwarder::StartForwarding(SystemAddress source, SystemAddress destination, SLNet::TimeMS timeoutOnNoDataMS, const char *forceHostAddress, unsigned short socketFamily,
135 unsigned short *forwardingPort, __UDPSOCKET__ *forwardingSocket)
136 {
137 // Invalid parameters?
138 if (timeoutOnNoDataMS == 0 || timeoutOnNoDataMS > UDP_FORWARDER_MAXIMUM_TIMEOUT || source==UNASSIGNED_SYSTEM_ADDRESS || destination==UNASSIGNED_SYSTEM_ADDRESS)
139 return UDPFORWARDER_INVALID_PARAMETERS;
140
141 if (isRunning.GetValue()==0)
142 return UDPFORWARDER_NOT_RUNNING;
143
144 (void) socketFamily;
145
146 unsigned int inputId = nextInputId++;
147
148 StartForwardingInputStruct *sfis;
149 sfis = startForwardingInput.Allocate(_FILE_AND_LINE_);
150 sfis->source=source;
151 sfis->destination=destination;
152 sfis->timeoutOnNoDataMS=timeoutOnNoDataMS;
153 RakAssert(timeoutOnNoDataMS!=0);
154 if (forceHostAddress && forceHostAddress[0])
155 sfis->forceHostAddress=forceHostAddress;
156 sfis->socketFamily=socketFamily;
157 sfis->inputId=inputId;
158 startForwardingInput.Push(sfis);
159
160 for(;;)
161 {
162 RakSleep(0);
163 startForwardingOutputMutex.Lock();
164 for (unsigned int i=0; i < startForwardingOutput.Size(); i++)
165 {
166 if (startForwardingOutput[i].inputId==inputId)
167 {
168 if (startForwardingOutput[i].result==UDPFORWARDER_SUCCESS)
169 {
170 if (forwardingPort)
171 *forwardingPort = startForwardingOutput[i].forwardingPort;
172 if (forwardingSocket)
173 *forwardingSocket = startForwardingOutput[i].forwardingSocket;
174 }
175 UDPForwarderResult res = startForwardingOutput[i].result;
176 startForwardingOutput.RemoveAtIndex(i);
177 startForwardingOutputMutex.Unlock();
178 return res;
179 }
180 }
181 startForwardingOutputMutex.Unlock();
182 }
183 }
184 void UDPForwarder::StopForwarding(SystemAddress source, SystemAddress destination)
185 {
186 StopForwardingStruct *sfs;
187 sfs = stopForwardingCommands.Allocate(_FILE_AND_LINE_);
188 sfs->destination=destination;
189 sfs->source=source;
190 stopForwardingCommands.Push(sfs);
191 }
192 void UDPForwarder::RecvFrom(SLNet::TimeMS curTime, ForwardEntry *forwardEntry)
193 {
194 #ifndef __native_client__
195 char data[ MAXIMUM_MTU_SIZE ];
196
197 #if RAKNET_SUPPORT_IPV6==1
198 sockaddr_storage their_addr;
199 memset(&their_addr,0,sizeof(their_addr));
200 sockaddr* sockAddrPtr;
201 socklen_t sockLen;
202 socklen_t* socketlenPtr=(socklen_t*) &sockLen;
203 sockaddr_in *sockAddrIn;
204 sockaddr_in6 *sockAddrIn6;
205 sockLen=sizeof(their_addr);
206 sockAddrPtr=(sockaddr*) &their_addr;
207 #else
208 sockaddr_in sockAddrIn;
209 memset(&sockAddrIn,0,sizeof(sockaddr_in));
210 socklen_t len2;
211 len2 = sizeof( sockAddrIn );
212 sockAddrIn.sin_family = AF_INET;
213 #endif
214
215 #if defined(__GNUC__)
216 #if defined(MSG_DONTWAIT)
217 const int flag=MSG_DONTWAIT;
218 #else
219 const int flag=0x40;
220 #endif
221 #else
222 const int flag=0;
223 #endif
224
225 int receivedDataLen, len=0;
226 //unsigned short portnum=0;
227
228 #if RAKNET_SUPPORT_IPV6==1
229 receivedDataLen = recvfrom__( forwardEntry->socket, data, MAXIMUM_MTU_SIZE, flag, sockAddrPtr, socketlenPtr );
230 #else
231 receivedDataLen = recvfrom__( forwardEntry->socket, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sockAddrIn, ( socklen_t* ) & len2 );
232 #endif
233
234 if (receivedDataLen<0)
235 {
236 #if defined(_WIN32) && defined(_DEBUG) && !defined(WINDOWS_PHONE_8) && !defined(WINDOWS_STORE_RT)
237 DWORD dwIOError = WSAGetLastError();
238
239 if (dwIOError!=WSAECONNRESET && dwIOError!=WSAEINTR && dwIOError!=WSAETIMEDOUT && dwIOError!=WSAEWOULDBLOCK)
240 {
241 LPTSTR messageBuffer;
242 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
243 NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
244 ( LPTSTR ) & messageBuffer, 0, NULL );
245 // something has gone wrong here...
246 RAKNET_DEBUG_TPRINTF( _T("recvfrom failed:Error code - %lu\n%s"), dwIOError, messageBuffer );
247
248 //Free the buffer.
249 LocalFree( messageBuffer );
250 }
251 #else
252 if (errno!=EAGAIN
253 && errno!=0
254 #if defined(__GNUC__)
255 && errno!=EWOULDBLOCK
256 #endif
257 )
258 {
259 printf("errno=%i\n", errno);
260 }
261 #endif
262
263
264 }
265
266 if (receivedDataLen<=0)
267 return;
268
269 SystemAddress receivedAddr;
270 #if RAKNET_SUPPORT_IPV6==1
271 if (their_addr.ss_family==AF_INET)
272 {
273 sockAddrIn=(sockaddr_in *)&their_addr;
274 sockAddrIn6=0;
275 memcpy(&receivedAddr.address.addr4,sockAddrIn,sizeof(sockaddr_in));
276 }
277 else
278 {
279 sockAddrIn=0;
280 sockAddrIn6=(sockaddr_in6 *)&their_addr;
281 memcpy(&receivedAddr.address.addr6,sockAddrIn6,sizeof(sockaddr_in6));
282 }
283 #else
284 memcpy(&receivedAddr.address.addr4,&sockAddrIn,sizeof(sockaddr_in));
285 #endif
286 //portnum=receivedAddr.GetPort();
287
288 SystemAddress forwardTarget;
289
290 bool confirmed1 = forwardEntry->addr1Confirmed!=UNASSIGNED_SYSTEM_ADDRESS;
291 bool confirmed2 = forwardEntry->addr2Confirmed!=UNASSIGNED_SYSTEM_ADDRESS;
292 bool matchConfirmed1 =
293 confirmed1 &&
294 forwardEntry->addr1Confirmed==receivedAddr;
295 bool matchConfirmed2 =
296 confirmed2 &&
297 forwardEntry->addr2Confirmed==receivedAddr;
298 bool matchUnconfirmed1 = forwardEntry->addr1Unconfirmed.EqualsExcludingPort(receivedAddr);
299 bool matchUnconfirmed2 = forwardEntry->addr2Unconfirmed.EqualsExcludingPort(receivedAddr);
300
301 if (matchConfirmed1==true || (matchConfirmed2==false && confirmed1==false && matchUnconfirmed1==true))
302 {
303 // Forward to addr2
304 if (forwardEntry->addr1Confirmed==UNASSIGNED_SYSTEM_ADDRESS)
305 {
306 forwardEntry->addr1Confirmed=receivedAddr;
307 }
308 if (forwardEntry->addr2Confirmed!=UNASSIGNED_SYSTEM_ADDRESS)
309 forwardTarget=forwardEntry->addr2Confirmed;
310 else
311 forwardTarget=forwardEntry->addr2Unconfirmed;
312 }
313 else if (matchConfirmed2==true || (confirmed2==false && matchUnconfirmed2==true))
314 {
315 // Forward to addr1
316 if (forwardEntry->addr2Confirmed==UNASSIGNED_SYSTEM_ADDRESS)
317 {
318 forwardEntry->addr2Confirmed=receivedAddr;
319 }
320 if (forwardEntry->addr1Confirmed!=UNASSIGNED_SYSTEM_ADDRESS)
321 forwardTarget=forwardEntry->addr1Confirmed;
322 else
323 forwardTarget=forwardEntry->addr1Unconfirmed;
324 }
325 else
326 {
327 return;
328 }
329
330 // Forward to dest
331 len=0;
332 // sockaddr_in saOut;
333 // saOut.sin_port = forwardTarget.GetPortNetworkOrder(); // User port
334 // saOut.sin_addr.s_addr = forwardTarget.address.addr4.sin_addr.s_addr;
335 // saOut.sin_family = AF_INET;
336 do
337 {
338
339
340
341 #if RAKNET_SUPPORT_IPV6==1
342 if (forwardTarget.address.addr4.sin_family==AF_INET)
343 {
344 do
345 {
346 len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & forwardTarget.address.addr4, sizeof( sockaddr_in ) );
347 }
348 while ( len == 0 );
349 }
350 else
351 {
352 do
353 {
354 len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & forwardTarget.address.addr6, sizeof( sockaddr_in6 ) );
355 }
356 while ( len == 0 );
357 }
358 #else
359 do
360 {
361 len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & forwardTarget.address.addr4, sizeof( sockaddr_in ) );
362 }
363 while ( len == 0 );
364 #endif
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395 }
396 while ( len == 0 );
397
398 forwardEntry->timeLastDatagramForwarded=curTime;
399 #endif // __native_client__
400 }
401 void UDPForwarder::UpdateUDPForwarder(void)
402 {
403 /*
404 #if !defined(SN_TARGET_PSP2)
405 timeval tv;
406 tv.tv_sec=0;
407 tv.tv_usec=0;
408 #endif
409 */
410
411 SLNet::TimeMS curTime = SLNet::GetTimeMS();
412
413 StartForwardingInputStruct *sfis;
414 StartForwardingOutputStruct sfos;
415 sfos.forwardingSocket=INVALID_SOCKET;
416 sfos.forwardingPort=0;
417 sfos.inputId=0;
418 sfos.result=UDPFORWARDER_RESULT_COUNT;
419
420 for(;;)
421 {
422 sfis = startForwardingInput.Pop();
423 if (sfis==0)
424 break;
425
426 if (GetUsedForwardEntries()>maxForwardEntries)
427 {
428 sfos.result=UDPFORWARDER_NO_SOCKETS;
429 }
430 else
431 {
432 sfos.result=UDPFORWARDER_RESULT_COUNT;
433
434 for (unsigned int i=0; i < forwardListNotUpdated.Size(); i++)
435 {
436 if (
437 (forwardListNotUpdated[i]->addr1Unconfirmed==sfis->source &&
438 forwardListNotUpdated[i]->addr2Unconfirmed==sfis->destination)
439 ||
440 (forwardListNotUpdated[i]->addr1Unconfirmed==sfis->destination &&
441 forwardListNotUpdated[i]->addr2Unconfirmed==sfis->source)
442 )
443 {
444 ForwardEntry *fe = forwardListNotUpdated[i];
445 sfos.forwardingPort = SocketLayer::GetLocalPort ( fe->socket );
446 sfos.forwardingSocket=fe->socket;
447 sfos.result=UDPFORWARDER_FORWARDING_ALREADY_EXISTS;
448 break;
449 }
450 }
451
452 if (sfos.result==UDPFORWARDER_RESULT_COUNT)
453 {
454 int sock_opt;
455 sockaddr_in listenerSocketAddress;
456 listenerSocketAddress.sin_port = 0;
457 ForwardEntry *fe = SLNet::OP_NEW<UDPForwarder::ForwardEntry>(_FILE_AND_LINE_);
458 fe->addr1Unconfirmed=sfis->source;
459 fe->addr2Unconfirmed=sfis->destination;
460 fe->timeoutOnNoDataMS=sfis->timeoutOnNoDataMS;
461
462 #if RAKNET_SUPPORT_IPV6!=1
463 fe->socket = socket__( AF_INET, SOCK_DGRAM, 0 );
464 listenerSocketAddress.sin_family = AF_INET;
465 if (sfis->forceHostAddress.IsEmpty()==false)
466 {
467
468
469
470
471 inet_pton(AF_INET, sfis->forceHostAddress.C_String(), &listenerSocketAddress.sin_addr.s_addr);
472
473 }
474 else
475 {
476 listenerSocketAddress.sin_addr.s_addr = INADDR_ANY;
477 }
478 int ret = bind__( fe->socket, ( struct sockaddr * ) & listenerSocketAddress, sizeof( listenerSocketAddress ) );
479 if (ret==-1)
480 {
481 SLNet::OP_DELETE(fe,_FILE_AND_LINE_);
482 sfos.result=UDPFORWARDER_BIND_FAILED;
483 }
484 else
485 {
486 sfos.result=UDPFORWARDER_SUCCESS;
487 }
488
489 #else // RAKNET_SUPPORT_IPV6==1
490 struct addrinfo hints;
491 memset(&hints, 0, sizeof (addrinfo)); // make sure the struct is empty
492 hints.ai_family = sfis->socketFamily;
493 hints.ai_socktype = SOCK_DGRAM; // UDP sockets
494 hints.ai_flags = AI_PASSIVE; // fill in my IP for me
495 struct addrinfo *servinfo=0, *aip; // will point to the results
496
497 if (sfis->forceHostAddress.IsEmpty() || sfis->forceHostAddress=="UNASSIGNED_SYSTEM_ADDRESS")
498 getaddrinfo(0, "0", &hints, &servinfo);
499 else
500 getaddrinfo(sfis->forceHostAddress.C_String(), "0", &hints, &servinfo);
501
502 for (aip = servinfo; aip != NULL; aip = aip->ai_next)
503 {
504 // Open socket. The address type depends on what
505 // getaddrinfo() gave us.
506 fe->socket = socket__(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
507 if (fe->socket != INVALID_SOCKET)
508 {
509 int ret = bind__( fe->socket, aip->ai_addr, (int) aip->ai_addrlen );
510 if (ret>=0)
511 {
512 break;
513 }
514 else
515 {
516 closesocket__(fe->socket);
517 fe->socket=INVALID_SOCKET;
518 }
519 }
520 }
521
522 if (fe->socket==INVALID_SOCKET)
523 sfos.result=UDPFORWARDER_BIND_FAILED;
524 else
525 sfos.result=UDPFORWARDER_SUCCESS;
526 #endif // RAKNET_SUPPORT_IPV6==1
527
528 if (sfos.result==UDPFORWARDER_SUCCESS)
529 {
530 sfos.forwardingPort = SocketLayer::GetLocalPort ( fe->socket );
531 sfos.forwardingSocket=fe->socket;
532
533 sock_opt=1024*256;
534 setsockopt__(fe->socket, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
535 sock_opt=0;
536 setsockopt__(fe->socket, SOL_SOCKET, SO_LINGER, ( char * ) & sock_opt, sizeof ( sock_opt ) );
537 #ifdef _WIN32
538 unsigned long nonblocking = 1;
539 ioctlsocket__( fe->socket, FIONBIO, &nonblocking );
540
541
542
543 #else
544 fcntl( fe->socket, F_SETFL, O_NONBLOCK );
545 #endif
546
547 forwardListNotUpdated.Insert(fe,_FILE_AND_LINE_);
548 }
549 }
550 }
551
552 // Push result
553 sfos.inputId=sfis->inputId;
554 startForwardingOutputMutex.Lock();
555 startForwardingOutput.Push(sfos,_FILE_AND_LINE_);
556 startForwardingOutputMutex.Unlock();
557
558 startForwardingInput.Deallocate(sfis, _FILE_AND_LINE_);
559 }
560
561 StopForwardingStruct *sfs;
562
563 for(;;)
564 {
565 sfs = stopForwardingCommands.Pop();
566 if (sfs==0)
567 break;
568
569 ForwardEntry *fe;
570 for (unsigned int i=0; i < forwardListNotUpdated.Size(); i++)
571 {
572 if (
573 (forwardListNotUpdated[i]->addr1Unconfirmed==sfs->source &&
574 forwardListNotUpdated[i]->addr2Unconfirmed==sfs->destination)
575 ||
576 (forwardListNotUpdated[i]->addr1Unconfirmed==sfs->destination &&
577 forwardListNotUpdated[i]->addr2Unconfirmed==sfs->source)
578 )
579 {
580 fe = forwardListNotUpdated[i];
581 forwardListNotUpdated.RemoveAtIndexFast(i);
582 SLNet::OP_DELETE(fe, _FILE_AND_LINE_);
583 break;
584 }
585 }
586
587 stopForwardingCommands.Deallocate(sfs, _FILE_AND_LINE_);
588 }
589
590 unsigned int i;
591
592 i=0;
593 while (i < forwardListNotUpdated.Size())
594 {
595 if (curTime > forwardListNotUpdated[i]->timeLastDatagramForwarded && // Account for timestamp wrap
596 curTime > forwardListNotUpdated[i]->timeLastDatagramForwarded+forwardListNotUpdated[i]->timeoutOnNoDataMS)
597 {
598 SLNet::OP_DELETE(forwardListNotUpdated[i],_FILE_AND_LINE_);
599 forwardListNotUpdated.RemoveAtIndex(i);
600 }
601 else
602 i++;
603 }
604
605 ForwardEntry *forwardEntry;
606 for (i=0; i < forwardListNotUpdated.Size(); i++)
607 {
608 forwardEntry = forwardListNotUpdated[i];
609 RecvFrom(curTime, forwardEntry);
610 }
611 }
612
613 namespace SLNet {
614 RAK_THREAD_DECLARATION(UpdateUDPForwarderGlobal)
615 {
616
617
618
619 UDPForwarder * udpForwarder = ( UDPForwarder * ) arguments;
620
621
622 udpForwarder->threadRunning.Increment();
623 while (udpForwarder->isRunning.GetValue()>0)
624 {
625 udpForwarder->UpdateUDPForwarder();
626
627 // 12/1/2010 Do not change from 0
628 // See http://www.jenkinssoftware.com/forum/index.php?topic=4033.0;topicseen
629 // Avoid 100% reported CPU usage
630 if (udpForwarder->forwardListNotUpdated.Size()==0)
631 RakSleep(30);
632 else
633 RakSleep(0);
634 }
635 udpForwarder->threadRunning.Decrement();
636
637
638
639
640 return 0;
641
642
643 }
644
645 } // namespace SLNet
646
647 #endif // #if _RAKNET_SUPPORT_FileOperations==1