WebSocketTransport.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #if !BESTHTTP_DISABLE_SIGNALR
  2. #if !BESTHTTP_DISABLE_WEBSOCKET
  3. using System;
  4. using System.Text;
  5. using BestHTTP;
  6. using BestHTTP.JSON;
  7. using BestHTTP.SignalR.Hubs;
  8. using BestHTTP.SignalR.Messages;
  9. using BestHTTP.SignalR.JsonEncoders;
  10. namespace BestHTTP.SignalR.Transports
  11. {
  12. public sealed class WebSocketTransport : TransportBase
  13. {
  14. #region Overridden Properties
  15. public override bool SupportsKeepAlive { get { return true; } }
  16. public override TransportTypes Type { get { return TransportTypes.WebSocket; } }
  17. #endregion
  18. private WebSocket.WebSocket wSocket;
  19. public WebSocketTransport(Connection connection)
  20. : base("webSockets", connection)
  21. {
  22. }
  23. #region Overrides from TransportBase
  24. /// <summary>
  25. /// Websocket transport specific connection logic. It will create a WebSocket instance, and starts to connect to the server.
  26. /// </summary>
  27. public override void Connect()
  28. {
  29. if (wSocket != null)
  30. {
  31. HTTPManager.Logger.Warning("WebSocketTransport", "Start - WebSocket already created!");
  32. return;
  33. }
  34. // Skip the Connecting state if we are reconnecting. If the connect succeeds, we will set the Started state directly
  35. if (this.State != TransportStates.Reconnecting)
  36. this.State = TransportStates.Connecting;
  37. RequestTypes requestType = this.State == TransportStates.Reconnecting ? RequestTypes.Reconnect : RequestTypes.Connect;
  38. Uri uri = Connection.BuildUri(requestType, this);
  39. // Create the WebSocket instance
  40. wSocket = new WebSocket.WebSocket(uri);
  41. // Set up eventhandlers
  42. wSocket.OnOpen += WSocket_OnOpen;
  43. wSocket.OnMessage += WSocket_OnMessage;
  44. wSocket.OnClosed += WSocket_OnClosed;
  45. wSocket.OnErrorDesc += WSocket_OnError;
  46. #if !UNITY_WEBGL || UNITY_EDITOR
  47. // prepare the internal http request
  48. Connection.PrepareRequest(wSocket.InternalRequest, requestType);
  49. #endif
  50. // start opening the websocket protocol
  51. wSocket.Open();
  52. }
  53. protected override void SendImpl(string json)
  54. {
  55. if (wSocket != null && wSocket.IsOpen)
  56. wSocket.Send(json);
  57. }
  58. public override void Stop()
  59. {
  60. if (wSocket != null)
  61. {
  62. wSocket.OnOpen = null;
  63. wSocket.OnMessage = null;
  64. wSocket.OnClosed = null;
  65. wSocket.OnErrorDesc = null;
  66. wSocket.Close();
  67. wSocket = null;
  68. }
  69. }
  70. protected override void Started()
  71. {
  72. // Nothing to be done here for this transport
  73. }
  74. /// <summary>
  75. /// The /abort request successfully finished
  76. /// </summary>
  77. protected override void Aborted()
  78. {
  79. // if the websocket is still open, close it
  80. if (wSocket != null && wSocket.IsOpen)
  81. {
  82. wSocket.Close();
  83. wSocket = null;
  84. }
  85. }
  86. #endregion
  87. #region WebSocket Events
  88. void WSocket_OnOpen(WebSocket.WebSocket webSocket)
  89. {
  90. if (webSocket != wSocket)
  91. return;
  92. HTTPManager.Logger.Information("WebSocketTransport", "WSocket_OnOpen");
  93. OnConnected();
  94. }
  95. void WSocket_OnMessage(WebSocket.WebSocket webSocket, string message)
  96. {
  97. if (webSocket != wSocket)
  98. return;
  99. IServerMessage msg = TransportBase.Parse(Connection.JsonEncoder, message);
  100. if (msg != null)
  101. Connection.OnMessage(msg);
  102. }
  103. void WSocket_OnClosed(WebSocket.WebSocket webSocket, ushort code, string message)
  104. {
  105. if (webSocket != wSocket)
  106. return;
  107. string reason = code.ToString() + " : " + message;
  108. HTTPManager.Logger.Information("WebSocketTransport", "WSocket_OnClosed " + reason);
  109. if (this.State == TransportStates.Closing)
  110. this.State = TransportStates.Closed;
  111. else
  112. Connection.Error(reason);
  113. }
  114. void WSocket_OnError(WebSocket.WebSocket webSocket, string reason)
  115. {
  116. if (webSocket != wSocket)
  117. return;
  118. // On WP8.1, somehow we receive an exception that the remote server forcibly closed the connection instead of the
  119. // WebSocket closed packet... Also, even the /abort request didn't finished.
  120. if (this.State == TransportStates.Closing ||
  121. this.State == TransportStates.Closed)
  122. {
  123. base.AbortFinished();
  124. }
  125. else
  126. {
  127. HTTPManager.Logger.Error("WebSocketTransport", "WSocket_OnError " + reason);
  128. this.State = TransportStates.Closed;
  129. Connection.Error(reason);
  130. }
  131. }
  132. #endregion
  133. }
  134. }
  135. #endif
  136. #endif