ovr_sdk

annotate 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
rev   line source
nuclear@0 1 /************************************************************************************
nuclear@0 2
nuclear@0 3 Filename : OVR_RPC1.cpp
nuclear@0 4 Content : A network plugin that provides remote procedure call functionality.
nuclear@0 5 Created : June 10, 2014
nuclear@0 6 Authors : Kevin Jenkins
nuclear@0 7
nuclear@0 8 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
nuclear@0 9
nuclear@0 10 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
nuclear@0 11 you may not use the Oculus VR Rift SDK except in compliance with the License,
nuclear@0 12 which is provided at the time of installation or download, or which
nuclear@0 13 otherwise accompanies this software in either electronic or hard copy form.
nuclear@0 14
nuclear@0 15 You may obtain a copy of the License at
nuclear@0 16
nuclear@0 17 http://www.oculusvr.com/licenses/LICENSE-3.2
nuclear@0 18
nuclear@0 19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
nuclear@0 20 distributed under the License is distributed on an "AS IS" BASIS,
nuclear@0 21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nuclear@0 22 See the License for the specific language governing permissions and
nuclear@0 23 limitations under the License.
nuclear@0 24
nuclear@0 25 ************************************************************************************/
nuclear@0 26
nuclear@0 27 #include "OVR_RPC1.h"
nuclear@0 28 #include "OVR_BitStream.h"
nuclear@0 29 #include "../Kernel/OVR_Threads.h" // Thread::MSleep
nuclear@0 30 #include "OVR_MessageIDTypes.h"
nuclear@0 31
nuclear@0 32 namespace OVR { namespace Net { namespace Plugins {
nuclear@0 33
nuclear@0 34
nuclear@0 35 //-----------------------------------------------------------------------------
nuclear@0 36 // Types
nuclear@0 37
nuclear@0 38 enum {
nuclear@0 39 ID_RPC4_SIGNAL,
nuclear@0 40 CALL_BLOCKING,
nuclear@0 41 RPC_ERROR_FUNCTION_NOT_REGISTERED,
nuclear@0 42 ID_RPC4_RETURN,
nuclear@0 43 };
nuclear@0 44
nuclear@0 45
nuclear@0 46 //-----------------------------------------------------------------------------
nuclear@0 47 // RPC1
nuclear@0 48
nuclear@0 49 RPC1::RPC1()
nuclear@0 50 {
nuclear@0 51 blockingOnThisConnection = 0;
nuclear@0 52 blockingReturnValue = new BitStream();
nuclear@0 53 }
nuclear@0 54
nuclear@0 55 RPC1::~RPC1()
nuclear@0 56 {
nuclear@0 57 slotHash.Clear();
nuclear@0 58 delete blockingReturnValue;
nuclear@0 59 }
nuclear@0 60
nuclear@0 61 void RPC1::RegisterSlot(OVR::String sharedIdentifier, OVR::Observer<RPCSlot>* rpcSlotObserver )
nuclear@0 62 {
nuclear@0 63 slotHash.AddObserverToSubject(sharedIdentifier, rpcSlotObserver);
nuclear@0 64 }
nuclear@0 65
nuclear@0 66 bool RPC1::RegisterBlockingFunction(OVR::String uniqueID, RPCDelegate blockingFunction)
nuclear@0 67 {
nuclear@0 68 if (registeredBlockingFunctions.Get(uniqueID))
nuclear@0 69 return false;
nuclear@0 70
nuclear@0 71 registeredBlockingFunctions.Set(uniqueID, blockingFunction);
nuclear@0 72 return true;
nuclear@0 73 }
nuclear@0 74
nuclear@0 75 void RPC1::UnregisterBlockingFunction(OVR::String uniqueID)
nuclear@0 76 {
nuclear@0 77 registeredBlockingFunctions.Remove(uniqueID);
nuclear@0 78 }
nuclear@0 79
nuclear@0 80 bool RPC1::CallBlocking( OVR::String uniqueID, OVR::Net::BitStream* bitStream, Ptr<Connection> pConnection, OVR::Net::BitStream* returnData )
nuclear@0 81 {
nuclear@0 82 // If invalid parameters,
nuclear@0 83 if (!pConnection)
nuclear@0 84 {
nuclear@0 85 // Note: This may happen if the endpoint disconnects just before the call
nuclear@0 86 return false;
nuclear@0 87 }
nuclear@0 88
nuclear@0 89 OVR::Net::BitStream out;
nuclear@0 90 out.Write((MessageID) OVRID_RPC1);
nuclear@0 91 out.Write((MessageID) CALL_BLOCKING);
nuclear@0 92 out.Write(uniqueID);
nuclear@0 93 if (bitStream)
nuclear@0 94 {
nuclear@0 95 bitStream->ResetReadPointer();
nuclear@0 96 out.AlignWriteToByteBoundary();
nuclear@0 97 out.Write(bitStream);
nuclear@0 98 }
nuclear@0 99
nuclear@0 100 SendParameters sp(pConnection, out.GetData(), out.GetNumberOfBytesUsed());
nuclear@0 101
nuclear@0 102 if (returnData)
nuclear@0 103 {
nuclear@0 104 returnData->Reset();
nuclear@0 105 }
nuclear@0 106
nuclear@0 107 // Only one thread call at a time
nuclear@0 108 Lock::Locker singleRPCLocker(&singleRPCLock);
nuclear@0 109
nuclear@0 110 // Note this does not prevent multiple calls at a time because .Wait will unlock it below.
nuclear@0 111 // The purpose of this mutex is to synchronize the polling thread and this one, not prevent
nuclear@0 112 // multiple threads from invoking RPC.
nuclear@0 113 Mutex::Locker locker(&callBlockingMutex);
nuclear@0 114
nuclear@0 115 blockingReturnValue->Reset();
nuclear@0 116 blockingOnThisConnection = pConnection;
nuclear@0 117
nuclear@0 118 int bytesSent = pSession->Send(&sp);
nuclear@0 119 if (bytesSent == sp.Bytes)
nuclear@0 120 {
nuclear@0 121 while (blockingOnThisConnection == pConnection)
nuclear@0 122 {
nuclear@0 123 callBlockingWait.Wait(&callBlockingMutex);
nuclear@0 124 }
nuclear@0 125 }
nuclear@0 126 else
nuclear@0 127 {
nuclear@0 128 return false;
nuclear@0 129 }
nuclear@0 130
nuclear@0 131 if (returnData)
nuclear@0 132 {
nuclear@0 133 returnData->Write(blockingReturnValue);
nuclear@0 134 returnData->ResetReadPointer();
nuclear@0 135 }
nuclear@0 136
nuclear@0 137 return true;
nuclear@0 138 }
nuclear@0 139
nuclear@0 140 bool RPC1::Signal(OVR::String sharedIdentifier, OVR::Net::BitStream* bitStream, Ptr<Connection> pConnection)
nuclear@0 141 {
nuclear@0 142 OVR::Net::BitStream out;
nuclear@0 143 out.Write((MessageID) OVRID_RPC1);
nuclear@0 144 out.Write((MessageID) ID_RPC4_SIGNAL);
nuclear@0 145 //out.Write(PluginId);
nuclear@0 146 out.Write(sharedIdentifier);
nuclear@0 147 if (bitStream)
nuclear@0 148 {
nuclear@0 149 bitStream->ResetReadPointer();
nuclear@0 150 out.AlignWriteToByteBoundary();
nuclear@0 151 out.Write(bitStream);
nuclear@0 152 }
nuclear@0 153 SendParameters sp(pConnection, out.GetData(), out.GetNumberOfBytesUsed());
nuclear@0 154 int32_t bytesSent = pSession->Send(&sp);
nuclear@0 155 return bytesSent == sp.Bytes;
nuclear@0 156 }
nuclear@0 157 void RPC1::BroadcastSignal(OVR::String sharedIdentifier, OVR::Net::BitStream* bitStream)
nuclear@0 158 {
nuclear@0 159 OVR::Net::BitStream out;
nuclear@0 160 out.Write((MessageID) OVRID_RPC1);
nuclear@0 161 out.Write((MessageID) ID_RPC4_SIGNAL);
nuclear@0 162 //out.Write(PluginId);
nuclear@0 163 out.Write(sharedIdentifier);
nuclear@0 164 if (bitStream)
nuclear@0 165 {
nuclear@0 166 bitStream->ResetReadPointer();
nuclear@0 167 out.AlignWriteToByteBoundary();
nuclear@0 168 out.Write(bitStream);
nuclear@0 169 }
nuclear@0 170 BroadcastParameters p(out.GetData(), out.GetNumberOfBytesUsed());
nuclear@0 171 pSession->Broadcast(&p);
nuclear@0 172 }
nuclear@0 173 void RPC1::OnReceive(ReceivePayload *pPayload, ListenerReceiveResult *lrrOut)
nuclear@0 174 {
nuclear@0 175 OVR_UNUSED(lrrOut);
nuclear@0 176
nuclear@0 177 if (pPayload->pData[0] == OVRID_RPC1)
nuclear@0 178 {
nuclear@0 179 OVR_ASSERT(pPayload->Bytes >= 2);
nuclear@0 180
nuclear@0 181 OVR::Net::BitStream bsIn((char*)pPayload->pData, pPayload->Bytes, false);
nuclear@0 182 bsIn.IgnoreBytes(2);
nuclear@0 183
nuclear@0 184 if (pPayload->pData[1] == RPC_ERROR_FUNCTION_NOT_REGISTERED)
nuclear@0 185 {
nuclear@0 186 Mutex::Locker locker(&callBlockingMutex);
nuclear@0 187
nuclear@0 188 blockingReturnValue->Reset();
nuclear@0 189 blockingOnThisConnection = 0;
nuclear@0 190 callBlockingWait.NotifyAll();
nuclear@0 191 }
nuclear@0 192 else if (pPayload->pData[1] == ID_RPC4_RETURN)
nuclear@0 193 {
nuclear@0 194 Mutex::Locker locker(&callBlockingMutex);
nuclear@0 195
nuclear@0 196 blockingReturnValue->Reset();
nuclear@0 197 blockingReturnValue->Write(bsIn);
nuclear@0 198 blockingOnThisConnection = 0;
nuclear@0 199 callBlockingWait.NotifyAll();
nuclear@0 200 }
nuclear@0 201 else if (pPayload->pData[1] == CALL_BLOCKING)
nuclear@0 202 {
nuclear@0 203 OVR::String uniqueId;
nuclear@0 204 bsIn.Read(uniqueId);
nuclear@0 205
nuclear@0 206 RPCDelegate *bf = registeredBlockingFunctions.Get(uniqueId);
nuclear@0 207 if (bf==0)
nuclear@0 208 {
nuclear@0 209 OVR::Net::BitStream bsOut;
nuclear@0 210 bsOut.Write((unsigned char) OVRID_RPC1);
nuclear@0 211 bsOut.Write((unsigned char) RPC_ERROR_FUNCTION_NOT_REGISTERED);
nuclear@0 212
nuclear@0 213 SendParameters sp(pPayload->pConnection, bsOut.GetData(), bsOut.GetNumberOfBytesUsed());
nuclear@0 214 pSession->Send(&sp);
nuclear@0 215
nuclear@0 216 return;
nuclear@0 217 }
nuclear@0 218
nuclear@0 219 OVR::Net::BitStream returnData;
nuclear@0 220 bsIn.AlignReadToByteBoundary();
nuclear@0 221 (*bf)(&bsIn, &returnData, pPayload);
nuclear@0 222
nuclear@0 223 OVR::Net::BitStream out;
nuclear@0 224 out.Write((MessageID) OVRID_RPC1);
nuclear@0 225 out.Write((MessageID) ID_RPC4_RETURN);
nuclear@0 226 returnData.ResetReadPointer();
nuclear@0 227 out.AlignWriteToByteBoundary();
nuclear@0 228 out.Write(returnData);
nuclear@0 229
nuclear@0 230 SendParameters sp(pPayload->pConnection, out.GetData(), out.GetNumberOfBytesUsed());
nuclear@0 231 pSession->Send(&sp);
nuclear@0 232 }
nuclear@0 233 else if (pPayload->pData[1]==ID_RPC4_SIGNAL)
nuclear@0 234 {
nuclear@0 235 OVR::String sharedIdentifier;
nuclear@0 236 bsIn.Read(sharedIdentifier);
nuclear@0 237
nuclear@0 238 Observer<RPCSlot> *o = slotHash.GetSubject(sharedIdentifier);
nuclear@0 239
nuclear@0 240 if (o)
nuclear@0 241 {
nuclear@0 242 bsIn.AlignReadToByteBoundary();
nuclear@0 243
nuclear@0 244 if (o)
nuclear@0 245 {
nuclear@0 246 OVR::Net::BitStream serializedParameters(bsIn.GetData() + bsIn.GetReadOffset()/8, bsIn.GetNumberOfUnreadBits()/8, false);
nuclear@0 247
nuclear@0 248 o->Call(&serializedParameters, pPayload);
nuclear@0 249 }
nuclear@0 250 }
nuclear@0 251 }
nuclear@0 252 }
nuclear@0 253 }
nuclear@0 254
nuclear@0 255 void RPC1::OnDisconnected(Connection* conn)
nuclear@0 256 {
nuclear@0 257 if (blockingOnThisConnection == conn)
nuclear@0 258 {
nuclear@0 259 blockingOnThisConnection = 0;
nuclear@0 260 callBlockingWait.NotifyAll();
nuclear@0 261 }
nuclear@0 262 }
nuclear@0 263
nuclear@0 264 void RPC1::OnConnected(Connection* conn)
nuclear@0 265 {
nuclear@0 266 OVR_UNUSED(conn);
nuclear@0 267 }
nuclear@0 268
nuclear@0 269
nuclear@0 270 }}} // OVR::Net::Plugins