// For future reference, here is what Transports need to do in Mirror:
//
// Connecting:
// * Transports are responsible to call either OnConnected || OnDisconnected
// in a certain time after a Connect was called. It can not end in limbo.
//
// Disconnecting:
// * Connections might disconnect voluntarily by the other end.
// * Connections might be disconnect involuntarily by the server.
// * Either way, Transports need to detect it and call OnDisconnected.
//
// Timeouts:
// * Transports should expose a configurable timeout
// * Transports are responsible for calling OnDisconnected after a timeout
//
// Channels:
// * Default channel is Reliable, as in reliable ordered (OR DISCONNECT)
// * Where possible, Unreliable should be supported (unordered, no guarantee)
//
// Other:
// * Transports functions are all bound to the main thread.
// (Transports can use other threads in the background if they manage them)
// * Transports should only process messages while the component is enabled.
//
using System;
using UnityEngine;
namespace Mirror
{
/// Abstract transport layer component
public abstract class Transport : MonoBehaviour
{
/// The current transport used by Mirror.
public static Transport activeTransport;
/// Is this transport available in the current platform?
public abstract bool Available();
/// Called by Transport when the client connected to the server.
public Action OnClientConnected = () => Debug.LogWarning("OnClientConnected called with no handler");
/// Called by Transport when the client received a message from the server.
public Action, int> OnClientDataReceived = (data, channel) => Debug.LogWarning("OnClientDataReceived called with no handler");
/// Called by Transport when the client encountered an error.
public Action OnClientError = (error) => Debug.LogWarning("OnClientError called with no handler");
/// Called by Transport when the client disconnected from the server.
public Action OnClientDisconnected = () => Debug.LogWarning("OnClientDisconnected called with no handler");
/// True if the client is currently connected to the server.
public abstract bool ClientConnected();
/// Connects the client to the server at the address.
public abstract void ClientConnect(string address);
/// Connects the client to the server at the Uri.
public virtual void ClientConnect(Uri uri)
{
// By default, to keep backwards compatibility, just connect to the host
// in the uri
ClientConnect(uri.Host);
}
/// Sends a message to the server over the given channel.
// The ArraySegment is only valid until returning. Copy if needed.
public abstract void ClientSend(ArraySegment segment, int channelId = Channels.Reliable);
/// Disconnects the client from the server
public abstract void ClientDisconnect();
/// Returns server address as Uri.
// Useful for NetworkDiscovery.
public abstract Uri ServerUri();
/// Called by Transport when a new client connected to the server.
public Action OnServerConnected = (connId) => Debug.LogWarning("OnServerConnected called with no handler");
/// Called by Transport when the server received a message from a client.
public Action, int> OnServerDataReceived = (connId, data, channel) => Debug.LogWarning("OnServerDataReceived called with no handler");
/// Called by Transport when a server's connection encountered a problem.
/// If a Disconnect will also be raised, raise the Error first.
public Action OnServerError = (connId, error) => Debug.LogWarning("OnServerError called with no handler");
/// Called by Transport when a client disconnected from the server.
public Action OnServerDisconnected = (connId) => Debug.LogWarning("OnServerDisconnected called with no handler");
/// True if the server is currently listening for connections.
public abstract bool ServerActive();
/// Start listening for connections.
public abstract void ServerStart();
/// Send a message to a client over the given channel.
public abstract void ServerSend(int connectionId, ArraySegment segment, int channelId = Channels.Reliable);
/// Disconnect a client from the server.
public abstract void ServerDisconnect(int connectionId);
/// Get a client's address on the server.
// Can be useful for Game Master IP bans etc.
public abstract string ServerGetClientAddress(int connectionId);
/// Stop listening and disconnect all connections.
public abstract void ServerStop();
/// Maximum message size for the given channel.
// Different channels often have different sizes, ranging from MTU to
// several megabytes.
//
// Needs to return a value at all times, even if the Transport isn't
// running or available because it's needed for initializations.
public abstract int GetMaxPacketSize(int channelId = Channels.Reliable);
/// Recommended Batching threshold for this transport.
// Uses GetMaxPacketSize by default.
// Some transports like kcp support large max packet sizes which should
// not be used for batching all the time because they end up being too
// slow (head of line blocking etc.).
public virtual int GetBatchThreshold(int channelId = Channels.Reliable)
{
return GetMaxPacketSize(channelId);
}
// block Update & LateUpdate to show warnings if Transports still use
// them instead of using
// Client/ServerEarlyUpdate: to process incoming messages
// Client/ServerLateUpdate: to process outgoing messages
// those are called by NetworkClient/Server at the right time.
//
// allows transports to implement the proper network update order of:
// process_incoming()
// update_world()
// process_outgoing()
//
// => see NetworkLoop.cs for detailed explanations!
#pragma warning disable UNT0001 // Empty Unity message
public void Update() {}
public void LateUpdate() {}
#pragma warning restore UNT0001 // Empty Unity message
///
/// NetworkLoop NetworkEarly/LateUpdate were added for a proper network
/// update order. the goal is to:
/// process_incoming()
/// update_world()
/// process_outgoing()
/// in order to avoid unnecessary latency and data races.
///
// => split into client and server parts so that we can cleanly call
// them from NetworkClient/Server
// => VIRTUAL for now so we can take our time to convert transports
// without breaking anything.
public virtual void ClientEarlyUpdate() {}
public virtual void ServerEarlyUpdate() {}
public virtual void ClientLateUpdate() {}
public virtual void ServerLateUpdate() {}
/// Shut down the transport, both as client and server
public abstract void Shutdown();
/// Called by Unity when quitting. Inheriting Transports should call base for proper Shutdown.
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();
}
}
}