ovr_sdk

annotate LibOVR/Src/Net/OVR_Session.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_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