ovr_sdk

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