ovr_sdk
diff LibOVR/Src/Net/OVR_RPC1.cpp @ 0:1b39a1b46319
initial 0.4.4
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 14 Jan 2015 06:51:16 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/Net/OVR_RPC1.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,270 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : OVR_RPC1.cpp 1.7 +Content : A network plugin that provides remote procedure call functionality. 1.8 +Created : June 10, 2014 1.9 +Authors : Kevin Jenkins 1.10 + 1.11 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.12 + 1.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.15 +which is provided at the time of installation or download, or which 1.16 +otherwise accompanies this software in either electronic or hard copy form. 1.17 + 1.18 +You may obtain a copy of the License at 1.19 + 1.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.21 + 1.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.23 +distributed under the License is distributed on an "AS IS" BASIS, 1.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.25 +See the License for the specific language governing permissions and 1.26 +limitations under the License. 1.27 + 1.28 +************************************************************************************/ 1.29 + 1.30 +#include "OVR_RPC1.h" 1.31 +#include "OVR_BitStream.h" 1.32 +#include "../Kernel/OVR_Threads.h" // Thread::MSleep 1.33 +#include "OVR_MessageIDTypes.h" 1.34 + 1.35 +namespace OVR { namespace Net { namespace Plugins { 1.36 + 1.37 + 1.38 +//----------------------------------------------------------------------------- 1.39 +// Types 1.40 + 1.41 +enum { 1.42 + ID_RPC4_SIGNAL, 1.43 + CALL_BLOCKING, 1.44 + RPC_ERROR_FUNCTION_NOT_REGISTERED, 1.45 + ID_RPC4_RETURN, 1.46 +}; 1.47 + 1.48 + 1.49 +//----------------------------------------------------------------------------- 1.50 +// RPC1 1.51 + 1.52 +RPC1::RPC1() 1.53 +{ 1.54 + blockingOnThisConnection = 0; 1.55 + blockingReturnValue = new BitStream(); 1.56 +} 1.57 + 1.58 +RPC1::~RPC1() 1.59 +{ 1.60 + slotHash.Clear(); 1.61 + delete blockingReturnValue; 1.62 +} 1.63 + 1.64 +void RPC1::RegisterSlot(OVR::String sharedIdentifier, OVR::Observer<RPCSlot>* rpcSlotObserver ) 1.65 +{ 1.66 + slotHash.AddObserverToSubject(sharedIdentifier, rpcSlotObserver); 1.67 +} 1.68 + 1.69 +bool RPC1::RegisterBlockingFunction(OVR::String uniqueID, RPCDelegate blockingFunction) 1.70 +{ 1.71 + if (registeredBlockingFunctions.Get(uniqueID)) 1.72 + return false; 1.73 + 1.74 + registeredBlockingFunctions.Set(uniqueID, blockingFunction); 1.75 + return true; 1.76 +} 1.77 + 1.78 +void RPC1::UnregisterBlockingFunction(OVR::String uniqueID) 1.79 +{ 1.80 + registeredBlockingFunctions.Remove(uniqueID); 1.81 +} 1.82 + 1.83 +bool RPC1::CallBlocking( OVR::String uniqueID, OVR::Net::BitStream* bitStream, Ptr<Connection> pConnection, OVR::Net::BitStream* returnData ) 1.84 +{ 1.85 + // If invalid parameters, 1.86 + if (!pConnection) 1.87 + { 1.88 + // Note: This may happen if the endpoint disconnects just before the call 1.89 + return false; 1.90 + } 1.91 + 1.92 + OVR::Net::BitStream out; 1.93 + out.Write((MessageID) OVRID_RPC1); 1.94 + out.Write((MessageID) CALL_BLOCKING); 1.95 + out.Write(uniqueID); 1.96 + if (bitStream) 1.97 + { 1.98 + bitStream->ResetReadPointer(); 1.99 + out.AlignWriteToByteBoundary(); 1.100 + out.Write(bitStream); 1.101 + } 1.102 + 1.103 + SendParameters sp(pConnection, out.GetData(), out.GetNumberOfBytesUsed()); 1.104 + 1.105 + if (returnData) 1.106 + { 1.107 + returnData->Reset(); 1.108 + } 1.109 + 1.110 + // Only one thread call at a time 1.111 + Lock::Locker singleRPCLocker(&singleRPCLock); 1.112 + 1.113 + // Note this does not prevent multiple calls at a time because .Wait will unlock it below. 1.114 + // The purpose of this mutex is to synchronize the polling thread and this one, not prevent 1.115 + // multiple threads from invoking RPC. 1.116 + Mutex::Locker locker(&callBlockingMutex); 1.117 + 1.118 + blockingReturnValue->Reset(); 1.119 + blockingOnThisConnection = pConnection; 1.120 + 1.121 + int bytesSent = pSession->Send(&sp); 1.122 + if (bytesSent == sp.Bytes) 1.123 + { 1.124 + while (blockingOnThisConnection == pConnection) 1.125 + { 1.126 + callBlockingWait.Wait(&callBlockingMutex); 1.127 + } 1.128 + } 1.129 + else 1.130 + { 1.131 + return false; 1.132 + } 1.133 + 1.134 + if (returnData) 1.135 + { 1.136 + returnData->Write(blockingReturnValue); 1.137 + returnData->ResetReadPointer(); 1.138 + } 1.139 + 1.140 + return true; 1.141 +} 1.142 + 1.143 +bool RPC1::Signal(OVR::String sharedIdentifier, OVR::Net::BitStream* bitStream, Ptr<Connection> pConnection) 1.144 +{ 1.145 + OVR::Net::BitStream out; 1.146 + out.Write((MessageID) OVRID_RPC1); 1.147 + out.Write((MessageID) ID_RPC4_SIGNAL); 1.148 + //out.Write(PluginId); 1.149 + out.Write(sharedIdentifier); 1.150 + if (bitStream) 1.151 + { 1.152 + bitStream->ResetReadPointer(); 1.153 + out.AlignWriteToByteBoundary(); 1.154 + out.Write(bitStream); 1.155 + } 1.156 + SendParameters sp(pConnection, out.GetData(), out.GetNumberOfBytesUsed()); 1.157 + int32_t bytesSent = pSession->Send(&sp); 1.158 + return bytesSent == sp.Bytes; 1.159 +} 1.160 +void RPC1::BroadcastSignal(OVR::String sharedIdentifier, OVR::Net::BitStream* bitStream) 1.161 +{ 1.162 + OVR::Net::BitStream out; 1.163 + out.Write((MessageID) OVRID_RPC1); 1.164 + out.Write((MessageID) ID_RPC4_SIGNAL); 1.165 + //out.Write(PluginId); 1.166 + out.Write(sharedIdentifier); 1.167 + if (bitStream) 1.168 + { 1.169 + bitStream->ResetReadPointer(); 1.170 + out.AlignWriteToByteBoundary(); 1.171 + out.Write(bitStream); 1.172 + } 1.173 + BroadcastParameters p(out.GetData(), out.GetNumberOfBytesUsed()); 1.174 + pSession->Broadcast(&p); 1.175 +} 1.176 +void RPC1::OnReceive(ReceivePayload *pPayload, ListenerReceiveResult *lrrOut) 1.177 +{ 1.178 + OVR_UNUSED(lrrOut); 1.179 + 1.180 + if (pPayload->pData[0] == OVRID_RPC1) 1.181 + { 1.182 + OVR_ASSERT(pPayload->Bytes >= 2); 1.183 + 1.184 + OVR::Net::BitStream bsIn((char*)pPayload->pData, pPayload->Bytes, false); 1.185 + bsIn.IgnoreBytes(2); 1.186 + 1.187 + if (pPayload->pData[1] == RPC_ERROR_FUNCTION_NOT_REGISTERED) 1.188 + { 1.189 + Mutex::Locker locker(&callBlockingMutex); 1.190 + 1.191 + blockingReturnValue->Reset(); 1.192 + blockingOnThisConnection = 0; 1.193 + callBlockingWait.NotifyAll(); 1.194 + } 1.195 + else if (pPayload->pData[1] == ID_RPC4_RETURN) 1.196 + { 1.197 + Mutex::Locker locker(&callBlockingMutex); 1.198 + 1.199 + blockingReturnValue->Reset(); 1.200 + blockingReturnValue->Write(bsIn); 1.201 + blockingOnThisConnection = 0; 1.202 + callBlockingWait.NotifyAll(); 1.203 + } 1.204 + else if (pPayload->pData[1] == CALL_BLOCKING) 1.205 + { 1.206 + OVR::String uniqueId; 1.207 + bsIn.Read(uniqueId); 1.208 + 1.209 + RPCDelegate *bf = registeredBlockingFunctions.Get(uniqueId); 1.210 + if (bf==0) 1.211 + { 1.212 + OVR::Net::BitStream bsOut; 1.213 + bsOut.Write((unsigned char) OVRID_RPC1); 1.214 + bsOut.Write((unsigned char) RPC_ERROR_FUNCTION_NOT_REGISTERED); 1.215 + 1.216 + SendParameters sp(pPayload->pConnection, bsOut.GetData(), bsOut.GetNumberOfBytesUsed()); 1.217 + pSession->Send(&sp); 1.218 + 1.219 + return; 1.220 + } 1.221 + 1.222 + OVR::Net::BitStream returnData; 1.223 + bsIn.AlignReadToByteBoundary(); 1.224 + (*bf)(&bsIn, &returnData, pPayload); 1.225 + 1.226 + OVR::Net::BitStream out; 1.227 + out.Write((MessageID) OVRID_RPC1); 1.228 + out.Write((MessageID) ID_RPC4_RETURN); 1.229 + returnData.ResetReadPointer(); 1.230 + out.AlignWriteToByteBoundary(); 1.231 + out.Write(returnData); 1.232 + 1.233 + SendParameters sp(pPayload->pConnection, out.GetData(), out.GetNumberOfBytesUsed()); 1.234 + pSession->Send(&sp); 1.235 + } 1.236 + else if (pPayload->pData[1]==ID_RPC4_SIGNAL) 1.237 + { 1.238 + OVR::String sharedIdentifier; 1.239 + bsIn.Read(sharedIdentifier); 1.240 + 1.241 + Observer<RPCSlot> *o = slotHash.GetSubject(sharedIdentifier); 1.242 + 1.243 + if (o) 1.244 + { 1.245 + bsIn.AlignReadToByteBoundary(); 1.246 + 1.247 + if (o) 1.248 + { 1.249 + OVR::Net::BitStream serializedParameters(bsIn.GetData() + bsIn.GetReadOffset()/8, bsIn.GetNumberOfUnreadBits()/8, false); 1.250 + 1.251 + o->Call(&serializedParameters, pPayload); 1.252 + } 1.253 + } 1.254 + } 1.255 + } 1.256 +} 1.257 + 1.258 +void RPC1::OnDisconnected(Connection* conn) 1.259 +{ 1.260 + if (blockingOnThisConnection == conn) 1.261 + { 1.262 + blockingOnThisConnection = 0; 1.263 + callBlockingWait.NotifyAll(); 1.264 + } 1.265 +} 1.266 + 1.267 +void RPC1::OnConnected(Connection* conn) 1.268 +{ 1.269 + OVR_UNUSED(conn); 1.270 +} 1.271 + 1.272 + 1.273 +}}} // OVR::Net::Plugins