using System;
namespace Mirror
{
///
/// Abstract transport layer component
///
///
///
/// Transport Rules
///
///
///
/// All transports should follow these rules so that they work correctly with mirror
///
/// -
/// When Monobehaviour is disabled the Transport should not invoke callbacks
///
/// -
/// Callbacks should be invoked on main thread. It is best to do this from LateUpdate
///
/// -
/// Callbacks can be invoked after or as been called
///
/// -
/// or can be called by mirror multiple times
///
/// -
/// should check the platform and 32 vs 64 bit if the transport only works on some of them
///
/// -
/// should return size even if transport is not running
///
/// -
/// Default channel should be reliable
///
///
///
public abstract class Transport
{
///
/// The current transport used by Mirror.
///
public static Transport activeTransport;
///
/// Is this transport available in the current platform?
/// Some transports might only be available in mobile
/// Many will not work in webgl
/// Example usage: return Application.platform == RuntimePlatform.WebGLPlayer
///
/// True if this transport works in the current platform
public abstract bool Available();
#region Client
///
/// Notify subscribers when when this client establish a successful connection to the server
/// callback()
///
public Action OnClientConnected = () => Console.WriteLine("OnClientConnected called with no handler");
///
/// Notify subscribers when this client receive data from the server
/// callback(ArraySegment<byte> data, int channel)
///
public Action, int> OnClientDataReceived = (data, channel) => Console.WriteLine("OnClientDataReceived called with no handler");
///
/// Notify subscribers when this client encounters an error communicating with the server
/// callback(Exception e)
///
public Action OnClientError = (error) => Console.WriteLine("OnClientError called with no handler");
///
/// Notify subscribers when this client disconnects from the server
/// callback()
///
public Action OnClientDisconnected = () => Console.WriteLine("OnClientDisconnected called with no handler");
///
/// Determines if we are currently connected to the server
///
/// True if a connection has been established to the server
public abstract bool ClientConnected();
///
/// Establish a connection to a server
///
/// The IP address or FQDN of the server we are trying to connect to
public abstract void ClientConnect(string address);
///
/// Establish a connection to a server
///
/// The address of the server we are trying to connect to
public virtual void ClientConnect(Uri uri)
{
// By default, to keep backwards compatibility, just connect to the host
// in the uri
ClientConnect(uri.Host);
}
///
/// Send data to the server
///
/// The channel to use. 0 is the default channel,
/// but some transports might want to provide unreliable, encrypted, compressed, or any other feature
/// as new channels
/// The data to send to the server. Will be recycled after returning, so either use it directly or copy it internally. This allows for allocation-free sends!
public abstract void ClientSend(int channelId, ArraySegment segment);
///
/// Disconnect this client from the server
///
public abstract void ClientDisconnect();
#endregion
#region Server
///
/// Retrieves the address of this server.
/// Useful for network discovery
///
/// the url at which this server can be reached
public abstract Uri ServerUri();
///
/// Notify subscribers when a client connects to this server
/// callback(int connId)
///
public Action OnServerConnected = (connId) => Console.WriteLine("OnServerConnected called with no handler");
///
/// Notify subscribers when this server receives data from the client
/// callback(int connId, ArraySegment<byte> data, int channel)
///
public Action, int> OnServerDataReceived = (connId, data, channel) => Console.WriteLine("OnServerDataReceived called with no handler");
///
/// Notify subscribers when this server has some problem communicating with the client
/// callback(int connId, Exception e)
///
public Action OnServerError = (connId, error) => Console.WriteLine("OnServerError called with no handler");
///
/// Notify subscribers when a client disconnects from this server
/// callback(int connId)
///
public Action OnServerDisconnected = (connId) => Console.WriteLine("OnServerDisconnected called with no handler");
///
/// Determines if the server is up and running
///
/// true if the transport is ready for connections from clients
public abstract bool ServerActive();
///
/// Start listening for clients
///
public abstract void ServerStart(ushort port);
///
/// Send data to a client.
///
/// The client connection id to send the data to
/// The channel to be used. Transports can use channels to implement
/// other features such as unreliable, encryption, compression, etc...
///
public abstract void ServerSend(int connectionId, int channelId, ArraySegment segment);
///
/// Disconnect a client from this server. Useful to kick people out.
///
/// the id of the client to disconnect
/// true if the client was kicked
public abstract bool ServerDisconnect(int connectionId);
///
/// Get the client address
///
/// id of the client
/// address of the client
public abstract string ServerGetClientAddress(int connectionId);
///
/// Stop listening for clients and disconnect all existing clients
///
public abstract void ServerStop();
#endregion
///
/// The maximum packet size for a given channel. Unreliable transports
/// usually can only deliver small packets. Reliable fragmented channels
/// can usually deliver large ones.
///
/// GetMaxPacketSize needs to return a value at all times. Even if the
/// Transport isn't running, or isn't Available(). This is because
/// Fallback and Multiplex transports need to find the smallest possible
/// packet size at runtime.
///
/// channel id
/// the size in bytes that can be sent via the provided channel
public abstract int GetMaxPacketSize(int channelId = 0);
///
/// Shut down the transport, both as client and server
///
public abstract void Shutdown();
// block Update() to force Transports to use LateUpdate to avoid race
// conditions. messages should be processed after all the game state
// was processed in Update.
// -> in other words: use LateUpdate!
// -> uMMORPG 480 CCU stress test: when bot machine stops, it causes
// 'Observer not ready for ...' log messages when using Update
// -> occupying a public Update() function will cause Warnings if a
// transport uses Update.
//
// IMPORTANT: set script execution order to >1000 to call Transport's
// LateUpdate after all others. Fixes race condition where
// e.g. in uSurvival Transport would apply Cmds before
// ShoulderRotation.LateUpdate, resulting in projectile
// spawns at the point before shoulder rotation.
#pragma warning disable UNT0001 // Empty Unity message
public void Update() { }
#pragma warning restore UNT0001 // Empty Unity message
///
/// called when quitting the application by closing the window / pressing stop in the editor
/// virtual so that inheriting classes' OnApplicationQuit() can call base.OnApplicationQuit() too
///
public virtual void OnApplicationQuit()
{
// stop transport (e.g. to shut down threads)
// (when pressing Stop in the Editor, Unity keeps threads alive
// until we press Start again. so if Transports use threads, we
// really want them to end now and not after next start)
Shutdown();
}
}
}