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