forked from facebookarchive/RakNet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRakNetSocket2.h
453 lines (333 loc) · 12.7 KB
/
RakNetSocket2.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
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
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
/*
* Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#ifndef __RAKNET_SOCKET_2_H
#define __RAKNET_SOCKET_2_H
#include "RakNetTypes.h"
#include "MTUSize.h"
#include "LocklessTypes.h"
#include "RakThread.h"
#include "DS_ThreadsafeAllocatingQueue.h"
#include "Export.h"
// For CFSocket
// https://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFSocketRef/Reference/reference.html
// Reason: http://sourceforge.net/p/open-dis/discussion/683284/thread/0929d6a0
#if defined(__APPLE__)
#import <CoreFoundation/CoreFoundation.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif
// #define TEST_NATIVE_CLIENT_ON_WINDOWS
#ifdef TEST_NATIVE_CLIENT_ON_WINDOWS
#define __native_client__
typedef int PP_Resource;
#endif
namespace RakNet
{
class RakNetSocket2;
struct RNS2_BerkleyBindParameters;
struct RNS2_SendParameters;
typedef int RNS2Socket;
enum RNS2BindResult
{
BR_SUCCESS,
BR_REQUIRES_RAKNET_SUPPORT_IPV6_DEFINE,
BR_FAILED_TO_BIND_SOCKET,
BR_FAILED_SEND_TEST,
};
typedef int RNS2SendResult;
enum RNS2Type
{
RNS2T_WINDOWS_STORE_8,
RNS2T_PS3,
RNS2T_PS4,
RNS2T_CHROME,
RNS2T_VITA,
RNS2T_XBOX_360,
RNS2T_XBOX_720,
RNS2T_WINDOWS,
RNS2T_LINUX
};
struct RNS2_SendParameters
{
RNS2_SendParameters() {ttl=0;}
char *data;
int length;
SystemAddress systemAddress;
int ttl;
};
struct RNS2RecvStruct
{
char data[MAXIMUM_MTU_SIZE];
int bytesRead;
SystemAddress systemAddress;
RakNet::TimeUS timeRead;
RakNetSocket2 *socket;
};
class RakNetSocket2Allocator
{
public:
static RakNetSocket2* AllocRNS2(void);
static void DeallocRNS2(RakNetSocket2 *s);
};
class RAK_DLL_EXPORT RNS2EventHandler
{
public:
RNS2EventHandler() {}
virtual ~RNS2EventHandler() {}
// bufferedPackets.Push(recvFromStruct);
// quitAndDataEvents.SetEvent();
virtual void OnRNS2Recv(RNS2RecvStruct *recvStruct)=0;
virtual void DeallocRNS2RecvStruct(RNS2RecvStruct *s, const char *file, unsigned int line)=0;
virtual RNS2RecvStruct *AllocRNS2RecvStruct(const char *file, unsigned int line)=0;
// recvFromStruct=bufferedPackets.Allocate( _FILE_AND_LINE_ );
// DataStructures::ThreadsafeAllocatingQueue<RNS2RecvStruct> bufferedPackets;
};
class RakNetSocket2
{
public:
RakNetSocket2();
virtual ~RakNetSocket2();
// In order for the handler to trigger, some platforms must call PollRecvFrom, some platforms this create an internal thread.
void SetRecvEventHandler(RNS2EventHandler *_eventHandler);
virtual RNS2SendResult Send( RNS2_SendParameters *sendParameters, const char *file, unsigned int line )=0;
RNS2Type GetSocketType(void) const;
void SetSocketType(RNS2Type t);
bool IsBerkleySocket(void) const;
SystemAddress GetBoundAddress(void) const;
unsigned int GetUserConnectionSocketIndex(void) const;
void SetUserConnectionSocketIndex(unsigned int i);
RNS2EventHandler * GetEventHandler(void) const;
// ----------- STATICS ------------
static void GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] );
static void DomainNameToIP( const char *domainName, char ip[65] );
protected:
RNS2EventHandler *eventHandler;
RNS2Type socketType;
SystemAddress boundAddress;
unsigned int userConnectionSocketIndex;
};
#if defined(WINDOWS_STORE_RT)
ref class ListenerContext;
// #include <collection.h>
//#include <map>
#include "DS_List.h"
class RNS2_WindowsStore8 : public RakNetSocket2
{
public:
RNS2_WindowsStore8();
~RNS2_WindowsStore8();
virtual RNS2SendResult Send( RNS2_SendParameters *sendParameters, const char *file, unsigned int line );
RNS2BindResult Bind( Platform::String ^localServiceName );
// ----------- STATICS ------------
static void GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] );
static void DomainNameToIP( const char *domainName, char ip[65] );
static int WinRTInet_Addr(const char * cp);
static int WinRTSetSockOpt(Windows::Networking::Sockets::DatagramSocket ^s,
int level,
int optname,
const char * optval,
socklen_t optlen);
static int WinRTIOCTLSocket(Windows::Networking::Sockets::DatagramSocket ^s,
long cmd,
unsigned long *argp);
static int WinRTGetSockName(Windows::Networking::Sockets::DatagramSocket ^s,
struct sockaddr *name,
socklen_t* namelen);
static RNS2_WindowsStore8 *GetRNS2FromDatagramSocket(Windows::Networking::Sockets::DatagramSocket^ s);
protected:
static DataStructures::List<RNS2_WindowsStore8*> rns2List;
static SimpleMutex rns2ListMutex;
Windows::Networking::Sockets::DatagramSocket^ listener;
// Platform::Collections::Map<Windows::Storage::Streams::IOutputStream> ^outputStreamMap;
// Platform::Collections::Map<String^, int>^ m;
//std::map<> m;
ListenerContext^ listenerContext;
};
#elif defined(__native_client__)
struct NativeClientBindParameters
{
_PP_Instance_ nativeClientInstance;
unsigned short port;
const char *forceHostAddress;
bool is_ipv6;
RNS2EventHandler *eventHandler;
};
class RNS2_NativeClient;
struct RNS2_SendParameters_NativeClient : public RNS2_SendParameters
{
RNS2_NativeClient *socket2;
};
class RNS2_NativeClient : public RakNetSocket2
{
public:
RNS2_NativeClient();
virtual ~RNS2_NativeClient();
RNS2BindResult Bind( NativeClientBindParameters *bindParameters, const char *file, unsigned int line );
RNS2SendResult Send( RNS2_SendParameters *sendParameters, const char *file, unsigned int line );
const NativeClientBindParameters *GetBindings(void) const;
// ----------- STATICS ------------
static bool IsPortInUse(unsigned short port, const char *hostAddress, unsigned short addressFamily, int type );
static void GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] );
// RNS2_NativeClient doesn't automatically call recvfrom in a thread - user must call Update() from the main thread
// This causes buffered sends to send, until send is asynch pending
// It causes recvfrom events to trigger the callback, and push a message to the event handler
//
// Example:
//
// DataStructures::List< RakNet::RakNetSocket2* > sockets;
// rakPeerInterface->GetSockets(sockets);
// for (unsigned int i=0; i < sockets.Size(); i++)
// {
// ((RNS2_NativeClient*)sockets[i])->Update();
// }
void Update(void);
protected:
void ProcessBufferedSend(void);
static void SendImmediate(RNS2_SendParameters_NativeClient *sp);
static void DeallocSP(RNS2_SendParameters_NativeClient *sp);
static RNS2_SendParameters_NativeClient* CloneSP(RNS2_SendParameters *sp, RNS2_NativeClient *socket2, const char *file, unsigned int line);
static void onRecvFrom(void* pData, int32_t dataSize);
void IssueReceiveCall(void);
static void onSocketBound(void* pData, int32_t dataSize);
static void onSendTo(void* pData, int32_t dataSize);
void BufferSend( RNS2_SendParameters *sendParameters, const char *file, unsigned int line );
PP_Resource rns2Socket;
NativeClientBindParameters binding;
bool sendInProgress;
SimpleMutex sendInProgressMutex;
enum BindState
{
BS_UNBOUND,
BS_IN_PROGRESS,
BS_BOUND,
BS_FAILED
} bindState;
DataStructures::Queue<RNS2_SendParameters_NativeClient*> bufferedSends;
SimpleMutex bufferedSendsMutex;
};
#else // defined(WINDOWS_STORE_RT)
struct RNS2_BerkleyBindParameters
{
// Input parameters
unsigned short port;
char *hostAddress;
unsigned short addressFamily; // AF_INET or AF_INET6
int type; // SOCK_DGRAM
int protocol; // 0
bool nonBlockingSocket;
int setBroadcast;
int setIPHdrIncl;
int doNotFragment;
int pollingThreadPriority;
RNS2EventHandler *eventHandler;
unsigned short remotePortRakNetWasStartedOn_PS3_PS4_PSP2;
};
// Every platform except Windows Store 8 can use the Berkley sockets interface
class IRNS2_Berkley : public RakNetSocket2
{
public:
// ----------- STATICS ------------
// For addressFamily, use AF_INET
// For type, use SOCK_DGRAM
static bool IsPortInUse(unsigned short port, const char *hostAddress, unsigned short addressFamily, int type );
// ----------- MEMBERS ------------
virtual RNS2BindResult Bind( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line )=0;
};
// Every platform that uses Berkley sockets, except native client, can compile some common functions
class RNS2_Berkley : public IRNS2_Berkley
{
public:
RNS2_Berkley();
virtual ~RNS2_Berkley();
int CreateRecvPollingThread(int threadPriority);
void SignalStopRecvPollingThread(void);
void BlockOnStopRecvPollingThread(void);
const RNS2_BerkleyBindParameters *GetBindings(void) const;
RNS2Socket GetSocket(void) const;
void SetDoNotFragment( int opt );
protected:
// Used by other classes
RNS2BindResult BindShared( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line );
RNS2BindResult BindSharedIPV4( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line );
RNS2BindResult BindSharedIPV4And6( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line );
static void GetSystemAddressIPV4 ( RNS2Socket rns2Socket, SystemAddress *systemAddressOut );
static void GetSystemAddressIPV4And6 ( RNS2Socket rns2Socket, SystemAddress *systemAddressOut );
// Internal
void SetNonBlockingSocket(unsigned long nonblocking);
void SetSocketOptions(void);
void SetBroadcastSocket(int broadcast);
void SetIPHdrIncl(int ipHdrIncl);
void RecvFromBlocking(RNS2RecvStruct *recvFromStruct);
void RecvFromBlockingIPV4(RNS2RecvStruct *recvFromStruct);
void RecvFromBlockingIPV4And6(RNS2RecvStruct *recvFromStruct);
RNS2Socket rns2Socket;
RNS2_BerkleyBindParameters binding;
unsigned RecvFromLoopInt(void);
RakNet::LocklessUint32_t isRecvFromLoopThreadActive;
volatile bool endThreads;
// Constructor not called!
#if defined(__APPLE__)
// http://sourceforge.net/p/open-dis/discussion/683284/thread/0929d6a0
CFSocketRef _cfSocket;
#endif
static RAK_THREAD_DECLARATION(RecvFromLoop);
};
#if defined(_WIN32) || defined(__GNUC__) || defined(__GCCXML__) || defined(__S3E__)
class RNS2_Windows_Linux_360
{
public:
protected:
static RNS2SendResult Send_Windows_Linux_360NoVDP( RNS2Socket rns2Socket, RNS2_SendParameters *sendParameters, const char *file, unsigned int line );
};
#endif
#if defined(_WIN32)
class RAK_DLL_EXPORT SocketLayerOverride
{
public:
SocketLayerOverride() {}
virtual ~SocketLayerOverride() {}
/// Called when SendTo would otherwise occur.
virtual int RakNetSendTo( const char *data, int length, const SystemAddress &systemAddress )=0;
/// Called when RecvFrom would otherwise occur. Return number of bytes read. Write data into dataOut
// Return -1 to use RakNet's normal recvfrom, 0 to abort RakNet's normal recvfrom, and positive to return data
virtual int RakNetRecvFrom( char dataOut[ MAXIMUM_MTU_SIZE ], SystemAddress *senderOut, bool calledFromMainThread )=0;
};
class RNS2_Windows : public RNS2_Berkley, public RNS2_Windows_Linux_360
{
public:
RNS2_Windows();
virtual ~RNS2_Windows();
RNS2BindResult Bind( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line );
RNS2SendResult Send( RNS2_SendParameters *sendParameters, const char *file, unsigned int line );
void SetSocketLayerOverride(SocketLayerOverride *_slo);
SocketLayerOverride* GetSocketLayerOverride(void);
// ----------- STATICS ------------
static void GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] );
protected:
static void GetMyIPIPV4( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] );
static void GetMyIPIPV4And6( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] );
SocketLayerOverride *slo;
};
#else
class RNS2_Linux : public RNS2_Berkley, public RNS2_Windows_Linux_360
{
public:
RNS2BindResult Bind( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line );
RNS2SendResult Send( RNS2_SendParameters *sendParameters, const char *file, unsigned int line );
// ----------- STATICS ------------
static void GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] );
protected:
static void GetMyIPIPV4( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] );
static void GetMyIPIPV4And6( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] );
};
#endif // Linux
#endif // #elif !defined(WINDOWS_STORE_RT)
} // namespace RakNet
#endif // __RAKNET_SOCKET_2_H