CUGL 3.0
Cornell University Game Library
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
Classes | Public Types | Public Member Functions | Static Public Member Functions | List of all members
cugl::netcode::WebSocket Class Reference

#include <CUWebSocket.h>

Inheritance diagram for cugl::netcode::WebSocket:

Public Types

enum class  State : int {
  INACTIVE = -1 , CONNECTING = 0 , OPEN = 2 , CLOSING = 3 ,
  CLOSED = 4 , FAILED = 5
}
 
typedef std::function< void(State state)> StateCallback
 
typedef std::function< void(const std::vector< std::byte > &message, Uint64 time)> Dispatcher
 

Public Member Functions

 WebSocket ()
 
 ~WebSocket ()
 
const InetAddressgetAddress () const
 
const std::string getPath () const
 
bool isOpen ()
 
State getState ()
 
size_t getCapacity ()
 
void setCapacity (size_t capacity)
 
void open (bool secure=false)
 
void close ()
 
bool send (const std::vector< std::byte > &data)
 
bool send (std::vector< std::byte > &&data)
 
void receive (const Dispatcher &dispatcher)
 
void onReceipt (Dispatcher callback)
 
void onStateChange (StateCallback callback)
 
void setDebug (bool flag)
 
bool getDebug () const
 

Static Public Member Functions

static std::shared_ptr< WebSocketalloc (const InetAddress &address)
 
static std::shared_ptr< WebSocketallocWithPath (const InetAddress &address, const std::string path)
 

Detailed Description

This class represents a connection to a central server.

The class NetcodeConnection is built upon WebRTC for high speed communication. A side effect of this is that CUGL has access to websockets, an ubiquitous framework for creating servers. While not as performant as WebRTC, websockets are relatively simple to use, which makes sense to expose them to the rest of the engine.

Websockets can still be a little difficult for beginners, as bi-directional communication requires either a multi-threaded or an asynchronous (e.g. coroutines) environment. While these are possible in CUGL, it makes much more sense to synchronize messages receival and dispatch with the game loop, in much the same way that we did for NetcodeConnection. Hence this class shares a lot of the same features as that class.

With that said, this class is much more limited than NetcodeConnection. The websocket can only talk to one machine at a time. There is some basic connection handling, but no concept of migration or game session management. There is also no UUID for the connected server. The server is identified solely by its URL.

The biggest downside of this class is that the websocket server must have a publicly available address to connect to. This is unlikely to be the case between mobile devices (our primary application). That is why a lobby server (like the one used by NetcodeConnection is so important.

In addition, as a layer on top of TCP, the performance of this connection will not be as high as that of NetcodeConnection which uses UDP style communication.

It is completely unsafe for network connections to be used on the stack. For that reason, this class hides the initialization methods (and the constructors create uninitialized connections). You are forced to go through the static allocator alloc to create instances of this class.

Member Typedef Documentation

◆ Dispatcher

The dispatcher is called by the receive function to consume data from the message buffer. Unlike NetcodeConnection, this dispatcher only does it relays the message data since there can only be one source. However, we do include a timestamp of the number of microseconds that have passed since the function NetworkLayer#start was called.

The function type is equivalent to

 const std::function<void(const std::vector<std::byte>& message)>
Parameters
messageThe message data
timeThe number of microseconds since NetworkLayer#start

◆ StateCallback

This type represents a callback for the WebSocket class.

This callback is invoked when the connection state has changed. The parameter marks the new connection state. This is particularly helpful for monitoring host migrations.

Callback functions differ from listeners (found in the input classes) in that only one callback of any type is allowed in a WebSocket class. Callback functions are guaranteed to be called at the start of an animation frame, before the method Application#update(float).

The function type is equivalent to

 std::function<void(State state)>
Parameters
stateThe new connection state

Member Enumeration Documentation

◆ State

enum class cugl::netcode::WebSocket::State : int
strong

An enum representing the current connection state.

This state is the relationship of this connection to the websocket server. The peer connections and data channels have their own separate states.

Enumerator
INACTIVE 

The connection is initialized, but open has not yet been called.

CONNECTING 

The connection is in the initial connection phase.

This represent the initial handshake with the websocket server. This state ends when the connection is officially marked as open.

OPEN 

The connection is complete and the web socket is ready for use.

This state ends when either the connection is broken or the socket is closed at either end (e.g at this end or by the server).

CLOSING 

The connection is in the process of closing.

This states marks the transition period between when a socket started the process of closing, and when it actually marked as closed.

CLOSED 

The connection is disconnected.

This state occurs when the socket has finished closing and is no longer usable. It is possible to reopen a websocket after it has closed.

FAILED 

The connection has failed with an unknown error.

Constructor & Destructor Documentation

◆ WebSocket()

cugl::netcode::WebSocket::WebSocket ( )

Creates a degenerate websocket connection.

This object has not been initialized with an address and cannot be used.

You should NEVER USE THIS CONSTRUCTOR. All connections should be created by the static constructor alloc instead.

◆ ~WebSocket()

cugl::netcode::WebSocket::~WebSocket ( )

Deletes this websocket connection, disposing all resources

Member Function Documentation

◆ alloc()

static std::shared_ptr< WebSocket > cugl::netcode::WebSocket::alloc ( const InetAddress address)
inlinestatic

Returns a newly allocated websocket connection to a server.

This method initializes this websocket connection with all of the correct settings. However, it does not connect to the server. You must call the method open to initiate connection. This design decision is intended to give the user a chance to set the callback functions before connection is established.

Websocket servers typically reference their connections by a "path" provided by the user. The path is not an necessary an identifier, as multiple connections can use the same path. It is simply a way of logically grouping connections This path can be any string, though the socket applies a prefix of "/" if it is not already there. This This version uses an empty path.

This method will always return false if the NetworkLayer failed to initialize.

Parameters
addressThe server internet address
Returns
a newly allocated websocket connection to a server.

◆ allocWithPath()

static std::shared_ptr< WebSocket > cugl::netcode::WebSocket::allocWithPath ( const InetAddress address,
const std::string  path 
)
inlinestatic

Returns a newly allocated websocket connection to a server.

This method initializes this websocket connection with all of the correct settings. However, it does not connect to the server. You must call the method open to initiate connection. This design decision is intended to give the user a chance to set the callback functions before connection is established.

Websocket servers typically reference their connections by a "path" provided by the user. The path is not an necessary an identifier, as multiple connections can use the same path. It is simply a way of logically grouping connections This path can be any string, though this method will apply a prefix of "/" if it is not already there.

This method will always return false if the NetworkLayer failed to initialize.

Parameters
addressThe server internet address
pathThe connection path
Returns
a newly allocated websocket connection to a server.

◆ close()

void cugl::netcode::WebSocket::close ( )

Closes this connection normally.

Because this requires coordination with this connection, this method does not close the connection immediately. Verify that the state is State#CLOSED before destroying this object.

◆ getAddress()

const InetAddress & cugl::netcode::WebSocket::getAddress ( ) const
inline

Returns the internet address of this connection

Returns
the internet address of this connection

◆ getCapacity()

size_t cugl::netcode::WebSocket::getCapacity ( )

Returns the message buffer capacity.

It is possible for this connection to receive several messages over the network before it has a chance to all receive. This buffer stores those messages to be read later. The capacity indicates the number of messages that can be stored.

This method is not const because it requires a lock.

Returns
the message buffer capacity.

◆ getDebug()

bool cugl::netcode::WebSocket::getDebug ( ) const
inline

Returns the debugging status of this connection.

If debugging is active, connections will be quite verbose

Returns
the debugging status of this connection.

◆ getPath()

const std::string cugl::netcode::WebSocket::getPath ( ) const
inline

Returns the path for this connection.

Websocket servers typically reference their connections by a "path" provided by the user. The path is not an necessary an identifier, as multiple connections can use the same path. It is simply a way of logically grouping connections. This path can be any string, though it must start with a "/".

Returns
the path for this connection.

◆ getState()

State cugl::netcode::WebSocket::getState ( )

Returns the current state of this connection.

Monitoring state is one of the most important components of working with a web socket. It is possible for a connection to close remotely, without any input from this side.

This method is not constant because it performs an internal query.

State can either be monitored via polling with this method, or with a callback set to onStateChange.

◆ isOpen()

bool cugl::netcode::WebSocket::isOpen ( )

Returns true if this connection is open

Technically a connection is not open if the state is CONNECTING.

This method is not constant because it performs an internal query.

Returns
true if this connection is open

◆ onReceipt()

void cugl::netcode::WebSocket::onReceipt ( Dispatcher  callback)

Sets a callback function to invoke on message receipt

This callback is alternative to the method receive. Instead of buffering messages and calling that method each frame, this callback function will be invoked as soon as the message is received.

All callback functions are guaranteed to be called on the main thread. They are called at the start of an animation frame, before the method Application#update(float).

Parameters
callbackThe dispatcher callback

◆ onStateChange()

void cugl::netcode::WebSocket::onStateChange ( StateCallback  callback)

Sets a callback function to invoke on state changes

Monitoring state is one of the most important components of working with a web socket. It is possible for a connection to close remotely, without any input from this side.

State can either be monitored via a callback with this method, or with a polling the method getState.

Parameters
callbackThe state change callback

◆ open()

void cugl::netcode::WebSocket::open ( bool  secure = false)

Opens the connection to the websocket sever

This process is not instantaneous. Upon calling this method, you should wait for getState or the callback onStateChange to return State#OPEN. Once that happens, it is possible to start communicating with the serve.

This method allows us to control the type of connection (ws:// or wss://). Note that a server must have a SSL certificate to support a secure connection.

This method will be ignored if the socket is already open. However, it is possible to use this method reopen a closed connection.

Parameters
secureWhether to connect to a server via SSL

◆ receive()

void cugl::netcode::WebSocket::receive ( const Dispatcher dispatcher)

Receives incoming network messages.

When executed, the function dispatch willl be called on every received byte array since the last call to receive. It is up to you to interpret this data on your own or with NetcodeDeserializer

A network frame can, but need not be, the same as a render frame. Your dispatch function should be prepared to be called multiple times a render frame, or even not at all.

If a dispatcher callback has been registered with onReceipt, this method will never do anything. In that case, messages are not buffered and are processed as soon as they are received.

Parameters
dispatcherThe function to process received data

◆ send() [1/2]

bool cugl::netcode::WebSocket::send ( const std::vector< std::byte > &  data)

Sends a byte array to the server.

Communication is guaranteed to be ordered. So if this socket sends two messages to the server, the server will receive those messages in the same order.

You may choose to either send a byte array directly, or you can use the NetcodeSerializer and NetcodeDeserializer classes to encode more complex data.

This method requires that the socket be open. Otherwise it will return false.

Parameters
dataThe byte array to send.
Returns
true if the message was (apparently) sent

◆ send() [2/2]

bool cugl::netcode::WebSocket::send ( std::vector< std::byte > &&  data)

Sends a byte array to the server.

Communication is guaranteed to be ordered. So if this socket sends two messages to the server, the server will receive those messages in the same order.

You may choose to either send a byte array directly, or you can use the NetcodeSerializer and NetcodeDeserializer classes to encode more complex data.

This method requires that the socket be open. Otherwise it will return false.

Parameters
dataThe byte array to send.
Returns
true if the message was (apparently) sent

◆ setCapacity()

void cugl::netcode::WebSocket::setCapacity ( size_t  capacity)

Sets the message buffer capacity.

It is possible for this connection to recieve several messages over the network before it has a chance to all receive. This buffer stores those messages to be read later. The capacity indicates the number of messages that can be stored.

Parameters
capacityThe new message buffer capacity.

◆ setDebug()

void cugl::netcode::WebSocket::setDebug ( bool  flag)

Toggles the debugging status of this connection.

If debugging is active, connections will be quite verbose

Parameters
flagWhether to activate debugging

The documentation for this class was generated from the following file: