ovr_sdk

annotate LibOVR/Src/Net/OVR_Session.h @ 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 PublicHeader: n/a
nuclear@0 4 Filename : OVR_Session.h
nuclear@0 5 Content : One network session that provides connection/disconnection events.
nuclear@0 6 Created : June 10, 2014
nuclear@0 7 Authors : Kevin Jenkins, Chris Taylor
nuclear@0 8
nuclear@0 9 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
nuclear@0 10
nuclear@0 11 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
nuclear@0 12 you may not use the Oculus VR Rift SDK except in compliance with the License,
nuclear@0 13 which is provided at the time of installation or download, or which
nuclear@0 14 otherwise accompanies this software in either electronic or hard copy form.
nuclear@0 15
nuclear@0 16 You may obtain a copy of the License at
nuclear@0 17
nuclear@0 18 http://www.oculusvr.com/licenses/LICENSE-3.2
nuclear@0 19
nuclear@0 20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
nuclear@0 21 distributed under the License is distributed on an "AS IS" BASIS,
nuclear@0 22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nuclear@0 23 See the License for the specific language governing permissions and
nuclear@0 24 limitations under the License.
nuclear@0 25
nuclear@0 26 ************************************************************************************/
nuclear@0 27
nuclear@0 28 #ifndef OVR_Session_h
nuclear@0 29 #define OVR_Session_h
nuclear@0 30
nuclear@0 31 #include "OVR_Socket.h"
nuclear@0 32 #include "OVR_PacketizedTCPSocket.h"
nuclear@0 33 #include "../Kernel/OVR_Array.h"
nuclear@0 34 #include "../Kernel/OVR_Threads.h"
nuclear@0 35 #include "../Kernel/OVR_Atomic.h"
nuclear@0 36 #include "../Kernel/OVR_RefCount.h"
nuclear@0 37
nuclear@0 38 namespace OVR { namespace Net {
nuclear@0 39
nuclear@0 40 class Session;
nuclear@0 41
nuclear@0 42
nuclear@0 43 //-----------------------------------------------------------------------------
nuclear@0 44 // Based on Semantic Versioning ( http://semver.org/ )
nuclear@0 45 //
nuclear@0 46 // Please update changelog below:
nuclear@0 47 // 1.0.0 - [SDK 0.4.0] Initial version (July 21, 2014)
nuclear@0 48 // 1.1.0 - Add Get/SetDriverMode_1, HMDCountUpdate_1
nuclear@0 49 // Version mismatch results (July 28, 2014)
nuclear@0 50 //-----------------------------------------------------------------------------
nuclear@0 51
nuclear@0 52 static const uint16_t RPCVersion_Major = 1; // MAJOR version when you make incompatible API changes,
nuclear@0 53 static const uint16_t RPCVersion_Minor = 2; // MINOR version when you add functionality in a backwards-compatible manner, and
nuclear@0 54 static const uint16_t RPCVersion_Patch = 0; // PATCH version when you make backwards-compatible bug fixes.
nuclear@0 55
nuclear@0 56 // Client starts communication by sending its version number.
nuclear@0 57 struct RPC_C2S_Hello
nuclear@0 58 {
nuclear@0 59 RPC_C2S_Hello() :
nuclear@0 60 MajorVersion(0),
nuclear@0 61 MinorVersion(0),
nuclear@0 62 PatchVersion(0)
nuclear@0 63 {
nuclear@0 64 }
nuclear@0 65
nuclear@0 66 String HelloString;
nuclear@0 67
nuclear@0 68 // Client version info
nuclear@0 69 uint16_t MajorVersion, MinorVersion, PatchVersion;
nuclear@0 70
nuclear@0 71 void Serialize(Net::BitStream* bs)
nuclear@0 72 {
nuclear@0 73 bs->Write(HelloString);
nuclear@0 74 bs->Write(MajorVersion);
nuclear@0 75 bs->Write(MinorVersion);
nuclear@0 76 bs->Write(PatchVersion);
nuclear@0 77 }
nuclear@0 78
nuclear@0 79 bool Deserialize(Net::BitStream* bs)
nuclear@0 80 {
nuclear@0 81 bs->Read(HelloString);
nuclear@0 82 bs->Read(MajorVersion);
nuclear@0 83 bs->Read(MinorVersion);
nuclear@0 84 return bs->Read(PatchVersion);
nuclear@0 85 }
nuclear@0 86
nuclear@0 87 static void Generate(Net::BitStream* bs);
nuclear@0 88
nuclear@0 89 bool Validate();
nuclear@0 90 };
nuclear@0 91
nuclear@0 92 // Server responds with an authorization accepted message, including the server's version number
nuclear@0 93 struct RPC_S2C_Authorization
nuclear@0 94 {
nuclear@0 95 RPC_S2C_Authorization() :
nuclear@0 96 MajorVersion(0),
nuclear@0 97 MinorVersion(0),
nuclear@0 98 PatchVersion(0)
nuclear@0 99 {
nuclear@0 100 }
nuclear@0 101
nuclear@0 102 String AuthString;
nuclear@0 103
nuclear@0 104 // Server version info
nuclear@0 105 uint16_t MajorVersion, MinorVersion, PatchVersion;
nuclear@0 106
nuclear@0 107 void Serialize(Net::BitStream* bs)
nuclear@0 108 {
nuclear@0 109 bs->Write(AuthString);
nuclear@0 110 bs->Write(MajorVersion);
nuclear@0 111 bs->Write(MinorVersion);
nuclear@0 112 bs->Write(PatchVersion);
nuclear@0 113 }
nuclear@0 114
nuclear@0 115 bool Deserialize(Net::BitStream* bs)
nuclear@0 116 {
nuclear@0 117 bs->Read(AuthString);
nuclear@0 118 bs->Read(MajorVersion);
nuclear@0 119 bs->Read(MinorVersion);
nuclear@0 120 return bs->Read(PatchVersion);
nuclear@0 121 }
nuclear@0 122
nuclear@0 123 static void Generate(Net::BitStream* bs, String errorString = "");
nuclear@0 124
nuclear@0 125 bool Validate();
nuclear@0 126 };
nuclear@0 127
nuclear@0 128
nuclear@0 129 //-----------------------------------------------------------------------------
nuclear@0 130 // Result of a session function
nuclear@0 131 enum SessionResult
nuclear@0 132 {
nuclear@0 133 SessionResult_OK,
nuclear@0 134 SessionResult_BindFailure,
nuclear@0 135 SessionResult_ListenFailure,
nuclear@0 136 SessionResult_ConnectFailure,
nuclear@0 137 SessionResult_ConnectInProgress,
nuclear@0 138 SessionResult_AlreadyConnected,
nuclear@0 139 };
nuclear@0 140
nuclear@0 141
nuclear@0 142 //-----------------------------------------------------------------------------
nuclear@0 143 // Connection state
nuclear@0 144 enum EConnectionState
nuclear@0 145 {
nuclear@0 146 State_Zombie, // Disconnected
nuclear@0 147
nuclear@0 148 // Client-only:
nuclear@0 149 Client_Connecting, // Waiting for TCP connection
nuclear@0 150 Client_ConnectedWait, // Connected! Waiting for server to authorize
nuclear@0 151
nuclear@0 152 // Server-only:
nuclear@0 153 Server_ConnectedWait, // Connected! Waiting for client handshake
nuclear@0 154
nuclear@0 155 State_Connected // Connected
nuclear@0 156 };
nuclear@0 157
nuclear@0 158
nuclear@0 159 //-----------------------------------------------------------------------------
nuclear@0 160 // Generic connection over any transport
nuclear@0 161 class Connection : public RefCountBase<Connection>
nuclear@0 162 {
nuclear@0 163 public:
nuclear@0 164 Connection() :
nuclear@0 165 Transport(TransportType_None),
nuclear@0 166 State(State_Zombie),
nuclear@0 167 RemoteMajorVersion(0),
nuclear@0 168 RemoteMinorVersion(0),
nuclear@0 169 RemotePatchVersion(0)
nuclear@0 170 {
nuclear@0 171 }
nuclear@0 172 virtual ~Connection() // Allow delete from base
nuclear@0 173 {
nuclear@0 174 }
nuclear@0 175
nuclear@0 176 public:
nuclear@0 177 virtual void SetState(EConnectionState s) {State = s;}
nuclear@0 178
nuclear@0 179 TransportType Transport;
nuclear@0 180 EConnectionState State;
nuclear@0 181
nuclear@0 182 // Version number read from remote host just before connection completes
nuclear@0 183 int RemoteMajorVersion;
nuclear@0 184 int RemoteMinorVersion;
nuclear@0 185 int RemotePatchVersion;
nuclear@0 186 };
nuclear@0 187
nuclear@0 188
nuclear@0 189 //-----------------------------------------------------------------------------
nuclear@0 190 // Generic network connection over any network transport
nuclear@0 191 class NetworkConnection : public Connection
nuclear@0 192 {
nuclear@0 193 protected:
nuclear@0 194 NetworkConnection()
nuclear@0 195 {
nuclear@0 196 }
nuclear@0 197 virtual ~NetworkConnection()
nuclear@0 198 {
nuclear@0 199 }
nuclear@0 200
nuclear@0 201 public:
nuclear@0 202 virtual void SetState(EConnectionState s)
nuclear@0 203 {
nuclear@0 204 if (s != State)
nuclear@0 205 {
nuclear@0 206 Mutex::Locker locker(&StateMutex);
nuclear@0 207
nuclear@0 208 if (s != State)
nuclear@0 209 {
nuclear@0 210 State = s;
nuclear@0 211
nuclear@0 212 if (State != Client_Connecting)
nuclear@0 213 {
nuclear@0 214 ConnectingWait.NotifyAll();
nuclear@0 215 }
nuclear@0 216 }
nuclear@0 217 }
nuclear@0 218 }
nuclear@0 219
nuclear@0 220 void WaitOnConnecting()
nuclear@0 221 {
nuclear@0 222 Mutex::Locker locker(&StateMutex);
nuclear@0 223
nuclear@0 224 while (State == Client_Connecting)
nuclear@0 225 {
nuclear@0 226 ConnectingWait.Wait(&StateMutex);
nuclear@0 227 }
nuclear@0 228 }
nuclear@0 229
nuclear@0 230 SockAddr Address;
nuclear@0 231 Mutex StateMutex;
nuclear@0 232 WaitCondition ConnectingWait;
nuclear@0 233 };
nuclear@0 234
nuclear@0 235
nuclear@0 236 //-----------------------------------------------------------------------------
nuclear@0 237 // TCP Connection
nuclear@0 238 class TCPConnection : public NetworkConnection
nuclear@0 239 {
nuclear@0 240 public:
nuclear@0 241 TCPConnection()
nuclear@0 242 {
nuclear@0 243 }
nuclear@0 244 virtual ~TCPConnection()
nuclear@0 245 {
nuclear@0 246 }
nuclear@0 247
nuclear@0 248 public:
nuclear@0 249 Ptr<TCPSocket> pSocket;
nuclear@0 250 };
nuclear@0 251
nuclear@0 252
nuclear@0 253 //-----------------------------------------------------------------------------
nuclear@0 254 // Packetized TCP Connection
nuclear@0 255 class PacketizedTCPConnection : public TCPConnection
nuclear@0 256 {
nuclear@0 257 public:
nuclear@0 258 PacketizedTCPConnection()
nuclear@0 259 {
nuclear@0 260 Transport = TransportType_PacketizedTCP;
nuclear@0 261 }
nuclear@0 262 virtual ~PacketizedTCPConnection()
nuclear@0 263 {
nuclear@0 264 }
nuclear@0 265 };
nuclear@0 266
nuclear@0 267
nuclear@0 268 //-----------------------------------------------------------------------------
nuclear@0 269 // Generic socket listener description
nuclear@0 270 class ListenerDescription
nuclear@0 271 {
nuclear@0 272 public:
nuclear@0 273 ListenerDescription() :
nuclear@0 274 Transport(TransportType_None)
nuclear@0 275 {
nuclear@0 276 }
nuclear@0 277
nuclear@0 278 TransportType Transport;
nuclear@0 279 };
nuclear@0 280
nuclear@0 281
nuclear@0 282 //-----------------------------------------------------------------------------
nuclear@0 283 // Description for a Berkley socket listener
nuclear@0 284 class BerkleyListenerDescription : public ListenerDescription
nuclear@0 285 {
nuclear@0 286 public:
nuclear@0 287 static const int DefaultMaxIncomingConnections = 64;
nuclear@0 288 static const int DefaultMaxConnections = 128;
nuclear@0 289
nuclear@0 290 BerkleyListenerDescription() :
nuclear@0 291 MaxIncomingConnections(DefaultMaxIncomingConnections),
nuclear@0 292 MaxConnections(DefaultMaxConnections)
nuclear@0 293 {
nuclear@0 294 }
nuclear@0 295
nuclear@0 296 Ptr<BerkleySocket> BoundSocketToListenWith;
nuclear@0 297 int MaxIncomingConnections;
nuclear@0 298 int MaxConnections;
nuclear@0 299 };
nuclear@0 300
nuclear@0 301
nuclear@0 302 //-----------------------------------------------------------------------------
nuclear@0 303 // Receive payload
nuclear@0 304 struct ReceivePayload
nuclear@0 305 {
nuclear@0 306 Connection* pConnection; // Source connection
nuclear@0 307 uint8_t* pData; // Pointer to data received
nuclear@0 308 int Bytes; // Number of bytes of data received
nuclear@0 309 };
nuclear@0 310
nuclear@0 311 //-----------------------------------------------------------------------------
nuclear@0 312 // Broadcast parameters
nuclear@0 313 class BroadcastParameters
nuclear@0 314 {
nuclear@0 315 public:
nuclear@0 316 BroadcastParameters() :
nuclear@0 317 pData(NULL),
nuclear@0 318 Bytes(0)
nuclear@0 319 {
nuclear@0 320 }
nuclear@0 321
nuclear@0 322 BroadcastParameters(const void* _pData, int _bytes) :
nuclear@0 323 pData(_pData),
nuclear@0 324 Bytes(_bytes)
nuclear@0 325 {
nuclear@0 326 }
nuclear@0 327
nuclear@0 328 public:
nuclear@0 329 const void* pData; // Pointer to data to send
nuclear@0 330 int Bytes; // Number of bytes of data received
nuclear@0 331 };
nuclear@0 332
nuclear@0 333 //-----------------------------------------------------------------------------
nuclear@0 334 // Send parameters
nuclear@0 335 class SendParameters
nuclear@0 336 {
nuclear@0 337 public:
nuclear@0 338 SendParameters() :
nuclear@0 339 pData(NULL),
nuclear@0 340 Bytes(0)
nuclear@0 341 {
nuclear@0 342 }
nuclear@0 343 SendParameters(Ptr<Connection> _pConnection, const void* _pData, int _bytes) :
nuclear@0 344 pConnection(_pConnection),
nuclear@0 345 pData(_pData),
nuclear@0 346 Bytes(_bytes)
nuclear@0 347 {
nuclear@0 348 }
nuclear@0 349
nuclear@0 350 public:
nuclear@0 351 Ptr<Connection> pConnection; // Connection to use
nuclear@0 352 const void* pData; // Pointer to data to send
nuclear@0 353 int Bytes; // Number of bytes of data received
nuclear@0 354 };
nuclear@0 355
nuclear@0 356
nuclear@0 357 //-----------------------------------------------------------------------------
nuclear@0 358 // Parameters to connect
nuclear@0 359 struct ConnectParameters
nuclear@0 360 {
nuclear@0 361 public:
nuclear@0 362 ConnectParameters() :
nuclear@0 363 Transport(TransportType_None)
nuclear@0 364 {
nuclear@0 365 }
nuclear@0 366
nuclear@0 367 TransportType Transport;
nuclear@0 368 };
nuclear@0 369
nuclear@0 370 struct ConnectParametersBerkleySocket : public ConnectParameters
nuclear@0 371 {
nuclear@0 372 SockAddr RemoteAddress;
nuclear@0 373 Ptr<BerkleySocket> BoundSocketToConnectWith;
nuclear@0 374 bool Blocking;
nuclear@0 375
nuclear@0 376 ConnectParametersBerkleySocket(BerkleySocket* s, SockAddr* addr, bool blocking,
nuclear@0 377 TransportType transport) :
nuclear@0 378 RemoteAddress(*addr),
nuclear@0 379 BoundSocketToConnectWith(s),
nuclear@0 380 Blocking(blocking)
nuclear@0 381 {
nuclear@0 382 Transport = transport;
nuclear@0 383 }
nuclear@0 384 };
nuclear@0 385
nuclear@0 386
nuclear@0 387 //-----------------------------------------------------------------------------
nuclear@0 388 // Listener receive result
nuclear@0 389 enum ListenerReceiveResult
nuclear@0 390 {
nuclear@0 391 /// The SessionListener used this message and it shouldn't be given to the user.
nuclear@0 392 LRR_RETURN = 0,
nuclear@0 393
nuclear@0 394 /// The SessionListener is going to hold on to this message. Do not deallocate it but do not pass it to other plugins either.
nuclear@0 395 LRR_BREAK,
nuclear@0 396
nuclear@0 397 /// This message will be processed by other SessionListeners, and at last by the user.
nuclear@0 398 LRR_CONTINUE,
nuclear@0 399 };
nuclear@0 400
nuclear@0 401
nuclear@0 402 //-----------------------------------------------------------------------------
nuclear@0 403 // SessionListener
nuclear@0 404
nuclear@0 405 // Callback interface for network events such as connecting, disconnecting, getting data, independent of the transport medium
nuclear@0 406 class SessionListener
nuclear@0 407 {
nuclear@0 408 public:
nuclear@0 409 virtual ~SessionListener(){}
nuclear@0 410
nuclear@0 411 // Data events
nuclear@0 412 virtual void OnReceive(ReceivePayload* pPayload, ListenerReceiveResult* lrrOut) { OVR_UNUSED2(pPayload, lrrOut); }
nuclear@0 413
nuclear@0 414 // Connection was closed
nuclear@0 415 virtual void OnDisconnected(Connection* conn) = 0;
nuclear@0 416
nuclear@0 417 // Connection was created (some data was exchanged to verify protocol compatibility too)
nuclear@0 418 virtual void OnConnected(Connection* conn) = 0;
nuclear@0 419
nuclear@0 420 // Server accepted client
nuclear@0 421 virtual void OnNewIncomingConnection(Connection* conn) { OnConnected(conn); }
nuclear@0 422 // Client was accepted
nuclear@0 423 virtual void OnConnectionRequestAccepted(Connection* conn) { OnConnected(conn); }
nuclear@0 424
nuclear@0 425 // Connection attempt failed for some reason
nuclear@0 426 virtual void OnConnectionAttemptFailed(Connection* conn) { OnDisconnected(conn); }
nuclear@0 427
nuclear@0 428 // Incompatible protocol
nuclear@0 429 virtual void OnIncompatibleProtocol(Connection* conn) { OnConnectionAttemptFailed(conn); }
nuclear@0 430 // Disconnected during initial handshake
nuclear@0 431 virtual void OnHandshakeAttemptFailed(Connection* conn) { OnConnectionAttemptFailed(conn); }
nuclear@0 432
nuclear@0 433 // Other
nuclear@0 434 virtual void OnAddedToSession(Session* session) { OVR_UNUSED(session); }
nuclear@0 435 virtual void OnRemovedFromSession(Session* session) { OVR_UNUSED(session); }
nuclear@0 436 };
nuclear@0 437
nuclear@0 438
nuclear@0 439 //-----------------------------------------------------------------------------
nuclear@0 440 // Session
nuclear@0 441
nuclear@0 442 // Interface for network events such as listening on a socket, sending data, connecting, and disconnecting. Works independently of the transport medium and also implements loopback
nuclear@0 443 class Session : public SocketEvent_TCP, public NewOverrideBase
nuclear@0 444 {
nuclear@0 445 // Implement a policy to avoid releasing memory backing allBlockingTcpSockets
nuclear@0 446 struct ArrayNoShrinkPolicy : ArrayDefaultPolicy
nuclear@0 447 {
nuclear@0 448 bool NeverShrinking() const { return 1; }
nuclear@0 449 };
nuclear@0 450
nuclear@0 451 public:
nuclear@0 452 Session() :
nuclear@0 453 HasLoopbackListener(false)
nuclear@0 454 {
nuclear@0 455 }
nuclear@0 456 virtual ~Session()
nuclear@0 457 {
nuclear@0 458 // Ensure memory backing the sockets array is released
nuclear@0 459 allBlockingTcpSockets.ClearAndRelease();
nuclear@0 460 }
nuclear@0 461
nuclear@0 462 virtual SessionResult Listen(ListenerDescription* pListenerDescription);
nuclear@0 463 virtual SessionResult Connect(ConnectParameters* cp);
nuclear@0 464 virtual int Send(SendParameters* payload);
nuclear@0 465 virtual void Broadcast(BroadcastParameters* payload);
nuclear@0 466 // DO NOT CALL Poll() FROM MULTIPLE THREADS due to allBlockingTcpSockets being a member
nuclear@0 467 virtual void Poll(bool listeners = true);
nuclear@0 468 virtual void AddSessionListener(SessionListener* se);
nuclear@0 469 virtual void RemoveSessionListener(SessionListener* se);
nuclear@0 470 virtual SInt32 GetActiveSocketsCount();
nuclear@0 471
nuclear@0 472 // Packetized TCP convenience functions
nuclear@0 473 virtual SessionResult ListenPTCP(BerkleyBindParameters* bbp);
nuclear@0 474 virtual SessionResult ConnectPTCP(BerkleyBindParameters* bbp, SockAddr* RemoteAddress, bool blocking);
nuclear@0 475
nuclear@0 476 // Closes all the sockets; useful for interrupting the socket polling during shutdown
nuclear@0 477 void Shutdown();
nuclear@0 478
nuclear@0 479 // Get count of successful connections (past handshake point)
nuclear@0 480 int GetConnectionCount() const
nuclear@0 481 {
nuclear@0 482 return FullConnections.GetSizeI();
nuclear@0 483 }
nuclear@0 484 Ptr<Connection> GetConnectionAtIndex(int index);
nuclear@0 485
nuclear@0 486 protected:
nuclear@0 487 virtual Ptr<Connection> AllocConnection(TransportType transportType);
nuclear@0 488
nuclear@0 489 Lock SocketListenersLock, ConnectionsLock, SessionListenersLock;
nuclear@0 490 bool HasLoopbackListener; // Has loopback listener installed?
nuclear@0 491 Array< Ptr<TCPSocket> > SocketListeners; // List of active sockets
nuclear@0 492 Array< Ptr<Connection> > AllConnections; // List of active connections stuck at the versioning handshake
nuclear@0 493 Array< Ptr<Connection> > FullConnections; // List of active connections past the versioning handshake
nuclear@0 494 Array< SessionListener* > SessionListeners; // List of session listeners
nuclear@0 495 Array< Ptr< Net::TCPSocket >, ArrayNoShrinkPolicy > allBlockingTcpSockets; // Preallocated blocking sockets array
nuclear@0 496
nuclear@0 497 // Tools
nuclear@0 498 Ptr<PacketizedTCPConnection> findConnectionBySocket(Array< Ptr<Connection> >& connectionArray, Socket* s, int *connectionIndex = NULL); // Call with ConnectionsLock held
nuclear@0 499 Ptr<PacketizedTCPConnection> findConnectionBySockAddr(SockAddr* address); // Call with ConnectionsLock held
nuclear@0 500 int invokeSessionListeners(ReceivePayload*);
nuclear@0 501 void invokeSessionEvent(void(SessionListener::*f)(Connection*), Connection* pConnection);
nuclear@0 502
nuclear@0 503 // TCP
nuclear@0 504 virtual void TCP_OnRecv(Socket* pSocket, uint8_t* pData, int bytesRead);
nuclear@0 505 virtual void TCP_OnClosed(TCPSocket* pSocket);
nuclear@0 506 virtual void TCP_OnAccept(TCPSocket* pListener, SockAddr* pSockAddr, SocketHandle newSock);
nuclear@0 507 virtual void TCP_OnConnected(TCPSocket* pSocket);
nuclear@0 508 };
nuclear@0 509
nuclear@0 510
nuclear@0 511 }} // OVR::Net
nuclear@0 512
nuclear@0 513 #endif