diff options
Diffstat (limited to 'LibOVR/Src/Service')
-rw-r--r-- | LibOVR/Src/Service/Service_NetClient.cpp | 275 | ||||
-rw-r--r-- | LibOVR/Src/Service/Service_NetClient.h | 54 | ||||
-rw-r--r-- | LibOVR/Src/Service/Service_NetSessionCommon.cpp | 276 | ||||
-rwxr-xr-x[-rw-r--r--] | LibOVR/Src/Service/Service_NetSessionCommon.h | 53 | ||||
-rw-r--r-- | LibOVR/Src/Service/Service_Win32_FastIPC_Client.cpp | 228 | ||||
-rw-r--r-- | LibOVR/Src/Service/Service_Win32_FastIPC_Client.h | 84 |
6 files changed, 646 insertions, 324 deletions
diff --git a/LibOVR/Src/Service/Service_NetClient.cpp b/LibOVR/Src/Service/Service_NetClient.cpp index c6af2cd..22fea89 100644 --- a/LibOVR/Src/Service/Service_NetClient.cpp +++ b/LibOVR/Src/Service/Service_NetClient.cpp @@ -25,11 +25,12 @@ limitations under the License. ************************************************************************************/ #include "Service_NetClient.h" -#include "../Net/OVR_MessageIDTypes.h" +#include "Net/OVR_MessageIDTypes.h" #if defined (OVR_OS_MAC) || defined(OVR_OS_LINUX) #define GetCurrentProcessId getpid #endif + OVR_DEFINE_SINGLETON(OVR::Service::NetClient); namespace OVR { namespace Service { @@ -37,13 +38,17 @@ namespace OVR { namespace Service { using namespace OVR::Net; +// Default connection timeout in milliseconds. +static const int kDefaultConnectionTimeoutMS = 5000; // Timeout in Milliseconds + + //// NetClient NetClient::NetClient() : - LatencyTesterAvailable(false), - HMDCount(0), - EdgeTriggeredHMDCount(false) + LatencyTesterAvailable(false), HMDCount(-1), EdgeTriggeredHMDCount(false) { + SetDefaultParameters(); + GetSession()->AddSessionListener(this); // Register RPC functions @@ -51,7 +56,7 @@ NetClient::NetClient() : Start(); - // Must be at end of function + // Must be at end of function PushDestroyCallbacks(); } @@ -69,19 +74,40 @@ void NetClient::OnThreadDestroy() onThreadDestroy(); } +void NetClient::SetDefaultParameters() +{ + ServerOptional = false; + ExtraDebugging = false; + ConnectionTimeoutMS = kDefaultConnectionTimeoutMS; +} + +void NetClient::ApplyParameters(ovrInitParams const* params) +{ + SetDefaultParameters(); + + // If connection timeout is specified, + if (params->ConnectionTimeoutMS > 0) + { + ConnectionTimeoutMS = params->ConnectionTimeoutMS; + } + + ServerOptional = (params->Flags & ovrInit_ServerOptional) != 0; + ExtraDebugging = (params->Flags & ovrInit_Debug) != 0; +} + int NetClient::Run() { SetThreadName("NetClient"); - while (!Terminated) + while (!Terminated.load(std::memory_order_relaxed)) { - // Note: There is no watchdog here because the watchdog is part of the private code + // There is no watchdog here because the watchdog is part of the private code. GetSession()->Poll(false); if (GetSession()->GetActiveSocketsCount() == 0) { - Thread::MSleep(10); + Thread::MSleep(100); } } @@ -107,8 +133,22 @@ void NetClient::OnConnected(Connection* conn) { OVR_UNUSED(conn); - OVR_DEBUG_LOG(("[NetClient] Connected to a server running version %d.%d.%d (my version=%d.%d.%d)", + OVR_DEBUG_LOG(("[NetClient] Connected to the server running SDK version " \ + "(prod=%d).%d.%d(req=%d).%d(build=%d), RPC version %d.%d.%d. " \ + "Client SDK version (prod=%d).%d.%d(req=%d).%d.(build=%d), RPC version=%d.%d.%d", + conn->RemoteCodeVersion.ProductVersion, + conn->RemoteCodeVersion.MajorVersion, + conn->RemoteCodeVersion.MinorVersion, + conn->RemoteCodeVersion.RequestedMinorVersion, + conn->RemoteCodeVersion.PatchVersion, + conn->RemoteCodeVersion.BuildNumber, conn->RemoteMajorVersion, conn->RemoteMinorVersion, conn->RemotePatchVersion, + OVR_PRODUCT_VERSION, + OVR_MAJOR_VERSION, + OVR_MINOR_VERSION, + RuntimeSDKVersion.RequestedMinorVersion, + OVR_PATCH_VERSION, + OVR_BUILD_NUMBER, RPCVersion_Major, RPCVersion_Minor, RPCVersion_Patch)); EdgeTriggeredHMDCount = false; @@ -116,12 +156,18 @@ void NetClient::OnConnected(Connection* conn) bool NetClient::Connect(bool blocking) { + // If server is optional, + if (ServerOptional && !Session::IsSingleProcess()) + { + blocking = false; // Poll: Do not block + } + // Set up bind parameters - OVR::Net::BerkleyBindParameters bbp; - bbp.Address = "::1"; // Bind to localhost only! - bbp.blockingTimeout = 5000; - OVR::Net::SockAddr sa; - sa.Set("::1", VRServicePort, SOCK_STREAM); + OVR::Net::BerkleyBindParameters bbp; + bbp.Address = "::1"; // Bind to localhost only! + bbp.blockingTimeout = ConnectionTimeoutMS; + OVR::Net::SockAddr sa; + sa.Set("::1", VRServicePort, SOCK_STREAM); // Attempt to connect OVR::Net::SessionResult result = GetSession()->ConnectPTCP(&bbp, &sa, blocking); @@ -140,7 +186,7 @@ void NetClient::Disconnect() bool NetClient::IsConnected(bool attemptReconnect, bool blockOnReconnect) { // If it was able to connect, - if (GetSession()->GetConnectionCount() > 0) + if (GetSession()->ConnectionSuccessful()) { return true; } @@ -150,7 +196,7 @@ bool NetClient::IsConnected(bool attemptReconnect, bool blockOnReconnect) Connect(blockOnReconnect); // If it connected, - if (GetSession()->GetConnectionCount() > 0) + if (GetSession()->ConnectionSuccessful()) { return true; } @@ -182,21 +228,39 @@ bool NetClient::GetRemoteProtocolVersion(int& major, int& minor, int& patch) return false; } +void NetClient::GetLocalSDKVersion(SDKVersion& requestedSDKVersion) +{ + requestedSDKVersion = RuntimeSDKVersion; +} + +bool NetClient::GetRemoteSDKVersion(SDKVersion& remoteSDKVersion) +{ + Ptr<Connection> conn = GetSession()->GetConnectionAtIndex(0); + + if (conn) + { + remoteSDKVersion = conn->RemoteCodeVersion; + return true; + } + + return false; +} + //// NetClient API const char* NetClient::GetStringValue(VirtualHmdId hmd, const char* key, const char* default_val) { - if (!IsConnected(true, true)) + // If a null value is provided, + if (!default_val) { - return ""; + default_val = ""; } - // If a null value is provided, - if (!default_val) - { - default_val = ""; - } + if (!IsConnected(true, true)) + { + return default_val; + } ProfileGetValue1_Str = default_val; @@ -206,11 +270,11 @@ const char* NetClient::GetStringValue(VirtualHmdId hmd, const char* key, const c bsOut.Write(default_val); if (!GetRPC1()->CallBlocking("GetStringValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) { - return ""; + return default_val; } if (!returnData.Read(ProfileGetValue1_Str)) { - OVR_ASSERT(false); + OVR_ASSERT(false); //This assert will hit if you tamper or restart the service mid-call. } return ProfileGetValue1_Str.ToCStr(); } @@ -227,12 +291,12 @@ bool NetClient::GetBoolValue(VirtualHmdId hmd, const char* key, bool default_val bsOut.Write(default_val); if (!GetRPC1()->CallBlocking("GetBoolValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) { - return default_val; + return default_val; } uint8_t out = 0; if (!returnData.Read(out)) { - OVR_ASSERT(false); + OVR_ASSERT(false); //This assert will hit if you tamper or restart the service mid-call. } return out != 0; } @@ -249,12 +313,12 @@ int NetClient::GetIntValue(VirtualHmdId hmd, const char* key, int default_val) bsOut.Write(default_val); if (!GetRPC1()->CallBlocking("GetIntValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) { - return default_val; + return default_val; } int32_t out = (int32_t)default_val; if (!returnData.Read(out)) { - OVR_ASSERT(false); + OVR_ASSERT(false); //This assert will hit if you tamper or restart the service mid-call. } return out; } @@ -271,10 +335,13 @@ double NetClient::GetNumberValue(VirtualHmdId hmd, const char* key, double defau bsOut.Write(default_val); if (!GetRPC1()->CallBlocking("GetNumberValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) { - return default_val; + return default_val; } double out = 0.; - returnData.Read(out); + if (!returnData.Read(out)) + { + OVR_ASSERT(false); //This assert will hit if you tamper or restart the service mid-call. + } return out; } int NetClient::GetNumberValues(VirtualHmdId hmd, const char* key, double* values, int num_vals) @@ -293,7 +360,7 @@ int NetClient::GetNumberValues(VirtualHmdId hmd, const char* key, double* values if (!GetRPC1()->CallBlocking("GetNumberValues_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) { - return 0; + return 0; } int32_t out = 0; @@ -439,7 +506,7 @@ int NetClient::Hmd_Detect() { if (!IsConnected(true, false)) { - return 0; + return -1; } // If using edge-triggered HMD counting, @@ -451,21 +518,21 @@ int NetClient::Hmd_Detect() // Otherwise: We need to ask the first time - OVR::Net::BitStream bsOut, returnData; + OVR::Net::BitStream bsOut, returnData; - if (!GetRPC1()->CallBlocking("Hmd_Detect_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) - { - return 0; - } + if (!GetRPC1()->CallBlocking("Hmd_Detect_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) + { + return -1; + } int32_t out = 0; if (!returnData.Read(out)) { - OVR_ASSERT(false); + OVR_ASSERT(false); //This assert will hit if you tamper or restart the service mid-call. } HMDCount = out; EdgeTriggeredHMDCount = true; - return out; + return out; } bool NetClient::Hmd_Create(int index, HMDNetworkInfo* netInfo) @@ -475,21 +542,21 @@ bool NetClient::Hmd_Create(int index, HMDNetworkInfo* netInfo) return false; } - OVR::Net::BitStream bsOut, returnData; + OVR::Net::BitStream bsOut, returnData; int32_t w = (int32_t)index; - bsOut.Write(w); + bsOut.Write(w); // Need the Pid for driver mode pid_t pid = GetCurrentProcessId(); bsOut.Write(pid); - if (!GetRPC1()->CallBlocking("Hmd_Create_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) - { - return false; - } + if (!GetRPC1()->CallBlocking("Hmd_Create_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) + { + return false; + } - return netInfo->Deserialize(&returnData); + return netInfo->Serialize(&returnData, false); } bool NetClient::GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode) @@ -566,15 +633,19 @@ bool NetClient::Hmd_AttachToWindow(VirtualHmdId hmd, void* hWindow) OVR::Net::BitStream bsOut; bsOut.Write(hmd); + uint64_t hWinWord = 0; #ifdef OVR_OS_LINUX - if (hWindow == NULL) - { - return false; - } - unsigned long hWinWord = *(unsigned long *)hWindow; + if (hWindow == NULL) + { + return false; + } + hWinWord = *(uint64_t *)&hWindow; + #elif defined(OVR_OS_WIN32) + hWinWord = (UPInt)hWindow; #else - UInt64 hWinWord = (UPInt)hWindow; + OVR_UNUSED(hWindow); #endif + bsOut.Write(hWinWord); if (!GetRPC1()->CallBlocking("Hmd_AttachToWindow_1", &bsOut, GetSession()->GetConnectionAtIndex(0))) @@ -592,9 +663,9 @@ void NetClient::Hmd_Release(VirtualHmdId hmd) return; } - OVR::Net::BitStream bsOut; - bsOut.Write(hmd); - bool result = GetRPC1()->CallBlocking("Hmd_Release_1", &bsOut, GetSession()->GetConnectionAtIndex(0)); + OVR::Net::BitStream bsOut; + bsOut.Write(hmd); + bool result = GetRPC1()->CallBlocking("Hmd_Release_1", &bsOut, GetSession()->GetConnectionAtIndex(0)); OVR_ASSERT_AND_UNUSED(result, result); } @@ -612,16 +683,16 @@ const char* NetClient::Hmd_GetLastError(VirtualHmdId hmd) } OVR::Net::BitStream bsOut, returnData; - bsOut.Write(hmd); + bsOut.Write(hmd); if (!GetRPC1()->CallBlocking("Hmd_GetLastError_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) - { - return Hmd_GetLastError_Str.ToCStr(); - } + { + return Hmd_GetLastError_Str.ToCStr(); + } if (!returnData.Read(Hmd_GetLastError_Str)) { OVR_ASSERT(false); } - return Hmd_GetLastError_Str.ToCStr(); + return Hmd_GetLastError_Str.ToCStr(); } @@ -634,14 +705,14 @@ bool NetClient::Hmd_GetHmdInfo(VirtualHmdId hmd, HMDInfo* hmdInfo) return false; } - OVR::Net::BitStream bsOut, returnData; - bsOut.Write(hmd); - if (!GetRPC1()->CallBlocking("Hmd_GetHmdInfo_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) - { - return false; - } + OVR::Net::BitStream bsOut, returnData; + bsOut.Write(hmd); + if (!GetRPC1()->CallBlocking("Hmd_GetHmdInfo_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) + { + return false; + } - return NetSessionCommon::DeserializeHMDInfo(&returnData, hmdInfo); + return NetSessionCommon::SerializeHMDInfo(&returnData, hmdInfo, false); } @@ -653,19 +724,19 @@ unsigned int NetClient::Hmd_GetEnabledCaps(VirtualHmdId hmd) return 0; } - OVR::Net::BitStream bsOut, returnData; - bsOut.Write(hmd); - if (!GetRPC1()->CallBlocking("Hmd_GetEnabledCaps_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) - { - return 0; - } + OVR::Net::BitStream bsOut, returnData; + bsOut.Write(hmd); + if (!GetRPC1()->CallBlocking("Hmd_GetEnabledCaps_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) + { + return 0; + } uint32_t c = 0; if (!returnData.Read(c)) { - OVR_ASSERT(false); + OVR_ASSERT(false); //This assert will hit if you tamper or restart the service mid-call. } - return c; + return c; } // Returns new caps after modification @@ -676,21 +747,21 @@ unsigned int NetClient::Hmd_SetEnabledCaps(VirtualHmdId hmd, unsigned int hmdCap return 0; } - OVR::Net::BitStream bsOut, returnData; - bsOut.Write(hmd); + OVR::Net::BitStream bsOut, returnData; + bsOut.Write(hmd); uint32_t c = (uint32_t)hmdCaps; - bsOut.Write(c); + bsOut.Write(c); - if (!GetRPC1()->CallBlocking("Hmd_SetEnabledCaps_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) - { - return 0; - } + if (!GetRPC1()->CallBlocking("Hmd_SetEnabledCaps_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) + { + return 0; + } c = 0; if (!returnData.Read(c)) { - OVR_ASSERT(false); + OVR_ASSERT(false); //This assert will hit if you tamper or restart the service mid-call. } return c; } @@ -706,18 +777,18 @@ bool NetClient::Hmd_ConfigureTracking(VirtualHmdId hmd, unsigned supportedCaps, return false; } - OVR::Net::BitStream bsOut, returnData; - bsOut.Write(hmd); + OVR::Net::BitStream bsOut, returnData; + bsOut.Write(hmd); uint32_t w_sc = supportedCaps; bsOut.Write(w_sc); uint32_t w_rc = requiredCaps; bsOut.Write(w_rc); - if (!GetRPC1()->CallBlocking("Hmd_ConfigureTracking_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) - { - return false; - } + if (!GetRPC1()->CallBlocking("Hmd_ConfigureTracking_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) + { + return false; + } uint8_t b; if (!returnData.Read(b)) @@ -725,23 +796,28 @@ bool NetClient::Hmd_ConfigureTracking(VirtualHmdId hmd, unsigned supportedCaps, OVR_ASSERT(false); } - return b != 0; + return b != 0; } -void NetClient::Hmd_ResetTracking(VirtualHmdId hmd) +void NetClient::Hmd_ResetTracking(VirtualHmdId hmd, bool visionReset) { if (!IsConnected(false, false)) { return; } - OVR::Net::BitStream bsOut; - bsOut.Write(hmd); - if (!GetRPC1()->CallBlocking("Hmd_ResetTracking_1", &bsOut, GetSession()->GetConnectionAtIndex(0))) - { - return; - } + OVR::Net::BitStream bsOut; + bsOut.Write(hmd); + + int32_t w_visionReset; + w_visionReset = visionReset ? 1 : 0; + bsOut.Write(w_visionReset); + + if (!GetRPC1()->CallBlocking("Hmd_ResetTracking_1", &bsOut, GetSession()->GetConnectionAtIndex(0))) + { + return; + } } bool NetClient::LatencyUtil_ProcessInputs(double startTestSeconds, unsigned char rgbColorOut[3]) @@ -817,7 +893,8 @@ bool NetClient::ShutdownServer() void NetClient::registerRPC() { #define RPC_REGISTER_SLOT(observerScope, functionName) \ - observerScope.SetHandler(OVR::Net::Plugins::RPCSlot::FromMember<NetClient, &NetClient::functionName>(this)); pRPC->RegisterSlot(OVR_STRINGIZE(functionName), observerScope); + observerScope.SetHandler(OVR::Net::Plugins::RPCSlot::FromMember<NetClient, &NetClient::functionName>(this)); \ + pRPC->RegisterSlot(OVR_STRINGIZE(functionName), &observerScope); // Register RPC functions: RPC_REGISTER_SLOT(InitialServerStateScope, InitialServerState_1); diff --git a/LibOVR/Src/Service/Service_NetClient.h b/LibOVR/Src/Service/Service_NetClient.h index ab7906e..508c485 100644 --- a/LibOVR/Src/Service/Service_NetClient.h +++ b/LibOVR/Src/Service/Service_NetClient.h @@ -27,11 +27,11 @@ limitations under the License. #ifndef OVR_Service_NetClient_h #define OVR_Service_NetClient_h -#include "../Net/OVR_NetworkTypes.h" +#include "Net/OVR_NetworkTypes.h" #include "Service_NetSessionCommon.h" -#include "../Kernel/OVR_System.h" -#include "../OVR_CAPI.h" -#include "../Util/Util_Render_Stereo.h" +#include "Kernel/OVR_System.h" +#include "OVR_CAPI.h" +#include "Util/Util_Render_Stereo.h" namespace OVR { namespace Service { @@ -48,28 +48,22 @@ class NetClient : public NetSessionCommon, OVR_DECLARE_SINGLETON(NetClient); virtual void OnThreadDestroy(); - // Status - bool LatencyTesterAvailable; - int HMDCount; - bool EdgeTriggeredHMDCount; - - virtual void OnReceive(Net::ReceivePayload* pPayload, Net::ListenerReceiveResult* lrrOut); - virtual void OnDisconnected(Net::Connection* conn); - virtual void OnConnected(Net::Connection* conn); - - virtual int Run(); - public: bool Connect(bool blocking); bool IsConnected(bool attemptReconnect, bool blockOnReconnect); void Disconnect(); void GetLocalProtocolVersion(int& major, int& minor, int& patch); - // This function may fail if it is not connected + void GetLocalSDKVersion(SDKVersion& requestedSDKVersion); + + // These functions may fail if it is not connected bool GetRemoteProtocolVersion(int& major, int& minor, int& patch); + bool GetRemoteSDKVersion(SDKVersion& remoteSDKVersion); void SetLastError(String str); + void ApplyParameters(ovrInitParams const* params); + public: // Persistent key-value storage const char* GetStringValue(VirtualHmdId hmd, const char* key, const char* default_val); @@ -112,7 +106,7 @@ public: // *** Tracking Setup bool Hmd_ConfigureTracking(VirtualHmdId hmd, unsigned supportedCaps, unsigned requiredCaps); - void Hmd_ResetTracking(VirtualHmdId hmd); + void Hmd_ResetTracking(VirtualHmdId hmd, bool visionReset); // TBD: Camera frames bool LatencyUtil_ProcessInputs(double startTestSeconds, unsigned char rgbColorOut[3]); @@ -121,25 +115,43 @@ public: bool ShutdownServer(); protected: + // Status + bool LatencyTesterAvailable; + int HMDCount; + bool EdgeTriggeredHMDCount; + String Hmd_GetLastError_Str; String LatencyUtil_GetResultsString_Str; String ProfileGetValue1_Str, ProfileGetValue3_Str; + // Parameters passed to ovr_Initialize() + bool ServerOptional; // Server connection is optional? + bool ExtraDebugging; // Extra debugging enabled? + int ConnectionTimeoutMS; // Connection timeout in milliseconds + + void SetDefaultParameters(); + protected: + virtual void OnReceive(Net::ReceivePayload* pPayload, Net::ListenerReceiveResult* lrrOut); + virtual void OnDisconnected(Net::Connection* conn); + virtual void OnConnected(Net::Connection* conn); + + virtual int Run(); + //// Push Notifications: void registerRPC(); - ObserverScope<Net::Plugins::RPCSlot> InitialServerStateScope; + CallbackListener<Net::Plugins::RPCSlot> InitialServerStateScope; void InitialServerState_1(BitStream* userData, ReceivePayload* pPayload); - ObserverScope<Net::Plugins::RPCSlot> LatencyTesterAvailableScope; + CallbackListener<Net::Plugins::RPCSlot> LatencyTesterAvailableScope; void LatencyTesterAvailable_1(BitStream* userData, ReceivePayload* pPayload); - ObserverScope<Net::Plugins::RPCSlot> DefaultLogOutputScope; + CallbackListener<Net::Plugins::RPCSlot> DefaultLogOutputScope; void DefaultLogOutput_1(BitStream* userData, ReceivePayload* pPayload); - ObserverScope<Net::Plugins::RPCSlot> HMDCountUpdateScope; + CallbackListener<Net::Plugins::RPCSlot> HMDCountUpdateScope; void HMDCountUpdate_1(BitStream* userData, ReceivePayload* pPayload); }; diff --git a/LibOVR/Src/Service/Service_NetSessionCommon.cpp b/LibOVR/Src/Service/Service_NetSessionCommon.cpp index ba2c773..4a9fda6 100644 --- a/LibOVR/Src/Service/Service_NetSessionCommon.cpp +++ b/LibOVR/Src/Service/Service_NetSessionCommon.cpp @@ -30,7 +30,8 @@ limitations under the License. namespace OVR { namespace Service { -//// NetSessionCommon +//----------------------------------------------------------------------------- +// NetSessionCommon NetSessionCommon::NetSessionCommon() : Terminated(false) @@ -57,14 +58,14 @@ NetSessionCommon::~NetSessionCommon() pRPC = NULL; } - Terminated = true; + Terminated.store(true, std::memory_order_relaxed); OVR_ASSERT(IsFinished()); } void NetSessionCommon::onSystemDestroy() { - Terminated = true; + Terminated.store(true, std::memory_order_relaxed); Join(); @@ -73,93 +74,106 @@ void NetSessionCommon::onSystemDestroy() void NetSessionCommon::onThreadDestroy() { - Terminated = true; + Terminated.store(true, std::memory_order_relaxed); if (pSession) { pSession->Shutdown(); } } -void NetSessionCommon::SerializeHMDInfo(Net::BitStream *bitStream, HMDInfo* hmdInfo) +template<typename T> +static bool SerializeUInt32(bool write, Net::BitStream* bitStream, T& data) { - bitStream->Write(hmdInfo->ProductName); - bitStream->Write(hmdInfo->Manufacturer); - - int32_t w = hmdInfo->Version; - bitStream->Write(w); - - w = hmdInfo->HmdType; - bitStream->Write(w); - - w = hmdInfo->ResolutionInPixels.w; - bitStream->Write(w); - - w = hmdInfo->ResolutionInPixels.h; - bitStream->Write(w); + int32_t w = 0; + bool result = false; - w = hmdInfo->ShimInfo.DeviceNumber; - bitStream->Write(w); + if (write) + { + w = (int32_t)data; + result = bitStream->Serialize(write, w); + } + else + { + result = bitStream->Serialize(write, w); + data = (T)w; + } - w = hmdInfo->ShimInfo.NativeWidth; - bitStream->Write(w); + return result; +} - w = hmdInfo->ShimInfo.NativeHeight; - bitStream->Write(w); +static bool SerializeBool(bool write, Net::BitStream* bitStream, bool& data) +{ + uint8_t x = 0; + bool result = false; - w = hmdInfo->ShimInfo.Rotation; - bitStream->Write(w); + if (write) + { + x = data ? 1 : 0; + result = bitStream->Serialize(write, x); + } + else + { + result = bitStream->Serialize(write, x); + data = (x != 0); + } - bitStream->Write(hmdInfo->ScreenSizeInMeters.w); - bitStream->Write(hmdInfo->ScreenSizeInMeters.h); - bitStream->Write(hmdInfo->ScreenGapSizeInMeters); - bitStream->Write(hmdInfo->CenterFromTopInMeters); - bitStream->Write(hmdInfo->LensSeparationInMeters); + return result; +} - w = hmdInfo->DesktopX; - bitStream->Write(w); +bool NetSessionCommon::SerializeHMDInfo(Net::BitStream *bitStream, HMDInfo* hmdInfo, bool write) +{ + bool result = false; - w = hmdInfo->DesktopY; - bitStream->Write(w); + bitStream->Serialize(write, hmdInfo->ProductName); + bitStream->Serialize(write, hmdInfo->Manufacturer); - w = hmdInfo->Shutter.Type; - bitStream->Write(w); + SerializeUInt32(write, bitStream, hmdInfo->Version); + SerializeUInt32(write, bitStream, hmdInfo->HmdType); + SerializeUInt32(write, bitStream, hmdInfo->ResolutionInPixels.w); + SerializeUInt32(write, bitStream, hmdInfo->ResolutionInPixels.h); + SerializeUInt32(write, bitStream, hmdInfo->ShimInfo.DeviceNumber); + SerializeUInt32(write, bitStream, hmdInfo->ShimInfo.NativeWidth); + SerializeUInt32(write, bitStream, hmdInfo->ShimInfo.NativeHeight); + SerializeUInt32(write, bitStream, hmdInfo->ShimInfo.Rotation); - bitStream->Write(hmdInfo->Shutter.VsyncToNextVsync); - bitStream->Write(hmdInfo->Shutter.VsyncToFirstScanline); - bitStream->Write(hmdInfo->Shutter.FirstScanlineToLastScanline); - bitStream->Write(hmdInfo->Shutter.PixelSettleTime); - bitStream->Write(hmdInfo->Shutter.PixelPersistence); - bitStream->Write(hmdInfo->DisplayDeviceName); + bitStream->Serialize(write, hmdInfo->ScreenSizeInMeters.w); + bitStream->Serialize(write, hmdInfo->ScreenSizeInMeters.h); + bitStream->Serialize(write, hmdInfo->ScreenGapSizeInMeters); + bitStream->Serialize(write, hmdInfo->CenterFromTopInMeters); + bitStream->Serialize(write, hmdInfo->LensSeparationInMeters); - w = hmdInfo->DisplayId; - bitStream->Write(w); + SerializeUInt32(write, bitStream, hmdInfo->DesktopX); + SerializeUInt32(write, bitStream, hmdInfo->DesktopY); + SerializeUInt32(write, bitStream, hmdInfo->Shutter.Type); - bitStream->Write(hmdInfo->PrintedSerial); + bitStream->Serialize(write, hmdInfo->Shutter.VsyncToNextVsync); + bitStream->Serialize(write, hmdInfo->Shutter.VsyncToFirstScanline); + bitStream->Serialize(write, hmdInfo->Shutter.FirstScanlineToLastScanline); + bitStream->Serialize(write, hmdInfo->Shutter.PixelSettleTime); + bitStream->Serialize(write, hmdInfo->Shutter.PixelPersistence); + bitStream->Serialize(write, hmdInfo->DisplayDeviceName); - uint8_t b = hmdInfo->InCompatibilityMode ? 1 : 0; - bitStream->Write(b); + SerializeUInt32(write, bitStream, hmdInfo->DisplayId); - w = hmdInfo->VendorId; - bitStream->Write(w); + bitStream->Serialize(write, hmdInfo->PrintedSerial); - w = hmdInfo->ProductId; - bitStream->Write(w); + SerializeBool(write, bitStream, hmdInfo->InCompatibilityMode); - bitStream->Write(hmdInfo->CameraFrustumFarZInMeters); - bitStream->Write(hmdInfo->CameraFrustumHFovInRadians); - bitStream->Write(hmdInfo->CameraFrustumNearZInMeters); - bitStream->Write(hmdInfo->CameraFrustumVFovInRadians); + SerializeUInt32(write, bitStream, hmdInfo->VendorId); + SerializeUInt32(write, bitStream, hmdInfo->ProductId); - w = hmdInfo->FirmwareMajor; - bitStream->Write(w); + bitStream->Serialize(write, hmdInfo->CameraFrustumFarZInMeters); + bitStream->Serialize(write, hmdInfo->CameraFrustumHFovInRadians); + bitStream->Serialize(write, hmdInfo->CameraFrustumNearZInMeters); + bitStream->Serialize(write, hmdInfo->CameraFrustumVFovInRadians); - w = hmdInfo->FirmwareMinor; - bitStream->Write(w); + SerializeUInt32(write, bitStream, hmdInfo->FirmwareMajor); + SerializeUInt32(write, bitStream, hmdInfo->FirmwareMinor); - bitStream->Write(hmdInfo->PelOffsetR.x); - bitStream->Write(hmdInfo->PelOffsetR.y); - bitStream->Write(hmdInfo->PelOffsetB.x); - bitStream->Write(hmdInfo->PelOffsetB.y); + bitStream->Serialize(write, hmdInfo->PelOffsetR.x); + bitStream->Serialize(write, hmdInfo->PelOffsetR.y); + bitStream->Serialize(write, hmdInfo->PelOffsetB.x); + result = bitStream->Serialize(write, hmdInfo->PelOffsetB.y); // Important please read before modifying! // ---------------------------------------------------- @@ -167,138 +181,30 @@ void NetSessionCommon::SerializeHMDInfo(Net::BitStream *bitStream, HMDInfo* hmdI // Otherwise we will break backwards compatibility // and e.g. 0.4.4 runtime will not work with 0.4.3 SDK. - // Please also update the DeserializeHMDInfo() function - // below also and make sure that the members you added - // are initialized properly in the HMDInfo constructor. - // Note that whenever new fields are added here you // should also update the minor version of the RPC // protocol in OVR_Session.h so that clients fail at // a version check instead of when this data is // found to be truncated from the server. -} - -bool NetSessionCommon::DeserializeHMDInfo(Net::BitStream *bitStream, HMDInfo* hmdInfo) -{ - bitStream->Read(hmdInfo->ProductName); - bitStream->Read(hmdInfo->Manufacturer); - - int32_t w = 0; - if (!bitStream->Read(w)) - { - // This indicates that no HMD could be found - return false; - } - hmdInfo->Version = w; - - bitStream->Read(w); - hmdInfo->HmdType = (HmdTypeEnum)w; - - bitStream->Read(w); - hmdInfo->ResolutionInPixels.w = w; - - bitStream->Read(w); - hmdInfo->ResolutionInPixels.h = w; - - bitStream->Read(w); - hmdInfo->ShimInfo.DeviceNumber = w; - - bitStream->Read(w); - hmdInfo->ShimInfo.NativeWidth = w; - - bitStream->Read(w); - hmdInfo->ShimInfo.NativeHeight = w; - - bitStream->Read(w); - hmdInfo->ShimInfo.Rotation = w; - - bitStream->Read(hmdInfo->ScreenSizeInMeters.w); - bitStream->Read(hmdInfo->ScreenSizeInMeters.h); - bitStream->Read(hmdInfo->ScreenGapSizeInMeters); - bitStream->Read(hmdInfo->CenterFromTopInMeters); - bitStream->Read(hmdInfo->LensSeparationInMeters); - - bitStream->Read(w); - hmdInfo->DesktopX = w; - - bitStream->Read(w); - hmdInfo->DesktopY = w; - - bitStream->Read(w); - hmdInfo->Shutter.Type = (HmdShutterTypeEnum)w; - - bitStream->Read(hmdInfo->Shutter.VsyncToNextVsync); - bitStream->Read(hmdInfo->Shutter.VsyncToFirstScanline); - bitStream->Read(hmdInfo->Shutter.FirstScanlineToLastScanline); - bitStream->Read(hmdInfo->Shutter.PixelSettleTime); - bitStream->Read(hmdInfo->Shutter.PixelPersistence); - bitStream->Read(hmdInfo->DisplayDeviceName); - - bitStream->Read(w); - hmdInfo->DisplayId = w; - - bitStream->Read(hmdInfo->PrintedSerial); - - uint8_t b = 0; - bitStream->Read(b); - hmdInfo->InCompatibilityMode = (b != 0); - - bitStream->Read(w); - hmdInfo->VendorId = w; - - bitStream->Read(w); - hmdInfo->ProductId = w; - - bitStream->Read(hmdInfo->CameraFrustumFarZInMeters); - bitStream->Read(hmdInfo->CameraFrustumHFovInRadians); - bitStream->Read(hmdInfo->CameraFrustumNearZInMeters); - bitStream->Read(hmdInfo->CameraFrustumVFovInRadians); - - bitStream->Read(w); - hmdInfo->FirmwareMajor = w; - - if (!bitStream->Read(w)) - { - OVR_ASSERT(false); - return false; - } - hmdInfo->FirmwareMinor = w; - - bitStream->Read(hmdInfo->PelOffsetR.x); - bitStream->Read(hmdInfo->PelOffsetR.y); - bitStream->Read(hmdInfo->PelOffsetB.x); - if (!bitStream->Read(hmdInfo->PelOffsetB.y)) - { - OVR_ASSERT(false); - return false; - } - - // Important please read before modifying! - // ---------------------------------------------------- - // Please add new serialized data to the end, here. - // Otherwise we will break backwards compatibility - // and e.g. 0.4.4 runtime will not work with 0.4.3 SDK. - - // Be sure to check that the very last one read properly - // since HMD Info truncation should be caught here. - return true; + // The result of the final serialize should be returned to the caller. + return result; } // Prefix key names with this to pass through to server static const char* BypassPrefix = "server:"; static const char* KeyNames[][NetSessionCommon::ENumTypes] = { - /* EGetStringValue */ { "CameraSerial", "CameraUUID", 0 }, - /* EGetBoolValue */ { "ReleaseDK2Sensors", "ReleaseLegacySensors", 0 }, - /* EGetIntValue */ { 0 }, - /* EGetNumberValue */{ "CenterPupilDepth", "LoggingMask", 0 }, - /* EGetNumberValues */{ "NeckModelVector3f", 0 }, - /* ESetStringValue */ { 0 }, - /* ESetBoolValue */ { "ReleaseDK2Sensors", "ReleaseLegacySensors", 0 }, - /* ESetIntValue */ { 0 }, - /* ESetNumberValue */{ "CenterPupilDepth", "LoggingMask", 0 }, - /* ESetNumberValues */{ "NeckModelVector3f", 0 }, + /* EGetStringValue */ { "CameraSerial", "CameraUUID", 0 }, + /* EGetBoolValue */ { "ReleaseDK2Sensors", "ReleaseLegacySensors", 0 }, + /* EGetIntValue */ { 0 }, + /* EGetNumberValue */ { "CenterPupilDepth", "LoggingMask", 0 }, + /* EGetNumberValues */ { "NeckModelVector3f", 0 }, + /* ESetStringValue */ { 0 }, + /* ESetBoolValue */ { "ReleaseDK2Sensors", "ReleaseLegacySensors", 0 }, + /* ESetIntValue */ { 0 }, + /* ESetNumberValue */ { "CenterPupilDepth", "LoggingMask", 0 }, + /* ESetNumberValues */ { "NeckModelVector3f", 0 }, }; bool IsInStringArray(const char* a[], const char* key) diff --git a/LibOVR/Src/Service/Service_NetSessionCommon.h b/LibOVR/Src/Service/Service_NetSessionCommon.h index 79c0cfb..eefc292 100644..100755 --- a/LibOVR/Src/Service/Service_NetSessionCommon.h +++ b/LibOVR/Src/Service/Service_NetSessionCommon.h @@ -27,11 +27,14 @@ limitations under the License. #ifndef OVR_Service_NetSessionCommon_h #define OVR_Service_NetSessionCommon_h -#include "../OVR_CAPI.h" -#include "../Net/OVR_RPC1.h" -#include "../Kernel/OVR_Threads.h" -#include "../Net/OVR_BitStream.h" -#include "../Kernel/OVR_System.h" +#include <atomic> + +#include "OVR_CAPI.h" +#include "Kernel/OVR_Threads.h" +#include "Kernel/OVR_System.h" +#include "Net/OVR_RPC1.h" +#include "Net/OVR_BitStream.h" + namespace OVR { @@ -52,6 +55,13 @@ static const int32_t InvalidVirtualHmdId = -1; // Localhost-bound TCP port that the service listens on for VR apps static const int VRServicePort = 30322; // 0x7672 = "vr" little-endian +// Stores the names of shared memory regions +struct SharedMemoryNames +{ + String Hmd; + String Camera; +}; + // HMDInfo section related to networking struct HMDNetworkInfo { @@ -63,19 +73,25 @@ struct HMDNetworkInfo // Network identifier for HMD VirtualHmdId NetId; - // Name of the shared memory object - String SharedMemoryName; + // Names of the shared memory objects + SharedMemoryNames SharedMemoryName; - void Serialize(Net::BitStream* bs) + bool Serialize(Net::BitStream* bs, bool write = true) { - bs->Write(NetId); - bs->Write(SharedMemoryName); - } - bool Deserialize(Net::BitStream* bs) - { - bs->Read(NetId); - return bs->Read(SharedMemoryName); + bs->Serialize(write, NetId); + bs->Serialize(write, SharedMemoryName.Hmd); + if (!bs->Serialize(write, SharedMemoryName.Camera)) + return false; + return true; } + + // Assignment operator + HMDNetworkInfo& operator=(HMDNetworkInfo const & rhs) + { + NetId = rhs.NetId; + SharedMemoryName = rhs.SharedMemoryName; + return *this; + } }; @@ -103,8 +119,7 @@ public: return pSession; } - static void SerializeHMDInfo(Net::BitStream* bitStream, HMDInfo* hmdInfo); - static bool DeserializeHMDInfo(Net::BitStream* bitStream, HMDInfo* hmdInfo); + static bool SerializeHMDInfo(Net::BitStream* bitStream, HMDInfo* hmdInfo, bool write = true); public: // Getter/setter tools @@ -131,9 +146,9 @@ public: static bool IsServiceProperty(EGetterSetters e, const char* key); protected: - bool Terminated; // Thread termination flag + std::atomic<bool> Terminated; // Thread termination flag Net::Session* pSession; // Networking session - Net::Plugins::RPC1* pRPC; // Remote procedure calls object + Net::Plugins::RPC1* pRPC; // Remote procedure calls object }; diff --git a/LibOVR/Src/Service/Service_Win32_FastIPC_Client.cpp b/LibOVR/Src/Service/Service_Win32_FastIPC_Client.cpp new file mode 100644 index 0000000..22a0b4a --- /dev/null +++ b/LibOVR/Src/Service/Service_Win32_FastIPC_Client.cpp @@ -0,0 +1,228 @@ +/************************************************************************************ + +Filename : Service_Win32_FastIPC_Client.cpp +Content : Client side of connectionless fast IPC +Created : Sept 16, 2014 +Authors : Chris Taylor + +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.2 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#include "Service_Win32_FastIPC_Client.h" + +namespace OVR { namespace Service { namespace Win32 { + +using namespace OVR::Net; + + +//// FastIPCClient + +FastIPCClient::FastIPCClient() +{ +} + +bool FastIPCClient::ReadInitialData(const char* buffer) +{ + uint32_t magic = *(uint32_t*)(buffer); + uint32_t verMajor = *(uint32_t*)(buffer + 4); + uint32_t verMinor = *(uint32_t*)(buffer + 8); + + if (magic != Magic) + { + LogError("Magic does not match"); + return false; + } + + if (verMajor != MajorVersion) + { + LogError("Major version mismatch"); + return false; + } + + if (verMinor < MinorVersion) + { + LogError("Remote minor version too old for our feature level"); + return false; + } + + HANDLE remoteDataEvent = (HANDLE)*(uint64_t*)(buffer + 12); + HANDLE remoteReturnEvent = (HANDLE)*(uint64_t*)(buffer + 20); + pid_t serverProcessId = (pid_t) *(uint64_t*)(buffer + 28); + OVR_UNUSED(serverProcessId); + + if (!remoteDataEvent || !remoteReturnEvent) + { + LogError("Handshake was malformed. It seems like a version mismatch."); + return false; + } + + DataEvent.Attach(remoteDataEvent); + ReturnEvent.Attach(remoteReturnEvent); + + return true; +} + +bool FastIPCClient::Initialize(const char* sharedMemoryName) +{ + SharedMemory::OpenParameters params; + params.accessMode = SharedMemory::AccessMode_ReadWrite; + params.globalName = sharedMemoryName; + params.minSizeBytes = RegionSize; + params.openMode = SharedMemory::OpenMode_OpenOnly; + params.remoteMode = SharedMemory::RemoteMode_ReadWrite; + Scratch = SharedMemoryFactory::GetInstance()->Open(params); + IPCMessageIndex = 1; + + if (!Scratch || Scratch->GetSizeI() < RegionSize) + { + OVR_ASSERT(false); + LogError("Unable to open shared memory region"); + return false; + } + + char* data = (char*)Scratch->GetData(); + + // If unable to read handshake, + if (!ReadInitialData(data)) + { + return false; + } + + return true; +} + +FastIPCClient::~FastIPCClient() +{ +} + +bool FastIPCClient::Call(Net::BitStream* parameters, Net::BitStream* returnData, int timeoutMs) +{ + // If not initialized, + if (!ReturnEvent.IsValid()) + { + OVR_ASSERT(false); + return false; + } + + volatile unsigned char* scratch = (unsigned char*)Scratch->GetData(); + + uint32_t bytesUsed = ((uint32_t)parameters->GetNumberOfBitsUsed() + 7) / 8; + + // If data is too long, + if (bytesUsed > RegionSize - 4) + { + OVR_ASSERT(false); + return false; + } + + // First 4 bytes will be the size of the parameters + // Note that this is for IPC so endian-ness is not important + *(uint32_t*)(scratch + 4) = bytesUsed; + + // Copy data into place + memcpy((char*)scratch + 8, parameters->GetData(), bytesUsed); + + // Don't allow read/write operations to move around this point + MemoryBarrier(); + + // Write message index + *(volatile uint32_t*)scratch = IPCMessageIndex; + + // Wake the remote thread to service our request + if (!::SetEvent(DataEvent.Get())) + { + OVR_ASSERT(false); + return false; + } + + // Wait for result of call: + + ++IPCMessageIndex; + + // Use the GetTickCount() API for low-resolution timing + DWORD t0 = ::GetTickCount(); + int remaining = timeoutMs; + + // Forever, + for (;;) + { + // Wait on the return event + DWORD result = ::WaitForSingleObject(ReturnEvent.Get(), timeoutMs < 0 ? INFINITE : remaining); + + if (result == WAIT_FAILED) + { + int err = GetLastError(); + LogError("[FastIPC] Wait failed with error %d", err); + } + + // If wait succeeded, + if (result == WAIT_OBJECT_0) + { + if (*(volatile uint32_t*)scratch != IPCMessageIndex) + { + double callTimeoutStart = Timer::GetSeconds(); + + while (*(volatile uint32_t*)scratch != IPCMessageIndex) + { + if (Timer::GetSeconds() - callTimeoutStart > 1.) + { + LogError("[FastIPC] Timed out waiting for remote IPC message to be written."); + OVR_ASSERT(false); + return false; + } + + Thread::YieldCurrentThread(); + } + } + + _ReadBarrier(); + + // Wrap the scratch buffer + uint32_t len = *(uint32_t*)(scratch + 4); + returnData->WrapBuffer((unsigned char*)scratch + 8, len); + + ++IPCMessageIndex; + + // Return true for success + return true; + } + + // If not waiting forever, + if (timeoutMs > 0) + { + // If wait time has elapsed, + int elapsed = ::GetTickCount() - t0; + if (elapsed >= timeoutMs) + { + // Break out of loop returning false + break; + } + + // Calculate remaining wait time + remaining = timeoutMs - elapsed; + } + + // Continue waiting + } + + return false; +} + + +}}} // namespace OVR::Service::Win32 diff --git a/LibOVR/Src/Service/Service_Win32_FastIPC_Client.h b/LibOVR/Src/Service/Service_Win32_FastIPC_Client.h new file mode 100644 index 0000000..984da06 --- /dev/null +++ b/LibOVR/Src/Service/Service_Win32_FastIPC_Client.h @@ -0,0 +1,84 @@ +/************************************************************************************ + +Filename : OVR_Service_Win32_FastIPC_Client.h +Content : Client side of connectionless fast IPC +Created : Sept 16, 2014 +Authors : Chris Taylor + +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.2 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_Service_Win32_FastIPC_Client_h +#define OVR_Service_Win32_FastIPC_Client_h + +#include "Kernel/OVR_SharedMemory.h" +#include "Net/OVR_RPC1.h" +#include "Kernel/OVR_Win32_IncludeWindows.h" + +namespace OVR { namespace Service { namespace Win32 { + + +//----------------------------------------------------------------------------- +// FastIPCClient +// +// This class implements the client side for connectionless IPC messaging. +// +// The client reads the shared memory name provided and retrieves the data +// and return event handles. It can push data to the server synchronously +// by signaling the data handle and waiting on the return handle. + +class FastIPCClient +{ + String SharedMemoryName; + Ptr<SharedMemory> Scratch; + ScopedEventHANDLE DataEvent, ReturnEvent; + uint32_t IPCMessageIndex; + +protected: + bool ReadInitialData(const char* buffer); + +public: + static const int RegionSize = 4096; + static const uint32_t Magic = 0xfe67bead; + + // Semantic versioning + static const uint32_t MajorVersion = 1; + static const uint32_t MinorVersion = 0; + +public: + FastIPCClient(); + ~FastIPCClient(); + + String GetSharedMemoryName() const + { + return SharedMemoryName; + } + + // Call this to initialize the shared memory section + bool Initialize(const char* sharedMemoryName); + + // Make a blocking call to the server + // Pass -1 for the timeout to wait forever + bool Call(Net::BitStream* bread, Net::BitStream* toast, int timeoutMs = -1); +}; + + +}}} // namespace OVR::Service::Win32 + +#endif // OVR_Service_Win32_FastIPC_Client_h |