Transport.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // For future reference, here is what Transports need to do in Mirror:
  2. //
  3. // Connecting:
  4. // * Transports are responsible to call either OnConnected || OnDisconnected
  5. // in a certain time after a Connect was called. It can not end in limbo.
  6. //
  7. // Disconnecting:
  8. // * Connections might disconnect voluntarily by the other end.
  9. // * Connections might be disconnect involuntarily by the server.
  10. // * Either way, Transports need to detect it and call OnDisconnected.
  11. //
  12. // Timeouts:
  13. // * Transports should expose a configurable timeout
  14. // * Transports are responsible for calling OnDisconnected after a timeout
  15. //
  16. // Channels:
  17. // * Default channel is Reliable, as in reliable ordered (OR DISCONNECT)
  18. // * Where possible, Unreliable should be supported (unordered, no guarantee)
  19. //
  20. // Other:
  21. // * Transports functions are all bound to the main thread.
  22. // (Transports can use other threads in the background if they manage them)
  23. // * Transports should only process messages while the component is enabled.
  24. //
  25. using System;
  26. using UnityEngine;
  27. namespace Mirror
  28. {
  29. /// <summary>Abstract transport layer component</summary>
  30. public abstract class Transport : MonoBehaviour
  31. {
  32. /// <summary>The current transport used by Mirror.</summary>
  33. public static Transport activeTransport;
  34. /// <summary>Is this transport available in the current platform?</summary>
  35. public abstract bool Available();
  36. /// <summary>Called by Transport when the client connected to the server.</summary>
  37. public Action OnClientConnected = () => Debug.LogWarning("OnClientConnected called with no handler");
  38. /// <summary>Called by Transport when the client received a message from the server.</summary>
  39. public Action<ArraySegment<byte>, int> OnClientDataReceived = (data, channel) => Debug.LogWarning("OnClientDataReceived called with no handler");
  40. /// <summary>Called by Transport when the client encountered an error.</summary>
  41. public Action<Exception> OnClientError = (error) => Debug.LogWarning("OnClientError called with no handler");
  42. /// <summary>Called by Transport when the client disconnected from the server.</summary>
  43. public Action OnClientDisconnected = () => Debug.LogWarning("OnClientDisconnected called with no handler");
  44. /// <summary>True if the client is currently connected to the server.</summary>
  45. public abstract bool ClientConnected();
  46. /// <summary>Connects the client to the server at the address.</summary>
  47. public abstract void ClientConnect(string address);
  48. /// <summary>Connects the client to the server at the Uri.</summary>
  49. public virtual void ClientConnect(Uri uri)
  50. {
  51. // By default, to keep backwards compatibility, just connect to the host
  52. // in the uri
  53. ClientConnect(uri.Host);
  54. }
  55. /// <summary>Sends a message to the server over the given channel.</summary>
  56. // The ArraySegment is only valid until returning. Copy if needed.
  57. // TODO make second version abstract after removing the obsolete version
  58. // Deprecated 2021-05-17
  59. [Obsolete("Use ClientSend(segment, channelId) instead. channelId is now the last parameter.")]
  60. public virtual void ClientSend(int channelId, ArraySegment<byte> segment) {}
  61. public virtual void ClientSend(ArraySegment<byte> segment, int channelId)
  62. {
  63. // defaults to obsolete version to not force break transports.
  64. #pragma warning disable 618
  65. ClientSend(channelId, segment);
  66. #pragma warning restore 618
  67. }
  68. /// <summary>Disconnects the client from the server</summary>
  69. public abstract void ClientDisconnect();
  70. /// <summary>Returns server address as Uri.</summary>
  71. // Useful for NetworkDiscovery.
  72. public abstract Uri ServerUri();
  73. /// <summary>Called by Transport when a new client connected to the server.</summary>
  74. public Action<int> OnServerConnected = (connId) => Debug.LogWarning("OnServerConnected called with no handler");
  75. /// <summary>Called by Transport when the server received a message from a client.</summary>
  76. public Action<int, ArraySegment<byte>, int> OnServerDataReceived = (connId, data, channel) => Debug.LogWarning("OnServerDataReceived called with no handler");
  77. /// <summary>Called by Transport when a server's connection encountered a problem.</summary>
  78. /// If a Disconnect will also be raised, raise the Error first.
  79. public Action<int, Exception> OnServerError = (connId, error) => Debug.LogWarning("OnServerError called with no handler");
  80. /// <summary>Called by Transport when a client disconnected from the server.</summary>
  81. public Action<int> OnServerDisconnected = (connId) => Debug.LogWarning("OnServerDisconnected called with no handler");
  82. /// <summary>True if the server is currently listening for connections.</summary>
  83. public abstract bool ServerActive();
  84. /// <summary>Start listening for connections.</summary>
  85. public abstract void ServerStart();
  86. /// <summary>Send a message to a client over the given channel.</summary>
  87. // TODO make second version abstract after removing the obsolete version
  88. // Deprecated 2021-05-17
  89. [Obsolete("Use ServerSend(connectionId, segment, channelId) instead. channelId is now the last parameter.")]
  90. public virtual void ServerSend(int connectionId, int channelId, ArraySegment<byte> segment) {}
  91. public virtual void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId)
  92. {
  93. // defaults to obsolete version to not force break transports.
  94. #pragma warning disable 618
  95. ServerSend(connectionId, channelId, segment);
  96. #pragma warning restore 618
  97. }
  98. /// <summary>Disconnect a client from the server.</summary>
  99. public abstract void ServerDisconnect(int connectionId);
  100. /// <summary>Get a client's address on the server.</summary>
  101. // Can be useful for Game Master IP bans etc.
  102. public abstract string ServerGetClientAddress(int connectionId);
  103. /// <summary>Stop listening and disconnect all connections.</summary>
  104. public abstract void ServerStop();
  105. /// <summary>Maximum message size for the given channel.</summary>
  106. // Different channels often have different sizes, ranging from MTU to
  107. // several megabytes.
  108. //
  109. // Needs to return a value at all times, even if the Transport isn't
  110. // running or available because it's needed for initializations.
  111. public abstract int GetMaxPacketSize(int channelId = Channels.Reliable);
  112. /// <summary>Recommended Batching threshold for this transport.</summary>
  113. // Uses GetMaxPacketSize by default.
  114. // Some transports like kcp support large max packet sizes which should
  115. // not be used for batching all the time because they end up being too
  116. // slow (head of line blocking etc.).
  117. public virtual int GetBatchThreshold(int channelId)
  118. {
  119. // change to GetMaxPacketSize by default after removing obsolete
  120. #pragma warning disable 618
  121. return GetMaxBatchSize(channelId);
  122. #pragma warning restore 618
  123. }
  124. // Deprecated 2021-06-17
  125. [Obsolete("GetMaxBatchSize was renamed to GetBatchThreshold.")]
  126. public virtual int GetMaxBatchSize(int channelId) =>
  127. GetMaxPacketSize(channelId);
  128. // block Update & LateUpdate to show warnings if Transports still use
  129. // them instead of using
  130. // Client/ServerEarlyUpdate: to process incoming messages
  131. // Client/ServerLateUpdate: to process outgoing messages
  132. // those are called by NetworkClient/Server at the right time.
  133. //
  134. // allows transports to implement the proper network update order of:
  135. // process_incoming()
  136. // update_world()
  137. // process_outgoing()
  138. //
  139. // => see NetworkLoop.cs for detailed explanations!
  140. #pragma warning disable UNT0001 // Empty Unity message
  141. public void Update() {}
  142. public void LateUpdate() {}
  143. #pragma warning restore UNT0001 // Empty Unity message
  144. /// <summary>
  145. /// NetworkLoop NetworkEarly/LateUpdate were added for a proper network
  146. /// update order. the goal is to:
  147. /// process_incoming()
  148. /// update_world()
  149. /// process_outgoing()
  150. /// in order to avoid unnecessary latency and data races.
  151. /// </summary>
  152. // => split into client and server parts so that we can cleanly call
  153. // them from NetworkClient/Server
  154. // => VIRTUAL for now so we can take our time to convert transports
  155. // without breaking anything.
  156. public virtual void ClientEarlyUpdate() {}
  157. public virtual void ServerEarlyUpdate() {}
  158. public virtual void ClientLateUpdate() {}
  159. public virtual void ServerLateUpdate() {}
  160. /// <summary>Shut down the transport, both as client and server</summary>
  161. public abstract void Shutdown();
  162. /// <summary>Called by Unity when quitting. Inheriting Transports should call base for proper Shutdown.</summary>
  163. public virtual void OnApplicationQuit()
  164. {
  165. // stop transport (e.g. to shut down threads)
  166. // (when pressing Stop in the Editor, Unity keeps threads alive
  167. // until we press Start again. so if Transports use threads, we
  168. // really want them to end now and not after next start)
  169. Shutdown();
  170. }
  171. }
  172. }