ovr_sdk

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