LocalConnectionToServer.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace Mirror
  5. {
  6. // a localClient's connection TO a server.
  7. // send messages on this connection causes the server's handler function to be invoked directly.
  8. public class LocalConnectionToServer : NetworkConnectionToServer
  9. {
  10. internal LocalConnectionToClient connectionToClient;
  11. // packet queue
  12. internal readonly Queue<NetworkWriterPooled> queue = new Queue<NetworkWriterPooled>();
  13. public override string address => "localhost";
  14. // see caller for comments on why we need this
  15. bool connectedEventPending;
  16. bool disconnectedEventPending;
  17. internal void QueueConnectedEvent() => connectedEventPending = true;
  18. internal void QueueDisconnectedEvent() => disconnectedEventPending = true;
  19. // Send stage two: serialized NetworkMessage as ArraySegment<byte>
  20. internal override void Send(ArraySegment<byte> segment, int channelId = Channels.Reliable)
  21. {
  22. if (segment.Count == 0)
  23. {
  24. Debug.LogError("LocalConnection.SendBytes cannot send zero bytes");
  25. return;
  26. }
  27. // OnTransportData assumes batching.
  28. // so let's make a batch with proper timestamp prefix.
  29. Batcher batcher = GetBatchForChannelId(channelId);
  30. batcher.AddMessage(segment, NetworkTime.localTime);
  31. // flush it to the server's OnTransportData immediately.
  32. // local connection to server always invokes immediately.
  33. using (NetworkWriterPooled writer = NetworkWriterPool.Get())
  34. {
  35. // make a batch with our local time (double precision)
  36. if (batcher.GetBatch(writer))
  37. {
  38. NetworkServer.OnTransportData(connectionId, writer.ToArraySegment(), channelId);
  39. }
  40. else Debug.LogError("Local connection failed to make batch. This should never happen.");
  41. }
  42. }
  43. internal override void Update()
  44. {
  45. base.Update();
  46. // should we still process a connected event?
  47. if (connectedEventPending)
  48. {
  49. connectedEventPending = false;
  50. NetworkClient.OnConnectedEvent?.Invoke();
  51. }
  52. // process internal messages so they are applied at the correct time
  53. while (queue.Count > 0)
  54. {
  55. // call receive on queued writer's content, return to pool
  56. NetworkWriterPooled writer = queue.Dequeue();
  57. ArraySegment<byte> message = writer.ToArraySegment();
  58. // OnTransportData assumes a proper batch with timestamp etc.
  59. // let's make a proper batch and pass it to OnTransportData.
  60. Batcher batcher = GetBatchForChannelId(Channels.Reliable);
  61. batcher.AddMessage(message, NetworkTime.localTime);
  62. using (NetworkWriterPooled batchWriter = NetworkWriterPool.Get())
  63. {
  64. // make a batch with our local time (double precision)
  65. if (batcher.GetBatch(batchWriter))
  66. {
  67. NetworkClient.OnTransportData(batchWriter.ToArraySegment(), Channels.Reliable);
  68. }
  69. }
  70. NetworkWriterPool.Return(writer);
  71. }
  72. // should we still process a disconnected event?
  73. if (disconnectedEventPending)
  74. {
  75. disconnectedEventPending = false;
  76. NetworkClient.OnDisconnectedEvent?.Invoke();
  77. }
  78. }
  79. /// <summary>Disconnects this connection.</summary>
  80. internal void DisconnectInternal()
  81. {
  82. // set not ready and handle clientscene disconnect in any case
  83. // (might be client or host mode here)
  84. // TODO remove redundant state. have one source of truth for .ready!
  85. isReady = false;
  86. NetworkClient.ready = false;
  87. }
  88. /// <summary>Disconnects this connection.</summary>
  89. public override void Disconnect()
  90. {
  91. connectionToClient.DisconnectInternal();
  92. DisconnectInternal();
  93. // simulate what a true remote connection would do:
  94. // first, the server should remove it:
  95. // TODO should probably be in connectionToClient.DisconnectInternal
  96. // because that's the NetworkServer's connection!
  97. NetworkServer.RemoveLocalConnection();
  98. // then call OnTransportDisconnected for proper disconnect handling,
  99. // callbacks & cleanups.
  100. // => otherwise OnClientDisconnected() is never called!
  101. // => see NetworkClientTests.DisconnectCallsOnClientDisconnect_HostMode()
  102. NetworkClient.OnTransportDisconnected();
  103. }
  104. // true because local connections never timeout
  105. internal override bool IsAlive(float timeout) => true;
  106. }
  107. }