rev |
line source |
nuclear@0
|
1 /************************************************************************************
|
nuclear@0
|
2
|
nuclear@0
|
3 Filename : OVR_Session.h
|
nuclear@0
|
4 Content : One network session that provides connection/disconnection events.
|
nuclear@0
|
5 Created : June 10, 2014
|
nuclear@0
|
6 Authors : Kevin Jenkins, Chris Taylor
|
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_Session.h"
|
nuclear@0
|
28 #include "OVR_PacketizedTCPSocket.h"
|
nuclear@0
|
29 #include "../Kernel/OVR_Log.h"
|
nuclear@0
|
30 #include "../Service/Service_NetSessionCommon.h"
|
nuclear@0
|
31
|
nuclear@0
|
32 namespace OVR { namespace Net {
|
nuclear@0
|
33
|
nuclear@0
|
34
|
nuclear@0
|
35 //-----------------------------------------------------------------------------
|
nuclear@0
|
36 // Protocol
|
nuclear@0
|
37
|
nuclear@0
|
38 static const char* OfficialHelloString = "OculusVR_Hello";
|
nuclear@0
|
39 static const char* OfficialAuthorizedString = "OculusVR_Authorized";
|
nuclear@0
|
40
|
nuclear@0
|
41 void RPC_C2S_Hello::Generate(Net::BitStream* bs)
|
nuclear@0
|
42 {
|
nuclear@0
|
43 RPC_C2S_Hello hello;
|
nuclear@0
|
44 hello.HelloString = OfficialHelloString;
|
nuclear@0
|
45 hello.MajorVersion = RPCVersion_Major;
|
nuclear@0
|
46 hello.MinorVersion = RPCVersion_Minor;
|
nuclear@0
|
47 hello.PatchVersion = RPCVersion_Patch;
|
nuclear@0
|
48 hello.Serialize(bs);
|
nuclear@0
|
49 }
|
nuclear@0
|
50
|
nuclear@0
|
51 bool RPC_C2S_Hello::Validate()
|
nuclear@0
|
52 {
|
nuclear@0
|
53 return MajorVersion == RPCVersion_Major &&
|
nuclear@0
|
54 MinorVersion <= RPCVersion_Minor &&
|
nuclear@0
|
55 HelloString.CompareNoCase(OfficialHelloString) == 0;
|
nuclear@0
|
56 }
|
nuclear@0
|
57
|
nuclear@0
|
58 void RPC_S2C_Authorization::Generate(Net::BitStream* bs, String errorString)
|
nuclear@0
|
59 {
|
nuclear@0
|
60 RPC_S2C_Authorization auth;
|
nuclear@0
|
61 if (errorString.IsEmpty())
|
nuclear@0
|
62 {
|
nuclear@0
|
63 auth.AuthString = OfficialAuthorizedString;
|
nuclear@0
|
64 }
|
nuclear@0
|
65 else
|
nuclear@0
|
66 {
|
nuclear@0
|
67 auth.AuthString = errorString;
|
nuclear@0
|
68 }
|
nuclear@0
|
69 auth.MajorVersion = RPCVersion_Major;
|
nuclear@0
|
70 auth.MinorVersion = RPCVersion_Minor;
|
nuclear@0
|
71 auth.PatchVersion = RPCVersion_Patch;
|
nuclear@0
|
72 auth.Serialize(bs);
|
nuclear@0
|
73 }
|
nuclear@0
|
74
|
nuclear@0
|
75 bool RPC_S2C_Authorization::Validate()
|
nuclear@0
|
76 {
|
nuclear@0
|
77 return AuthString.CompareNoCase(OfficialAuthorizedString) == 0;
|
nuclear@0
|
78 }
|
nuclear@0
|
79
|
nuclear@0
|
80
|
nuclear@0
|
81 //-----------------------------------------------------------------------------
|
nuclear@0
|
82 // Session
|
nuclear@0
|
83
|
nuclear@0
|
84 void Session::Shutdown()
|
nuclear@0
|
85 {
|
nuclear@0
|
86 {
|
nuclear@0
|
87 Lock::Locker locker(&SocketListenersLock);
|
nuclear@0
|
88
|
nuclear@0
|
89 const int count = SocketListeners.GetSizeI();
|
nuclear@0
|
90 for (int i = 0; i < count; ++i)
|
nuclear@0
|
91 {
|
nuclear@0
|
92 SocketListeners[i]->Close();
|
nuclear@0
|
93 }
|
nuclear@0
|
94 }
|
nuclear@0
|
95
|
nuclear@0
|
96 Lock::Locker locker(&ConnectionsLock);
|
nuclear@0
|
97
|
nuclear@0
|
98 const int count = AllConnections.GetSizeI();
|
nuclear@0
|
99 for (int i = 0; i < count; ++i)
|
nuclear@0
|
100 {
|
nuclear@0
|
101 Connection* arrayItem = AllConnections[i].GetPtr();
|
nuclear@0
|
102
|
nuclear@0
|
103 if (arrayItem->Transport == TransportType_PacketizedTCP)
|
nuclear@0
|
104 {
|
nuclear@0
|
105 PacketizedTCPConnection* ptcp = (PacketizedTCPConnection*)arrayItem;
|
nuclear@0
|
106
|
nuclear@0
|
107 ptcp->pSocket->Close();
|
nuclear@0
|
108 }
|
nuclear@0
|
109 }
|
nuclear@0
|
110 }
|
nuclear@0
|
111
|
nuclear@0
|
112 SessionResult Session::Listen(ListenerDescription* pListenerDescription)
|
nuclear@0
|
113 {
|
nuclear@0
|
114 if (pListenerDescription->Transport == TransportType_PacketizedTCP)
|
nuclear@0
|
115 {
|
nuclear@0
|
116 BerkleyListenerDescription* bld = (BerkleyListenerDescription*)pListenerDescription;
|
nuclear@0
|
117 TCPSocket* tcpSocket = (TCPSocket*)bld->BoundSocketToListenWith.GetPtr();
|
nuclear@0
|
118
|
nuclear@0
|
119 if (tcpSocket->Listen() < 0)
|
nuclear@0
|
120 {
|
nuclear@0
|
121 return SessionResult_ListenFailure;
|
nuclear@0
|
122 }
|
nuclear@0
|
123
|
nuclear@0
|
124 Lock::Locker locker(&SocketListenersLock);
|
nuclear@0
|
125 SocketListeners.PushBack(tcpSocket);
|
nuclear@0
|
126 }
|
nuclear@0
|
127 else if (pListenerDescription->Transport == TransportType_Loopback)
|
nuclear@0
|
128 {
|
nuclear@0
|
129 HasLoopbackListener = true;
|
nuclear@0
|
130 }
|
nuclear@0
|
131 else
|
nuclear@0
|
132 {
|
nuclear@0
|
133 OVR_ASSERT(false);
|
nuclear@0
|
134 }
|
nuclear@0
|
135
|
nuclear@0
|
136 return SessionResult_OK;
|
nuclear@0
|
137 }
|
nuclear@0
|
138
|
nuclear@0
|
139 SessionResult Session::Connect(ConnectParameters *cp)
|
nuclear@0
|
140 {
|
nuclear@0
|
141 if (cp->Transport == TransportType_PacketizedTCP)
|
nuclear@0
|
142 {
|
nuclear@0
|
143 ConnectParametersBerkleySocket* cp2 = (ConnectParametersBerkleySocket*)cp;
|
nuclear@0
|
144 Ptr<PacketizedTCPConnection> c;
|
nuclear@0
|
145
|
nuclear@0
|
146 {
|
nuclear@0
|
147 Lock::Locker locker(&ConnectionsLock);
|
nuclear@0
|
148
|
nuclear@0
|
149 int connIndex;
|
nuclear@0
|
150 Ptr<PacketizedTCPConnection> conn = findConnectionBySocket(AllConnections, cp2->BoundSocketToConnectWith, &connIndex);
|
nuclear@0
|
151 if (conn)
|
nuclear@0
|
152 {
|
nuclear@0
|
153 return SessionResult_AlreadyConnected;
|
nuclear@0
|
154 }
|
nuclear@0
|
155
|
nuclear@0
|
156 TCPSocketBase* tcpSock = (TCPSocketBase*)cp2->BoundSocketToConnectWith.GetPtr();
|
nuclear@0
|
157
|
nuclear@0
|
158 int ret = tcpSock->Connect(&cp2->RemoteAddress);
|
nuclear@0
|
159 if (ret < 0)
|
nuclear@0
|
160 {
|
nuclear@0
|
161 return SessionResult_ConnectFailure;
|
nuclear@0
|
162 }
|
nuclear@0
|
163
|
nuclear@0
|
164 Ptr<Connection> newConnection = AllocConnection(cp2->Transport);
|
nuclear@0
|
165 if (!newConnection)
|
nuclear@0
|
166 {
|
nuclear@0
|
167 return SessionResult_ConnectFailure;
|
nuclear@0
|
168 }
|
nuclear@0
|
169
|
nuclear@0
|
170 c = (PacketizedTCPConnection*)newConnection.GetPtr();
|
nuclear@0
|
171 c->pSocket = (TCPSocket*) cp2->BoundSocketToConnectWith.GetPtr();
|
nuclear@0
|
172 c->Address = cp2->RemoteAddress;
|
nuclear@0
|
173 c->Transport = cp2->Transport;
|
nuclear@0
|
174 c->SetState(Client_Connecting);
|
nuclear@0
|
175
|
nuclear@0
|
176 AllConnections.PushBack(c);
|
nuclear@0
|
177
|
nuclear@0
|
178 }
|
nuclear@0
|
179
|
nuclear@0
|
180 if (cp2->Blocking)
|
nuclear@0
|
181 {
|
nuclear@0
|
182 c->WaitOnConnecting();
|
nuclear@0
|
183 }
|
nuclear@0
|
184
|
nuclear@0
|
185 if (c->State == State_Connected)
|
nuclear@0
|
186 {
|
nuclear@0
|
187 return SessionResult_OK;
|
nuclear@0
|
188 }
|
nuclear@0
|
189 else if (c->State == Client_Connecting)
|
nuclear@0
|
190 {
|
nuclear@0
|
191 return SessionResult_ConnectInProgress;
|
nuclear@0
|
192 }
|
nuclear@0
|
193 else
|
nuclear@0
|
194 {
|
nuclear@0
|
195 return SessionResult_ConnectFailure;
|
nuclear@0
|
196 }
|
nuclear@0
|
197 }
|
nuclear@0
|
198 else if (cp->Transport == TransportType_Loopback)
|
nuclear@0
|
199 {
|
nuclear@0
|
200 if (HasLoopbackListener)
|
nuclear@0
|
201 {
|
nuclear@0
|
202 Ptr<Connection> c = AllocConnection(cp->Transport);
|
nuclear@0
|
203 if (!c)
|
nuclear@0
|
204 {
|
nuclear@0
|
205 return SessionResult_ConnectFailure;
|
nuclear@0
|
206 }
|
nuclear@0
|
207
|
nuclear@0
|
208 c->Transport = cp->Transport;
|
nuclear@0
|
209 c->SetState(State_Connected);
|
nuclear@0
|
210
|
nuclear@0
|
211 {
|
nuclear@0
|
212 Lock::Locker locker(&ConnectionsLock);
|
nuclear@0
|
213 AllConnections.PushBack(c);
|
nuclear@0
|
214 }
|
nuclear@0
|
215
|
nuclear@0
|
216 invokeSessionEvent(&SessionListener::OnConnectionRequestAccepted, c);
|
nuclear@0
|
217 }
|
nuclear@0
|
218 else
|
nuclear@0
|
219 {
|
nuclear@0
|
220 OVR_ASSERT(false);
|
nuclear@0
|
221 }
|
nuclear@0
|
222 }
|
nuclear@0
|
223 else
|
nuclear@0
|
224 {
|
nuclear@0
|
225 OVR_ASSERT(false);
|
nuclear@0
|
226 }
|
nuclear@0
|
227
|
nuclear@0
|
228 return SessionResult_OK;
|
nuclear@0
|
229 }
|
nuclear@0
|
230
|
nuclear@0
|
231 SessionResult Session::ListenPTCP(OVR::Net::BerkleyBindParameters *bbp)
|
nuclear@0
|
232 {
|
nuclear@0
|
233 Ptr<PacketizedTCPSocket> listenSocket = *new OVR::Net::PacketizedTCPSocket();
|
nuclear@0
|
234 if (listenSocket->Bind(bbp) == INVALID_SOCKET)
|
nuclear@0
|
235 {
|
nuclear@0
|
236 return SessionResult_BindFailure;
|
nuclear@0
|
237 }
|
nuclear@0
|
238
|
nuclear@0
|
239 BerkleyListenerDescription bld;
|
nuclear@0
|
240 bld.BoundSocketToListenWith = listenSocket.GetPtr();
|
nuclear@0
|
241 bld.Transport = TransportType_PacketizedTCP;
|
nuclear@0
|
242
|
nuclear@0
|
243 return Listen(&bld);
|
nuclear@0
|
244 }
|
nuclear@0
|
245
|
nuclear@0
|
246 SessionResult Session::ConnectPTCP(OVR::Net::BerkleyBindParameters* bbp, SockAddr* remoteAddress, bool blocking)
|
nuclear@0
|
247 {
|
nuclear@0
|
248 ConnectParametersBerkleySocket cp(NULL, remoteAddress, blocking, TransportType_PacketizedTCP);
|
nuclear@0
|
249 Ptr<PacketizedTCPSocket> connectSocket = *new PacketizedTCPSocket();
|
nuclear@0
|
250
|
nuclear@0
|
251 cp.BoundSocketToConnectWith = connectSocket.GetPtr();
|
nuclear@0
|
252 if (connectSocket->Bind(bbp) == INVALID_SOCKET)
|
nuclear@0
|
253 {
|
nuclear@0
|
254 return SessionResult_BindFailure;
|
nuclear@0
|
255 }
|
nuclear@0
|
256
|
nuclear@0
|
257 return Connect(&cp);
|
nuclear@0
|
258 }
|
nuclear@0
|
259
|
nuclear@0
|
260 Ptr<PacketizedTCPConnection> Session::findConnectionBySockAddr(SockAddr* address)
|
nuclear@0
|
261 {
|
nuclear@0
|
262 const int count = AllConnections.GetSizeI();
|
nuclear@0
|
263 for (int i = 0; i < count; ++i)
|
nuclear@0
|
264 {
|
nuclear@0
|
265 Connection* arrayItem = AllConnections[i].GetPtr();
|
nuclear@0
|
266
|
nuclear@0
|
267 if (arrayItem->Transport == TransportType_PacketizedTCP)
|
nuclear@0
|
268 {
|
nuclear@0
|
269 PacketizedTCPConnection* conn = (PacketizedTCPConnection*)arrayItem;
|
nuclear@0
|
270
|
nuclear@0
|
271 if (conn->Address == *address)
|
nuclear@0
|
272 {
|
nuclear@0
|
273 return conn;
|
nuclear@0
|
274 }
|
nuclear@0
|
275 }
|
nuclear@0
|
276 }
|
nuclear@0
|
277
|
nuclear@0
|
278 return 0;
|
nuclear@0
|
279 }
|
nuclear@0
|
280
|
nuclear@0
|
281 int Session::Send(SendParameters *payload)
|
nuclear@0
|
282 {
|
nuclear@0
|
283 if (payload->pConnection->Transport == TransportType_Loopback)
|
nuclear@0
|
284 {
|
nuclear@0
|
285 Lock::Locker locker(&SessionListenersLock);
|
nuclear@0
|
286
|
nuclear@0
|
287 const int count = SessionListeners.GetSizeI();
|
nuclear@0
|
288 for (int i = 0; i < count; ++i)
|
nuclear@0
|
289 {
|
nuclear@0
|
290 SessionListener* sl = SessionListeners[i];
|
nuclear@0
|
291
|
nuclear@0
|
292 // FIXME: This looks like it needs to be reviewed at some point..
|
nuclear@0
|
293 ReceivePayload rp;
|
nuclear@0
|
294 rp.Bytes = payload->Bytes;
|
nuclear@0
|
295 rp.pConnection = payload->pConnection;
|
nuclear@0
|
296 rp.pData = (uint8_t*)payload->pData; // FIXME
|
nuclear@0
|
297 ListenerReceiveResult lrr = LRR_CONTINUE;
|
nuclear@0
|
298 sl->OnReceive(&rp, &lrr);
|
nuclear@0
|
299 if (lrr == LRR_RETURN)
|
nuclear@0
|
300 {
|
nuclear@0
|
301 return payload->Bytes;
|
nuclear@0
|
302 }
|
nuclear@0
|
303 else if (lrr == LRR_BREAK)
|
nuclear@0
|
304 {
|
nuclear@0
|
305 break;
|
nuclear@0
|
306 }
|
nuclear@0
|
307 }
|
nuclear@0
|
308
|
nuclear@0
|
309 return payload->Bytes;
|
nuclear@0
|
310 }
|
nuclear@0
|
311 else if (payload->pConnection->Transport == TransportType_PacketizedTCP)
|
nuclear@0
|
312 {
|
nuclear@0
|
313 PacketizedTCPConnection* conn = (PacketizedTCPConnection*)payload->pConnection.GetPtr();
|
nuclear@0
|
314
|
nuclear@0
|
315 return conn->pSocket->Send(payload->pData, payload->Bytes);
|
nuclear@0
|
316 }
|
nuclear@0
|
317 else
|
nuclear@0
|
318 {
|
nuclear@0
|
319 OVR_ASSERT(false);
|
nuclear@0
|
320 }
|
nuclear@0
|
321
|
nuclear@0
|
322 return 0;
|
nuclear@0
|
323 }
|
nuclear@0
|
324 void Session::Broadcast(BroadcastParameters *payload)
|
nuclear@0
|
325 {
|
nuclear@0
|
326 SendParameters sp;
|
nuclear@0
|
327 sp.Bytes=payload->Bytes;
|
nuclear@0
|
328 sp.pData=payload->pData;
|
nuclear@0
|
329
|
nuclear@0
|
330 {
|
nuclear@0
|
331 Lock::Locker locker(&ConnectionsLock);
|
nuclear@0
|
332
|
nuclear@0
|
333 const int connectionCount = FullConnections.GetSizeI();
|
nuclear@0
|
334 for (int i = 0; i < connectionCount; ++i)
|
nuclear@0
|
335 {
|
nuclear@0
|
336 sp.pConnection = FullConnections[i];
|
nuclear@0
|
337 Send(&sp);
|
nuclear@0
|
338 }
|
nuclear@0
|
339 }
|
nuclear@0
|
340 }
|
nuclear@0
|
341 // DO NOT CALL Poll() FROM MULTIPLE THREADS due to allBlockingTcpSockets being a member
|
nuclear@0
|
342 void Session::Poll(bool listeners)
|
nuclear@0
|
343 {
|
nuclear@0
|
344 allBlockingTcpSockets.Clear();
|
nuclear@0
|
345
|
nuclear@0
|
346 if (listeners)
|
nuclear@0
|
347 {
|
nuclear@0
|
348 Lock::Locker locker(&SocketListenersLock);
|
nuclear@0
|
349
|
nuclear@0
|
350 const int listenerCount = SocketListeners.GetSizeI();
|
nuclear@0
|
351 for (int i = 0; i < listenerCount; ++i)
|
nuclear@0
|
352 {
|
nuclear@0
|
353 allBlockingTcpSockets.PushBack(SocketListeners[i]);
|
nuclear@0
|
354 }
|
nuclear@0
|
355 }
|
nuclear@0
|
356
|
nuclear@0
|
357 {
|
nuclear@0
|
358 Lock::Locker locker(&ConnectionsLock);
|
nuclear@0
|
359
|
nuclear@0
|
360 const int connectionCount = AllConnections.GetSizeI();
|
nuclear@0
|
361 for (int i = 0; i < connectionCount; ++i)
|
nuclear@0
|
362 {
|
nuclear@0
|
363 Connection* arrayItem = AllConnections[i].GetPtr();
|
nuclear@0
|
364
|
nuclear@0
|
365 if (arrayItem->Transport == TransportType_PacketizedTCP)
|
nuclear@0
|
366 {
|
nuclear@0
|
367 PacketizedTCPConnection* ptcp = (PacketizedTCPConnection*)arrayItem;
|
nuclear@0
|
368
|
nuclear@0
|
369 allBlockingTcpSockets.PushBack(ptcp->pSocket);
|
nuclear@0
|
370 }
|
nuclear@0
|
371 else
|
nuclear@0
|
372 {
|
nuclear@0
|
373 OVR_ASSERT(false);
|
nuclear@0
|
374 }
|
nuclear@0
|
375 }
|
nuclear@0
|
376 }
|
nuclear@0
|
377
|
nuclear@0
|
378 const int count = allBlockingTcpSockets.GetSizeI();
|
nuclear@0
|
379 if (count > 0)
|
nuclear@0
|
380 {
|
nuclear@0
|
381 TCPSocketPollState state;
|
nuclear@0
|
382
|
nuclear@0
|
383 // Add all the sockets for polling,
|
nuclear@0
|
384 for (int i = 0; i < count; ++i)
|
nuclear@0
|
385 {
|
nuclear@0
|
386 Net::TCPSocket* sock = allBlockingTcpSockets[i].GetPtr();
|
nuclear@0
|
387
|
nuclear@0
|
388 // If socket handle is invalid,
|
nuclear@0
|
389 if (sock->GetSocketHandle() == INVALID_SOCKET)
|
nuclear@0
|
390 {
|
nuclear@0
|
391 OVR_DEBUG_LOG(("[Session] Detected an invalid socket handle - Treating it as a disconnection."));
|
nuclear@0
|
392 sock->IsConnecting = false;
|
nuclear@0
|
393 TCP_OnClosed(sock);
|
nuclear@0
|
394 }
|
nuclear@0
|
395 else
|
nuclear@0
|
396 {
|
nuclear@0
|
397 state.Add(sock);
|
nuclear@0
|
398 }
|
nuclear@0
|
399 }
|
nuclear@0
|
400
|
nuclear@0
|
401 // If polling returns with an event,
|
nuclear@0
|
402 if (state.Poll(allBlockingTcpSockets[0]->GetBlockingTimeoutUsec(), allBlockingTcpSockets[0]->GetBlockingTimeoutSec()))
|
nuclear@0
|
403 {
|
nuclear@0
|
404 // Handle any events for each socket
|
nuclear@0
|
405 for (int i = 0; i < count; ++i)
|
nuclear@0
|
406 {
|
nuclear@0
|
407 state.HandleEvent(allBlockingTcpSockets[i], this);
|
nuclear@0
|
408 }
|
nuclear@0
|
409 }
|
nuclear@0
|
410 }
|
nuclear@0
|
411 }
|
nuclear@0
|
412
|
nuclear@0
|
413 void Session::AddSessionListener(SessionListener* se)
|
nuclear@0
|
414 {
|
nuclear@0
|
415 Lock::Locker locker(&SessionListenersLock);
|
nuclear@0
|
416
|
nuclear@0
|
417 const int count = SessionListeners.GetSizeI();
|
nuclear@0
|
418 for (int i = 0; i < count; ++i)
|
nuclear@0
|
419 {
|
nuclear@0
|
420 if (SessionListeners[i] == se)
|
nuclear@0
|
421 {
|
nuclear@0
|
422 // Already added
|
nuclear@0
|
423 return;
|
nuclear@0
|
424 }
|
nuclear@0
|
425 }
|
nuclear@0
|
426
|
nuclear@0
|
427 SessionListeners.PushBack(se);
|
nuclear@0
|
428 se->OnAddedToSession(this);
|
nuclear@0
|
429 }
|
nuclear@0
|
430
|
nuclear@0
|
431 void Session::RemoveSessionListener(SessionListener* se)
|
nuclear@0
|
432 {
|
nuclear@0
|
433 Lock::Locker locker(&SessionListenersLock);
|
nuclear@0
|
434
|
nuclear@0
|
435 const int count = SessionListeners.GetSizeI();
|
nuclear@0
|
436 for (int i = 0; i < count; ++i)
|
nuclear@0
|
437 {
|
nuclear@0
|
438 if (SessionListeners[i] == se)
|
nuclear@0
|
439 {
|
nuclear@0
|
440 se->OnRemovedFromSession(this);
|
nuclear@0
|
441
|
nuclear@0
|
442 SessionListeners.RemoveAtUnordered(i);
|
nuclear@0
|
443 break;
|
nuclear@0
|
444 }
|
nuclear@0
|
445 }
|
nuclear@0
|
446 }
|
nuclear@0
|
447 SInt32 Session::GetActiveSocketsCount()
|
nuclear@0
|
448 {
|
nuclear@0
|
449 Lock::Locker locker1(&SocketListenersLock);
|
nuclear@0
|
450 Lock::Locker locker2(&ConnectionsLock);
|
nuclear@0
|
451 return SocketListeners.GetSize() + AllConnections.GetSize()>0;
|
nuclear@0
|
452 }
|
nuclear@0
|
453 Ptr<Connection> Session::AllocConnection(TransportType transport)
|
nuclear@0
|
454 {
|
nuclear@0
|
455 switch (transport)
|
nuclear@0
|
456 {
|
nuclear@0
|
457 case TransportType_Loopback: return *new Connection();
|
nuclear@0
|
458 case TransportType_TCP: return *new TCPConnection();
|
nuclear@0
|
459 case TransportType_PacketizedTCP: return *new PacketizedTCPConnection();
|
nuclear@0
|
460 default:
|
nuclear@0
|
461 OVR_ASSERT(false);
|
nuclear@0
|
462 break;
|
nuclear@0
|
463 }
|
nuclear@0
|
464
|
nuclear@0
|
465 return NULL;
|
nuclear@0
|
466 }
|
nuclear@0
|
467
|
nuclear@0
|
468 Ptr<PacketizedTCPConnection> Session::findConnectionBySocket(Array< Ptr<Connection> >& connectionArray, Socket* s, int *connectionIndex)
|
nuclear@0
|
469 {
|
nuclear@0
|
470 const int count = connectionArray.GetSizeI();
|
nuclear@0
|
471 for (int i = 0; i < count; ++i)
|
nuclear@0
|
472 {
|
nuclear@0
|
473 Connection* arrayItem = connectionArray[i].GetPtr();
|
nuclear@0
|
474
|
nuclear@0
|
475 if (arrayItem->Transport == TransportType_PacketizedTCP)
|
nuclear@0
|
476 {
|
nuclear@0
|
477 PacketizedTCPConnection* ptc = (PacketizedTCPConnection*)arrayItem;
|
nuclear@0
|
478
|
nuclear@0
|
479 if (ptc->pSocket == s)
|
nuclear@0
|
480 {
|
nuclear@0
|
481 if (connectionIndex)
|
nuclear@0
|
482 {
|
nuclear@0
|
483 *connectionIndex = i;
|
nuclear@0
|
484 }
|
nuclear@0
|
485 return ptc;
|
nuclear@0
|
486 }
|
nuclear@0
|
487 }
|
nuclear@0
|
488 }
|
nuclear@0
|
489
|
nuclear@0
|
490 return NULL;
|
nuclear@0
|
491 }
|
nuclear@0
|
492
|
nuclear@0
|
493 int Session::invokeSessionListeners(ReceivePayload* rp)
|
nuclear@0
|
494 {
|
nuclear@0
|
495 Lock::Locker locker(&SessionListenersLock);
|
nuclear@0
|
496
|
nuclear@0
|
497 const int count = SessionListeners.GetSizeI();
|
nuclear@0
|
498 for (int j = 0; j < count; ++j)
|
nuclear@0
|
499 {
|
nuclear@0
|
500 ListenerReceiveResult lrr = LRR_CONTINUE;
|
nuclear@0
|
501 SessionListeners[j]->OnReceive(rp, &lrr);
|
nuclear@0
|
502
|
nuclear@0
|
503 if (lrr == LRR_RETURN || lrr == LRR_BREAK)
|
nuclear@0
|
504 {
|
nuclear@0
|
505 break;
|
nuclear@0
|
506 }
|
nuclear@0
|
507 }
|
nuclear@0
|
508
|
nuclear@0
|
509 return rp->Bytes;
|
nuclear@0
|
510 }
|
nuclear@0
|
511
|
nuclear@0
|
512 void Session::TCP_OnRecv(Socket* pSocket, uint8_t* pData, int bytesRead)
|
nuclear@0
|
513 {
|
nuclear@0
|
514 // KevinJ: 9/2/2014 Fix deadlock - Watchdog calls Broadcast(), which locks ConnectionsLock().
|
nuclear@0
|
515 // Lock::Locker locker(&ConnectionsLock);
|
nuclear@0
|
516
|
nuclear@0
|
517 // Look for the connection in the full connection list first
|
nuclear@0
|
518 int connIndex;
|
nuclear@0
|
519 ConnectionsLock.DoLock();
|
nuclear@0
|
520 Ptr<PacketizedTCPConnection> conn = findConnectionBySocket(AllConnections, pSocket, &connIndex);
|
nuclear@0
|
521 ConnectionsLock.Unlock();
|
nuclear@0
|
522 if (conn)
|
nuclear@0
|
523 {
|
nuclear@0
|
524 if (conn->State == State_Connected)
|
nuclear@0
|
525 {
|
nuclear@0
|
526 ReceivePayload rp;
|
nuclear@0
|
527 rp.Bytes = bytesRead;
|
nuclear@0
|
528 rp.pConnection = conn;
|
nuclear@0
|
529 rp.pData = pData;
|
nuclear@0
|
530
|
nuclear@0
|
531 // Call listeners
|
nuclear@0
|
532 invokeSessionListeners(&rp);
|
nuclear@0
|
533 }
|
nuclear@0
|
534 else if (conn->State == Client_ConnectedWait)
|
nuclear@0
|
535 {
|
nuclear@0
|
536 // Check the version data from the message
|
nuclear@0
|
537 BitStream bsIn((char*)pData, bytesRead, false);
|
nuclear@0
|
538
|
nuclear@0
|
539 RPC_S2C_Authorization auth;
|
nuclear@0
|
540 if (!auth.Deserialize(&bsIn) ||
|
nuclear@0
|
541 !auth.Validate())
|
nuclear@0
|
542 {
|
nuclear@0
|
543 LogError("{ERR-001} [Session] REJECTED: OVRService did not authorize us: %s", auth.AuthString.ToCStr());
|
nuclear@0
|
544
|
nuclear@0
|
545 conn->SetState(State_Zombie);
|
nuclear@0
|
546 invokeSessionEvent(&SessionListener::OnIncompatibleProtocol, conn);
|
nuclear@0
|
547 }
|
nuclear@0
|
548 else
|
nuclear@0
|
549 {
|
nuclear@0
|
550 // Read remote version
|
nuclear@0
|
551 conn->RemoteMajorVersion = auth.MajorVersion;
|
nuclear@0
|
552 conn->RemoteMinorVersion = auth.MinorVersion;
|
nuclear@0
|
553 conn->RemotePatchVersion = auth.PatchVersion;
|
nuclear@0
|
554
|
nuclear@0
|
555 // Mark as connected
|
nuclear@0
|
556 conn->SetState(State_Connected);
|
nuclear@0
|
557 ConnectionsLock.DoLock();
|
nuclear@0
|
558 int connIndex2;
|
nuclear@0
|
559 if (findConnectionBySocket(AllConnections, pSocket, &connIndex2)==conn && findConnectionBySocket(FullConnections, pSocket, &connIndex2)==NULL)
|
nuclear@0
|
560 {
|
nuclear@0
|
561 FullConnections.PushBack(conn);
|
nuclear@0
|
562 }
|
nuclear@0
|
563 ConnectionsLock.Unlock();
|
nuclear@0
|
564 invokeSessionEvent(&SessionListener::OnConnectionRequestAccepted, conn);
|
nuclear@0
|
565 }
|
nuclear@0
|
566 }
|
nuclear@0
|
567 else if (conn->State == Server_ConnectedWait)
|
nuclear@0
|
568 {
|
nuclear@0
|
569 // Check the version data from the message
|
nuclear@0
|
570 BitStream bsIn((char*)pData, bytesRead, false);
|
nuclear@0
|
571
|
nuclear@0
|
572 RPC_C2S_Hello hello;
|
nuclear@0
|
573 if (!hello.Deserialize(&bsIn) ||
|
nuclear@0
|
574 !hello.Validate())
|
nuclear@0
|
575 {
|
nuclear@0
|
576 LogError("{ERR-002} [Session] REJECTED: Rift application is using an incompatible version %d.%d.%d (my version=%d.%d.%d)",
|
nuclear@0
|
577 hello.MajorVersion, hello.MinorVersion, hello.PatchVersion,
|
nuclear@0
|
578 RPCVersion_Major, RPCVersion_Minor, RPCVersion_Patch);
|
nuclear@0
|
579
|
nuclear@0
|
580 conn->SetState(State_Zombie);
|
nuclear@0
|
581
|
nuclear@0
|
582 // Send auth response
|
nuclear@0
|
583 BitStream bsOut;
|
nuclear@0
|
584 RPC_S2C_Authorization::Generate(&bsOut, "Incompatible protocol version. Please make sure your OVRService and SDK are both up to date.");
|
nuclear@0
|
585 conn->pSocket->Send(bsOut.GetData(), bsOut.GetNumberOfBytesUsed());
|
nuclear@0
|
586 }
|
nuclear@0
|
587 else
|
nuclear@0
|
588 {
|
nuclear@0
|
589 // Read remote version
|
nuclear@0
|
590 conn->RemoteMajorVersion = hello.MajorVersion;
|
nuclear@0
|
591 conn->RemoteMinorVersion = hello.MinorVersion;
|
nuclear@0
|
592 conn->RemotePatchVersion = hello.PatchVersion;
|
nuclear@0
|
593
|
nuclear@0
|
594 // Send auth response
|
nuclear@0
|
595 BitStream bsOut;
|
nuclear@0
|
596 RPC_S2C_Authorization::Generate(&bsOut);
|
nuclear@0
|
597 conn->pSocket->Send(bsOut.GetData(), bsOut.GetNumberOfBytesUsed());
|
nuclear@0
|
598
|
nuclear@0
|
599 // Mark as connected
|
nuclear@0
|
600 conn->SetState(State_Connected);
|
nuclear@0
|
601 ConnectionsLock.DoLock();
|
nuclear@0
|
602 int connIndex2;
|
nuclear@0
|
603 if (findConnectionBySocket(AllConnections, pSocket, &connIndex2)==conn && findConnectionBySocket(FullConnections, pSocket, &connIndex2)==NULL)
|
nuclear@0
|
604 {
|
nuclear@0
|
605 FullConnections.PushBack(conn);
|
nuclear@0
|
606 }
|
nuclear@0
|
607 ConnectionsLock.Unlock();
|
nuclear@0
|
608 invokeSessionEvent(&SessionListener::OnNewIncomingConnection, conn);
|
nuclear@0
|
609
|
nuclear@0
|
610 }
|
nuclear@0
|
611 }
|
nuclear@0
|
612 else
|
nuclear@0
|
613 {
|
nuclear@0
|
614 OVR_ASSERT(false);
|
nuclear@0
|
615 }
|
nuclear@0
|
616 }
|
nuclear@0
|
617 }
|
nuclear@0
|
618
|
nuclear@0
|
619 void Session::TCP_OnClosed(TCPSocket* s)
|
nuclear@0
|
620 {
|
nuclear@0
|
621 Lock::Locker locker(&ConnectionsLock);
|
nuclear@0
|
622
|
nuclear@0
|
623 // If found in the full connection list,
|
nuclear@0
|
624 int connIndex;
|
nuclear@0
|
625 Ptr<PacketizedTCPConnection> conn = findConnectionBySocket(AllConnections, s, &connIndex);
|
nuclear@0
|
626 if (conn)
|
nuclear@0
|
627 {
|
nuclear@0
|
628 AllConnections.RemoveAtUnordered(connIndex);
|
nuclear@0
|
629
|
nuclear@0
|
630 // If in the full connection list,
|
nuclear@0
|
631 if (findConnectionBySocket(FullConnections, s, &connIndex))
|
nuclear@0
|
632 {
|
nuclear@0
|
633 FullConnections.RemoveAtUnordered(connIndex);
|
nuclear@0
|
634 }
|
nuclear@0
|
635
|
nuclear@0
|
636 // Generate an appropriate event for the current state
|
nuclear@0
|
637 switch (conn->State)
|
nuclear@0
|
638 {
|
nuclear@0
|
639 case Client_Connecting:
|
nuclear@0
|
640 invokeSessionEvent(&SessionListener::OnConnectionAttemptFailed, conn);
|
nuclear@0
|
641 break;
|
nuclear@0
|
642 case Client_ConnectedWait:
|
nuclear@0
|
643 case Server_ConnectedWait:
|
nuclear@0
|
644 invokeSessionEvent(&SessionListener::OnHandshakeAttemptFailed, conn);
|
nuclear@0
|
645 break;
|
nuclear@0
|
646 case State_Connected:
|
nuclear@0
|
647 case State_Zombie:
|
nuclear@0
|
648 invokeSessionEvent(&SessionListener::OnDisconnected, conn);
|
nuclear@0
|
649 break;
|
nuclear@0
|
650 default:
|
nuclear@0
|
651 OVR_ASSERT(false);
|
nuclear@0
|
652 break;
|
nuclear@0
|
653 }
|
nuclear@0
|
654
|
nuclear@0
|
655 conn->SetState(State_Zombie);
|
nuclear@0
|
656 }
|
nuclear@0
|
657 }
|
nuclear@0
|
658
|
nuclear@0
|
659 void Session::TCP_OnAccept(TCPSocket* pListener, SockAddr* pSockAddr, SocketHandle newSock)
|
nuclear@0
|
660 {
|
nuclear@0
|
661 OVR_UNUSED(pListener);
|
nuclear@0
|
662 OVR_ASSERT(pListener->Transport == TransportType_PacketizedTCP);
|
nuclear@0
|
663
|
nuclear@0
|
664
|
nuclear@0
|
665 Ptr<PacketizedTCPSocket> newSocket = *new PacketizedTCPSocket(newSock, false);
|
nuclear@0
|
666 // If pSockAddr is not localhost, then close newSock
|
nuclear@0
|
667 if (pSockAddr->IsLocalhost()==false)
|
nuclear@0
|
668 {
|
nuclear@0
|
669 newSocket->Close();
|
nuclear@0
|
670 return;
|
nuclear@0
|
671 }
|
nuclear@0
|
672
|
nuclear@0
|
673 if (newSocket)
|
nuclear@0
|
674 {
|
nuclear@0
|
675 Ptr<Connection> b = AllocConnection(TransportType_PacketizedTCP);
|
nuclear@0
|
676 Ptr<PacketizedTCPConnection> c = (PacketizedTCPConnection*)b.GetPtr();
|
nuclear@0
|
677 c->pSocket = newSocket;
|
nuclear@0
|
678 c->Address = *pSockAddr;
|
nuclear@0
|
679 c->State = Server_ConnectedWait;
|
nuclear@0
|
680
|
nuclear@0
|
681 {
|
nuclear@0
|
682 Lock::Locker locker(&ConnectionsLock);
|
nuclear@0
|
683 AllConnections.PushBack(c);
|
nuclear@0
|
684 }
|
nuclear@0
|
685
|
nuclear@0
|
686 // Server does not send the first packet. It waits for the client to send its version
|
nuclear@0
|
687 }
|
nuclear@0
|
688 }
|
nuclear@0
|
689
|
nuclear@0
|
690 void Session::TCP_OnConnected(TCPSocket *s)
|
nuclear@0
|
691 {
|
nuclear@0
|
692 Lock::Locker locker(&ConnectionsLock);
|
nuclear@0
|
693
|
nuclear@0
|
694 // If connection was found,
|
nuclear@0
|
695 PacketizedTCPConnection* conn = findConnectionBySocket(AllConnections, s);
|
nuclear@0
|
696 if (conn)
|
nuclear@0
|
697 {
|
nuclear@0
|
698 OVR_ASSERT(conn->State == Client_Connecting);
|
nuclear@0
|
699
|
nuclear@0
|
700 // Send hello message
|
nuclear@0
|
701 BitStream bsOut;
|
nuclear@0
|
702 RPC_C2S_Hello::Generate(&bsOut);
|
nuclear@0
|
703 conn->pSocket->Send(bsOut.GetData(), bsOut.GetNumberOfBytesUsed());
|
nuclear@0
|
704
|
nuclear@0
|
705 // Just update state but do not generate any notifications yet
|
nuclear@0
|
706 conn->State = Client_ConnectedWait;
|
nuclear@0
|
707 }
|
nuclear@0
|
708 }
|
nuclear@0
|
709
|
nuclear@0
|
710 void Session::invokeSessionEvent(void(SessionListener::*f)(Connection*), Connection* conn)
|
nuclear@0
|
711 {
|
nuclear@0
|
712 Lock::Locker locker(&SessionListenersLock);
|
nuclear@0
|
713
|
nuclear@0
|
714 const int count = SessionListeners.GetSizeI();
|
nuclear@0
|
715 for (int i = 0; i < count; ++i)
|
nuclear@0
|
716 {
|
nuclear@0
|
717 (SessionListeners[i]->*f)(conn);
|
nuclear@0
|
718 }
|
nuclear@0
|
719 }
|
nuclear@0
|
720
|
nuclear@0
|
721 Ptr<Connection> Session::GetConnectionAtIndex(int index)
|
nuclear@0
|
722 {
|
nuclear@0
|
723 Lock::Locker locker(&ConnectionsLock);
|
nuclear@0
|
724
|
nuclear@0
|
725 const int count = FullConnections.GetSizeI();
|
nuclear@0
|
726
|
nuclear@0
|
727 if (index < count)
|
nuclear@0
|
728 {
|
nuclear@0
|
729 return FullConnections[index];
|
nuclear@0
|
730 }
|
nuclear@0
|
731
|
nuclear@0
|
732 return NULL;
|
nuclear@0
|
733 }
|
nuclear@0
|
734
|
nuclear@0
|
735
|
nuclear@0
|
736 }} // OVR::Net
|