| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- /*
- * 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
|