ovr_sdk
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/Net/OVR_Session.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,736 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : OVR_Session.h 1.7 +Content : One network session that provides connection/disconnection events. 1.8 +Created : June 10, 2014 1.9 +Authors : Kevin Jenkins, Chris Taylor 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_Session.h" 1.31 +#include "OVR_PacketizedTCPSocket.h" 1.32 +#include "../Kernel/OVR_Log.h" 1.33 +#include "../Service/Service_NetSessionCommon.h" 1.34 + 1.35 +namespace OVR { namespace Net { 1.36 + 1.37 + 1.38 +//----------------------------------------------------------------------------- 1.39 +// Protocol 1.40 + 1.41 +static const char* OfficialHelloString = "OculusVR_Hello"; 1.42 +static const char* OfficialAuthorizedString = "OculusVR_Authorized"; 1.43 + 1.44 +void RPC_C2S_Hello::Generate(Net::BitStream* bs) 1.45 +{ 1.46 + RPC_C2S_Hello hello; 1.47 + hello.HelloString = OfficialHelloString; 1.48 + hello.MajorVersion = RPCVersion_Major; 1.49 + hello.MinorVersion = RPCVersion_Minor; 1.50 + hello.PatchVersion = RPCVersion_Patch; 1.51 + hello.Serialize(bs); 1.52 +} 1.53 + 1.54 +bool RPC_C2S_Hello::Validate() 1.55 +{ 1.56 + return MajorVersion == RPCVersion_Major && 1.57 + MinorVersion <= RPCVersion_Minor && 1.58 + HelloString.CompareNoCase(OfficialHelloString) == 0; 1.59 +} 1.60 + 1.61 +void RPC_S2C_Authorization::Generate(Net::BitStream* bs, String errorString) 1.62 +{ 1.63 + RPC_S2C_Authorization auth; 1.64 + if (errorString.IsEmpty()) 1.65 + { 1.66 + auth.AuthString = OfficialAuthorizedString; 1.67 + } 1.68 + else 1.69 + { 1.70 + auth.AuthString = errorString; 1.71 + } 1.72 + auth.MajorVersion = RPCVersion_Major; 1.73 + auth.MinorVersion = RPCVersion_Minor; 1.74 + auth.PatchVersion = RPCVersion_Patch; 1.75 + auth.Serialize(bs); 1.76 +} 1.77 + 1.78 +bool RPC_S2C_Authorization::Validate() 1.79 +{ 1.80 + return AuthString.CompareNoCase(OfficialAuthorizedString) == 0; 1.81 +} 1.82 + 1.83 + 1.84 +//----------------------------------------------------------------------------- 1.85 +// Session 1.86 + 1.87 +void Session::Shutdown() 1.88 +{ 1.89 + { 1.90 + Lock::Locker locker(&SocketListenersLock); 1.91 + 1.92 + const int count = SocketListeners.GetSizeI(); 1.93 + for (int i = 0; i < count; ++i) 1.94 + { 1.95 + SocketListeners[i]->Close(); 1.96 + } 1.97 + } 1.98 + 1.99 + Lock::Locker locker(&ConnectionsLock); 1.100 + 1.101 + const int count = AllConnections.GetSizeI(); 1.102 + for (int i = 0; i < count; ++i) 1.103 + { 1.104 + Connection* arrayItem = AllConnections[i].GetPtr(); 1.105 + 1.106 + if (arrayItem->Transport == TransportType_PacketizedTCP) 1.107 + { 1.108 + PacketizedTCPConnection* ptcp = (PacketizedTCPConnection*)arrayItem; 1.109 + 1.110 + ptcp->pSocket->Close(); 1.111 + } 1.112 + } 1.113 +} 1.114 + 1.115 +SessionResult Session::Listen(ListenerDescription* pListenerDescription) 1.116 +{ 1.117 + if (pListenerDescription->Transport == TransportType_PacketizedTCP) 1.118 + { 1.119 + BerkleyListenerDescription* bld = (BerkleyListenerDescription*)pListenerDescription; 1.120 + TCPSocket* tcpSocket = (TCPSocket*)bld->BoundSocketToListenWith.GetPtr(); 1.121 + 1.122 + if (tcpSocket->Listen() < 0) 1.123 + { 1.124 + return SessionResult_ListenFailure; 1.125 + } 1.126 + 1.127 + Lock::Locker locker(&SocketListenersLock); 1.128 + SocketListeners.PushBack(tcpSocket); 1.129 + } 1.130 + else if (pListenerDescription->Transport == TransportType_Loopback) 1.131 + { 1.132 + HasLoopbackListener = true; 1.133 + } 1.134 + else 1.135 + { 1.136 + OVR_ASSERT(false); 1.137 + } 1.138 + 1.139 + return SessionResult_OK; 1.140 +} 1.141 + 1.142 +SessionResult Session::Connect(ConnectParameters *cp) 1.143 +{ 1.144 + if (cp->Transport == TransportType_PacketizedTCP) 1.145 + { 1.146 + ConnectParametersBerkleySocket* cp2 = (ConnectParametersBerkleySocket*)cp; 1.147 + Ptr<PacketizedTCPConnection> c; 1.148 + 1.149 + { 1.150 + Lock::Locker locker(&ConnectionsLock); 1.151 + 1.152 + int connIndex; 1.153 + Ptr<PacketizedTCPConnection> conn = findConnectionBySocket(AllConnections, cp2->BoundSocketToConnectWith, &connIndex); 1.154 + if (conn) 1.155 + { 1.156 + return SessionResult_AlreadyConnected; 1.157 + } 1.158 + 1.159 + TCPSocketBase* tcpSock = (TCPSocketBase*)cp2->BoundSocketToConnectWith.GetPtr(); 1.160 + 1.161 + int ret = tcpSock->Connect(&cp2->RemoteAddress); 1.162 + if (ret < 0) 1.163 + { 1.164 + return SessionResult_ConnectFailure; 1.165 + } 1.166 + 1.167 + Ptr<Connection> newConnection = AllocConnection(cp2->Transport); 1.168 + if (!newConnection) 1.169 + { 1.170 + return SessionResult_ConnectFailure; 1.171 + } 1.172 + 1.173 + c = (PacketizedTCPConnection*)newConnection.GetPtr(); 1.174 + c->pSocket = (TCPSocket*) cp2->BoundSocketToConnectWith.GetPtr(); 1.175 + c->Address = cp2->RemoteAddress; 1.176 + c->Transport = cp2->Transport; 1.177 + c->SetState(Client_Connecting); 1.178 + 1.179 + AllConnections.PushBack(c); 1.180 + 1.181 + } 1.182 + 1.183 + if (cp2->Blocking) 1.184 + { 1.185 + c->WaitOnConnecting(); 1.186 + } 1.187 + 1.188 + if (c->State == State_Connected) 1.189 + { 1.190 + return SessionResult_OK; 1.191 + } 1.192 + else if (c->State == Client_Connecting) 1.193 + { 1.194 + return SessionResult_ConnectInProgress; 1.195 + } 1.196 + else 1.197 + { 1.198 + return SessionResult_ConnectFailure; 1.199 + } 1.200 + } 1.201 + else if (cp->Transport == TransportType_Loopback) 1.202 + { 1.203 + if (HasLoopbackListener) 1.204 + { 1.205 + Ptr<Connection> c = AllocConnection(cp->Transport); 1.206 + if (!c) 1.207 + { 1.208 + return SessionResult_ConnectFailure; 1.209 + } 1.210 + 1.211 + c->Transport = cp->Transport; 1.212 + c->SetState(State_Connected); 1.213 + 1.214 + { 1.215 + Lock::Locker locker(&ConnectionsLock); 1.216 + AllConnections.PushBack(c); 1.217 + } 1.218 + 1.219 + invokeSessionEvent(&SessionListener::OnConnectionRequestAccepted, c); 1.220 + } 1.221 + else 1.222 + { 1.223 + OVR_ASSERT(false); 1.224 + } 1.225 + } 1.226 + else 1.227 + { 1.228 + OVR_ASSERT(false); 1.229 + } 1.230 + 1.231 + return SessionResult_OK; 1.232 +} 1.233 + 1.234 +SessionResult Session::ListenPTCP(OVR::Net::BerkleyBindParameters *bbp) 1.235 +{ 1.236 + Ptr<PacketizedTCPSocket> listenSocket = *new OVR::Net::PacketizedTCPSocket(); 1.237 + if (listenSocket->Bind(bbp) == INVALID_SOCKET) 1.238 + { 1.239 + return SessionResult_BindFailure; 1.240 + } 1.241 + 1.242 + BerkleyListenerDescription bld; 1.243 + bld.BoundSocketToListenWith = listenSocket.GetPtr(); 1.244 + bld.Transport = TransportType_PacketizedTCP; 1.245 + 1.246 + return Listen(&bld); 1.247 +} 1.248 + 1.249 +SessionResult Session::ConnectPTCP(OVR::Net::BerkleyBindParameters* bbp, SockAddr* remoteAddress, bool blocking) 1.250 +{ 1.251 + ConnectParametersBerkleySocket cp(NULL, remoteAddress, blocking, TransportType_PacketizedTCP); 1.252 + Ptr<PacketizedTCPSocket> connectSocket = *new PacketizedTCPSocket(); 1.253 + 1.254 + cp.BoundSocketToConnectWith = connectSocket.GetPtr(); 1.255 + if (connectSocket->Bind(bbp) == INVALID_SOCKET) 1.256 + { 1.257 + return SessionResult_BindFailure; 1.258 + } 1.259 + 1.260 + return Connect(&cp); 1.261 +} 1.262 + 1.263 +Ptr<PacketizedTCPConnection> Session::findConnectionBySockAddr(SockAddr* address) 1.264 +{ 1.265 + const int count = AllConnections.GetSizeI(); 1.266 + for (int i = 0; i < count; ++i) 1.267 + { 1.268 + Connection* arrayItem = AllConnections[i].GetPtr(); 1.269 + 1.270 + if (arrayItem->Transport == TransportType_PacketizedTCP) 1.271 + { 1.272 + PacketizedTCPConnection* conn = (PacketizedTCPConnection*)arrayItem; 1.273 + 1.274 + if (conn->Address == *address) 1.275 + { 1.276 + return conn; 1.277 + } 1.278 + } 1.279 + } 1.280 + 1.281 + return 0; 1.282 +} 1.283 + 1.284 +int Session::Send(SendParameters *payload) 1.285 +{ 1.286 + if (payload->pConnection->Transport == TransportType_Loopback) 1.287 + { 1.288 + Lock::Locker locker(&SessionListenersLock); 1.289 + 1.290 + const int count = SessionListeners.GetSizeI(); 1.291 + for (int i = 0; i < count; ++i) 1.292 + { 1.293 + SessionListener* sl = SessionListeners[i]; 1.294 + 1.295 + // FIXME: This looks like it needs to be reviewed at some point.. 1.296 + ReceivePayload rp; 1.297 + rp.Bytes = payload->Bytes; 1.298 + rp.pConnection = payload->pConnection; 1.299 + rp.pData = (uint8_t*)payload->pData; // FIXME 1.300 + ListenerReceiveResult lrr = LRR_CONTINUE; 1.301 + sl->OnReceive(&rp, &lrr); 1.302 + if (lrr == LRR_RETURN) 1.303 + { 1.304 + return payload->Bytes; 1.305 + } 1.306 + else if (lrr == LRR_BREAK) 1.307 + { 1.308 + break; 1.309 + } 1.310 + } 1.311 + 1.312 + return payload->Bytes; 1.313 + } 1.314 + else if (payload->pConnection->Transport == TransportType_PacketizedTCP) 1.315 + { 1.316 + PacketizedTCPConnection* conn = (PacketizedTCPConnection*)payload->pConnection.GetPtr(); 1.317 + 1.318 + return conn->pSocket->Send(payload->pData, payload->Bytes); 1.319 + } 1.320 + else 1.321 + { 1.322 + OVR_ASSERT(false); 1.323 + } 1.324 + 1.325 + return 0; 1.326 +} 1.327 +void Session::Broadcast(BroadcastParameters *payload) 1.328 +{ 1.329 + SendParameters sp; 1.330 + sp.Bytes=payload->Bytes; 1.331 + sp.pData=payload->pData; 1.332 + 1.333 + { 1.334 + Lock::Locker locker(&ConnectionsLock); 1.335 + 1.336 + const int connectionCount = FullConnections.GetSizeI(); 1.337 + for (int i = 0; i < connectionCount; ++i) 1.338 + { 1.339 + sp.pConnection = FullConnections[i]; 1.340 + Send(&sp); 1.341 + } 1.342 + } 1.343 +} 1.344 +// DO NOT CALL Poll() FROM MULTIPLE THREADS due to allBlockingTcpSockets being a member 1.345 +void Session::Poll(bool listeners) 1.346 +{ 1.347 + allBlockingTcpSockets.Clear(); 1.348 + 1.349 + if (listeners) 1.350 + { 1.351 + Lock::Locker locker(&SocketListenersLock); 1.352 + 1.353 + const int listenerCount = SocketListeners.GetSizeI(); 1.354 + for (int i = 0; i < listenerCount; ++i) 1.355 + { 1.356 + allBlockingTcpSockets.PushBack(SocketListeners[i]); 1.357 + } 1.358 + } 1.359 + 1.360 + { 1.361 + Lock::Locker locker(&ConnectionsLock); 1.362 + 1.363 + const int connectionCount = AllConnections.GetSizeI(); 1.364 + for (int i = 0; i < connectionCount; ++i) 1.365 + { 1.366 + Connection* arrayItem = AllConnections[i].GetPtr(); 1.367 + 1.368 + if (arrayItem->Transport == TransportType_PacketizedTCP) 1.369 + { 1.370 + PacketizedTCPConnection* ptcp = (PacketizedTCPConnection*)arrayItem; 1.371 + 1.372 + allBlockingTcpSockets.PushBack(ptcp->pSocket); 1.373 + } 1.374 + else 1.375 + { 1.376 + OVR_ASSERT(false); 1.377 + } 1.378 + } 1.379 + } 1.380 + 1.381 + const int count = allBlockingTcpSockets.GetSizeI(); 1.382 + if (count > 0) 1.383 + { 1.384 + TCPSocketPollState state; 1.385 + 1.386 + // Add all the sockets for polling, 1.387 + for (int i = 0; i < count; ++i) 1.388 + { 1.389 + Net::TCPSocket* sock = allBlockingTcpSockets[i].GetPtr(); 1.390 + 1.391 + // If socket handle is invalid, 1.392 + if (sock->GetSocketHandle() == INVALID_SOCKET) 1.393 + { 1.394 + OVR_DEBUG_LOG(("[Session] Detected an invalid socket handle - Treating it as a disconnection.")); 1.395 + sock->IsConnecting = false; 1.396 + TCP_OnClosed(sock); 1.397 + } 1.398 + else 1.399 + { 1.400 + state.Add(sock); 1.401 + } 1.402 + } 1.403 + 1.404 + // If polling returns with an event, 1.405 + if (state.Poll(allBlockingTcpSockets[0]->GetBlockingTimeoutUsec(), allBlockingTcpSockets[0]->GetBlockingTimeoutSec())) 1.406 + { 1.407 + // Handle any events for each socket 1.408 + for (int i = 0; i < count; ++i) 1.409 + { 1.410 + state.HandleEvent(allBlockingTcpSockets[i], this); 1.411 + } 1.412 + } 1.413 + } 1.414 +} 1.415 + 1.416 +void Session::AddSessionListener(SessionListener* se) 1.417 +{ 1.418 + Lock::Locker locker(&SessionListenersLock); 1.419 + 1.420 + const int count = SessionListeners.GetSizeI(); 1.421 + for (int i = 0; i < count; ++i) 1.422 + { 1.423 + if (SessionListeners[i] == se) 1.424 + { 1.425 + // Already added 1.426 + return; 1.427 + } 1.428 + } 1.429 + 1.430 + SessionListeners.PushBack(se); 1.431 + se->OnAddedToSession(this); 1.432 +} 1.433 + 1.434 +void Session::RemoveSessionListener(SessionListener* se) 1.435 +{ 1.436 + Lock::Locker locker(&SessionListenersLock); 1.437 + 1.438 + const int count = SessionListeners.GetSizeI(); 1.439 + for (int i = 0; i < count; ++i) 1.440 + { 1.441 + if (SessionListeners[i] == se) 1.442 + { 1.443 + se->OnRemovedFromSession(this); 1.444 + 1.445 + SessionListeners.RemoveAtUnordered(i); 1.446 + break; 1.447 + } 1.448 + } 1.449 +} 1.450 +SInt32 Session::GetActiveSocketsCount() 1.451 +{ 1.452 + Lock::Locker locker1(&SocketListenersLock); 1.453 + Lock::Locker locker2(&ConnectionsLock); 1.454 + return SocketListeners.GetSize() + AllConnections.GetSize()>0; 1.455 +} 1.456 +Ptr<Connection> Session::AllocConnection(TransportType transport) 1.457 +{ 1.458 + switch (transport) 1.459 + { 1.460 + case TransportType_Loopback: return *new Connection(); 1.461 + case TransportType_TCP: return *new TCPConnection(); 1.462 + case TransportType_PacketizedTCP: return *new PacketizedTCPConnection(); 1.463 + default: 1.464 + OVR_ASSERT(false); 1.465 + break; 1.466 + } 1.467 + 1.468 + return NULL; 1.469 +} 1.470 + 1.471 +Ptr<PacketizedTCPConnection> Session::findConnectionBySocket(Array< Ptr<Connection> >& connectionArray, Socket* s, int *connectionIndex) 1.472 +{ 1.473 + const int count = connectionArray.GetSizeI(); 1.474 + for (int i = 0; i < count; ++i) 1.475 + { 1.476 + Connection* arrayItem = connectionArray[i].GetPtr(); 1.477 + 1.478 + if (arrayItem->Transport == TransportType_PacketizedTCP) 1.479 + { 1.480 + PacketizedTCPConnection* ptc = (PacketizedTCPConnection*)arrayItem; 1.481 + 1.482 + if (ptc->pSocket == s) 1.483 + { 1.484 + if (connectionIndex) 1.485 + { 1.486 + *connectionIndex = i; 1.487 + } 1.488 + return ptc; 1.489 + } 1.490 + } 1.491 + } 1.492 + 1.493 + return NULL; 1.494 +} 1.495 + 1.496 +int Session::invokeSessionListeners(ReceivePayload* rp) 1.497 +{ 1.498 + Lock::Locker locker(&SessionListenersLock); 1.499 + 1.500 + const int count = SessionListeners.GetSizeI(); 1.501 + for (int j = 0; j < count; ++j) 1.502 + { 1.503 + ListenerReceiveResult lrr = LRR_CONTINUE; 1.504 + SessionListeners[j]->OnReceive(rp, &lrr); 1.505 + 1.506 + if (lrr == LRR_RETURN || lrr == LRR_BREAK) 1.507 + { 1.508 + break; 1.509 + } 1.510 + } 1.511 + 1.512 + return rp->Bytes; 1.513 +} 1.514 + 1.515 +void Session::TCP_OnRecv(Socket* pSocket, uint8_t* pData, int bytesRead) 1.516 +{ 1.517 + // KevinJ: 9/2/2014 Fix deadlock - Watchdog calls Broadcast(), which locks ConnectionsLock(). 1.518 + // Lock::Locker locker(&ConnectionsLock); 1.519 + 1.520 + // Look for the connection in the full connection list first 1.521 + int connIndex; 1.522 + ConnectionsLock.DoLock(); 1.523 + Ptr<PacketizedTCPConnection> conn = findConnectionBySocket(AllConnections, pSocket, &connIndex); 1.524 + ConnectionsLock.Unlock(); 1.525 + if (conn) 1.526 + { 1.527 + if (conn->State == State_Connected) 1.528 + { 1.529 + ReceivePayload rp; 1.530 + rp.Bytes = bytesRead; 1.531 + rp.pConnection = conn; 1.532 + rp.pData = pData; 1.533 + 1.534 + // Call listeners 1.535 + invokeSessionListeners(&rp); 1.536 + } 1.537 + else if (conn->State == Client_ConnectedWait) 1.538 + { 1.539 + // Check the version data from the message 1.540 + BitStream bsIn((char*)pData, bytesRead, false); 1.541 + 1.542 + RPC_S2C_Authorization auth; 1.543 + if (!auth.Deserialize(&bsIn) || 1.544 + !auth.Validate()) 1.545 + { 1.546 + LogError("{ERR-001} [Session] REJECTED: OVRService did not authorize us: %s", auth.AuthString.ToCStr()); 1.547 + 1.548 + conn->SetState(State_Zombie); 1.549 + invokeSessionEvent(&SessionListener::OnIncompatibleProtocol, conn); 1.550 + } 1.551 + else 1.552 + { 1.553 + // Read remote version 1.554 + conn->RemoteMajorVersion = auth.MajorVersion; 1.555 + conn->RemoteMinorVersion = auth.MinorVersion; 1.556 + conn->RemotePatchVersion = auth.PatchVersion; 1.557 + 1.558 + // Mark as connected 1.559 + conn->SetState(State_Connected); 1.560 + ConnectionsLock.DoLock(); 1.561 + int connIndex2; 1.562 + if (findConnectionBySocket(AllConnections, pSocket, &connIndex2)==conn && findConnectionBySocket(FullConnections, pSocket, &connIndex2)==NULL) 1.563 + { 1.564 + FullConnections.PushBack(conn); 1.565 + } 1.566 + ConnectionsLock.Unlock(); 1.567 + invokeSessionEvent(&SessionListener::OnConnectionRequestAccepted, conn); 1.568 + } 1.569 + } 1.570 + else if (conn->State == Server_ConnectedWait) 1.571 + { 1.572 + // Check the version data from the message 1.573 + BitStream bsIn((char*)pData, bytesRead, false); 1.574 + 1.575 + RPC_C2S_Hello hello; 1.576 + if (!hello.Deserialize(&bsIn) || 1.577 + !hello.Validate()) 1.578 + { 1.579 + LogError("{ERR-002} [Session] REJECTED: Rift application is using an incompatible version %d.%d.%d (my version=%d.%d.%d)", 1.580 + hello.MajorVersion, hello.MinorVersion, hello.PatchVersion, 1.581 + RPCVersion_Major, RPCVersion_Minor, RPCVersion_Patch); 1.582 + 1.583 + conn->SetState(State_Zombie); 1.584 + 1.585 + // Send auth response 1.586 + BitStream bsOut; 1.587 + RPC_S2C_Authorization::Generate(&bsOut, "Incompatible protocol version. Please make sure your OVRService and SDK are both up to date."); 1.588 + conn->pSocket->Send(bsOut.GetData(), bsOut.GetNumberOfBytesUsed()); 1.589 + } 1.590 + else 1.591 + { 1.592 + // Read remote version 1.593 + conn->RemoteMajorVersion = hello.MajorVersion; 1.594 + conn->RemoteMinorVersion = hello.MinorVersion; 1.595 + conn->RemotePatchVersion = hello.PatchVersion; 1.596 + 1.597 + // Send auth response 1.598 + BitStream bsOut; 1.599 + RPC_S2C_Authorization::Generate(&bsOut); 1.600 + conn->pSocket->Send(bsOut.GetData(), bsOut.GetNumberOfBytesUsed()); 1.601 + 1.602 + // Mark as connected 1.603 + conn->SetState(State_Connected); 1.604 + ConnectionsLock.DoLock(); 1.605 + int connIndex2; 1.606 + if (findConnectionBySocket(AllConnections, pSocket, &connIndex2)==conn && findConnectionBySocket(FullConnections, pSocket, &connIndex2)==NULL) 1.607 + { 1.608 + FullConnections.PushBack(conn); 1.609 + } 1.610 + ConnectionsLock.Unlock(); 1.611 + invokeSessionEvent(&SessionListener::OnNewIncomingConnection, conn); 1.612 + 1.613 + } 1.614 + } 1.615 + else 1.616 + { 1.617 + OVR_ASSERT(false); 1.618 + } 1.619 + } 1.620 +} 1.621 + 1.622 +void Session::TCP_OnClosed(TCPSocket* s) 1.623 +{ 1.624 + Lock::Locker locker(&ConnectionsLock); 1.625 + 1.626 + // If found in the full connection list, 1.627 + int connIndex; 1.628 + Ptr<PacketizedTCPConnection> conn = findConnectionBySocket(AllConnections, s, &connIndex); 1.629 + if (conn) 1.630 + { 1.631 + AllConnections.RemoveAtUnordered(connIndex); 1.632 + 1.633 + // If in the full connection list, 1.634 + if (findConnectionBySocket(FullConnections, s, &connIndex)) 1.635 + { 1.636 + FullConnections.RemoveAtUnordered(connIndex); 1.637 + } 1.638 + 1.639 + // Generate an appropriate event for the current state 1.640 + switch (conn->State) 1.641 + { 1.642 + case Client_Connecting: 1.643 + invokeSessionEvent(&SessionListener::OnConnectionAttemptFailed, conn); 1.644 + break; 1.645 + case Client_ConnectedWait: 1.646 + case Server_ConnectedWait: 1.647 + invokeSessionEvent(&SessionListener::OnHandshakeAttemptFailed, conn); 1.648 + break; 1.649 + case State_Connected: 1.650 + case State_Zombie: 1.651 + invokeSessionEvent(&SessionListener::OnDisconnected, conn); 1.652 + break; 1.653 + default: 1.654 + OVR_ASSERT(false); 1.655 + break; 1.656 + } 1.657 + 1.658 + conn->SetState(State_Zombie); 1.659 + } 1.660 +} 1.661 + 1.662 +void Session::TCP_OnAccept(TCPSocket* pListener, SockAddr* pSockAddr, SocketHandle newSock) 1.663 +{ 1.664 + OVR_UNUSED(pListener); 1.665 + OVR_ASSERT(pListener->Transport == TransportType_PacketizedTCP); 1.666 + 1.667 + 1.668 + Ptr<PacketizedTCPSocket> newSocket = *new PacketizedTCPSocket(newSock, false); 1.669 + // If pSockAddr is not localhost, then close newSock 1.670 + if (pSockAddr->IsLocalhost()==false) 1.671 + { 1.672 + newSocket->Close(); 1.673 + return; 1.674 + } 1.675 + 1.676 + if (newSocket) 1.677 + { 1.678 + Ptr<Connection> b = AllocConnection(TransportType_PacketizedTCP); 1.679 + Ptr<PacketizedTCPConnection> c = (PacketizedTCPConnection*)b.GetPtr(); 1.680 + c->pSocket = newSocket; 1.681 + c->Address = *pSockAddr; 1.682 + c->State = Server_ConnectedWait; 1.683 + 1.684 + { 1.685 + Lock::Locker locker(&ConnectionsLock); 1.686 + AllConnections.PushBack(c); 1.687 + } 1.688 + 1.689 + // Server does not send the first packet. It waits for the client to send its version 1.690 + } 1.691 +} 1.692 + 1.693 +void Session::TCP_OnConnected(TCPSocket *s) 1.694 +{ 1.695 + Lock::Locker locker(&ConnectionsLock); 1.696 + 1.697 + // If connection was found, 1.698 + PacketizedTCPConnection* conn = findConnectionBySocket(AllConnections, s); 1.699 + if (conn) 1.700 + { 1.701 + OVR_ASSERT(conn->State == Client_Connecting); 1.702 + 1.703 + // Send hello message 1.704 + BitStream bsOut; 1.705 + RPC_C2S_Hello::Generate(&bsOut); 1.706 + conn->pSocket->Send(bsOut.GetData(), bsOut.GetNumberOfBytesUsed()); 1.707 + 1.708 + // Just update state but do not generate any notifications yet 1.709 + conn->State = Client_ConnectedWait; 1.710 + } 1.711 +} 1.712 + 1.713 +void Session::invokeSessionEvent(void(SessionListener::*f)(Connection*), Connection* conn) 1.714 +{ 1.715 + Lock::Locker locker(&SessionListenersLock); 1.716 + 1.717 + const int count = SessionListeners.GetSizeI(); 1.718 + for (int i = 0; i < count; ++i) 1.719 + { 1.720 + (SessionListeners[i]->*f)(conn); 1.721 + } 1.722 +} 1.723 + 1.724 +Ptr<Connection> Session::GetConnectionAtIndex(int index) 1.725 +{ 1.726 + Lock::Locker locker(&ConnectionsLock); 1.727 + 1.728 + const int count = FullConnections.GetSizeI(); 1.729 + 1.730 + if (index < count) 1.731 + { 1.732 + return FullConnections[index]; 1.733 + } 1.734 + 1.735 + return NULL; 1.736 +} 1.737 + 1.738 + 1.739 +}} // OVR::Net