123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- // 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
- {
- /// <summary>Abstract transport layer component</summary>
- public abstract class Transport : MonoBehaviour
- {
- /// <summary>The current transport used by Mirror.</summary>
- public static Transport active;
- /// <summary>Is this transport available in the current platform?</summary>
- public abstract bool Available();
- // client //////////////////////////////////////////////////////////////
- /// <summary>Called by Transport when the client connected to the server.</summary>
- public Action OnClientConnected;
- /// <summary>Called by Transport when the client received a message from the server.</summary>
- public Action<ArraySegment<byte>, int> OnClientDataReceived;
- /// <summary>Called by Transport when the client sent a message to the server.</summary>
- // Transports are responsible for calling it because:
- // - groups it together with OnReceived responsibility
- // - allows transports to decide if anything was sent or not
- // - allows transports to decide the actual used channel (i.e. tcp always sending reliable)
- public Action<ArraySegment<byte>, int> OnClientDataSent;
- /// <summary>Called by Transport when the client encountered an error.</summary>
- public Action<TransportError, string> OnClientError;
- /// <summary>Called by Transport when the client disconnected from the server.</summary>
- public Action OnClientDisconnected;
- // server //////////////////////////////////////////////////////////////
- /// <summary>Called by Transport when a new client connected to the server.</summary>
- public Action<int> OnServerConnected;
- /// <summary>Called by Transport when the server received a message from a client.</summary>
- public Action<int, ArraySegment<byte>, int> OnServerDataReceived;
- /// <summary>Called by Transport when the server sent a message to a client.</summary>
- // Transports are responsible for calling it because:
- // - groups it together with OnReceived responsibility
- // - allows transports to decide if anything was sent or not
- // - allows transports to decide the actual used channel (i.e. tcp always sending reliable)
- public Action<int, ArraySegment<byte>, int> OnServerDataSent;
- /// <summary>Called by Transport when a server's connection encountered a problem.</summary>
- /// If a Disconnect will also be raised, raise the Error first.
- public Action<int, TransportError, string> OnServerError;
- /// <summary>Called by Transport when a client disconnected from the server.</summary>
- public Action<int> OnServerDisconnected;
- // client functions ////////////////////////////////////////////////////
- /// <summary>True if the client is currently connected to the server.</summary>
- public abstract bool ClientConnected();
- /// <summary>Connects the client to the server at the address.</summary>
- public abstract void ClientConnect(string address);
- /// <summary>Connects the client to the server at the Uri.</summary>
- public virtual void ClientConnect(Uri uri)
- {
- // By default, to keep backwards compatibility, just connect to the host
- // in the uri
- ClientConnect(uri.Host);
- }
- /// <summary>Sends a message to the server over the given channel.</summary>
- // The ArraySegment is only valid until returning. Copy if needed.
- public abstract void ClientSend(ArraySegment<byte> segment, int channelId = Channels.Reliable);
- /// <summary>Disconnects the client from the server</summary>
- public abstract void ClientDisconnect();
- // server functions ////////////////////////////////////////////////////
- /// <summary>Returns server address as Uri.</summary>
- // Useful for NetworkDiscovery.
- public abstract Uri ServerUri();
- /// <summary>True if the server is currently listening for connections.</summary>
- public abstract bool ServerActive();
- /// <summary>Start listening for connections.</summary>
- public abstract void ServerStart();
- /// <summary>Send a message to a client over the given channel.</summary>
- public abstract void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId = Channels.Reliable);
- /// <summary>Disconnect a client from the server.</summary>
- public abstract void ServerDisconnect(int connectionId);
- /// <summary>Get a client's address on the server.</summary>
- // Can be useful for Game Master IP bans etc.
- public abstract string ServerGetClientAddress(int connectionId);
- /// <summary>Stop listening and disconnect all connections.</summary>
- public abstract void ServerStop();
- /// <summary>Maximum message size for the given channel.</summary>
- // 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);
- /// <summary>Recommended Batching threshold for this transport.</summary>
- // 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
- /// <summary>
- /// 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.
- /// </summary>
- // => 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() {}
- /// <summary>Shut down the transport, both as client and server</summary>
- public abstract void Shutdown();
- /// <summary>Called by Unity when quitting. Inheriting Transports should call base for proper Shutdown.</summary>
- 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();
- }
- }
- }
|