WebSocket.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #if UNITY_WEBGL || WEBSOCKET || ((UNITY_XBOXONE || UNITY_GAMECORE) && UNITY_EDITOR)
  2. // --------------------------------------------------------------------------------------------------------------------
  3. // <summary>
  4. // Provided originally by Unity to cover WebSocket support in WebGL and the Editor. Modified by Exit Games GmbH.
  5. // </summary>
  6. // <author>developer@exitgames.com</author>
  7. // --------------------------------------------------------------------------------------------------------------------
  8. namespace ExitGames.Client.Photon
  9. {
  10. using System;
  11. using System.Text;
  12. #if UNITY_WEBGL && !UNITY_EDITOR
  13. using System.Runtime.InteropServices;
  14. #else
  15. using WebSocketSharp;
  16. using System.Collections.Generic;
  17. using System.Security.Authentication;
  18. #endif
  19. public class WebSocket
  20. {
  21. private Uri mUrl;
  22. /// <summary>Photon uses this to agree on a serialization protocol. Either: GpBinaryV16 or GpBinaryV18. Based on enum SerializationProtocol.</summary>
  23. private string protocols = "GpBinaryV16";
  24. public WebSocket(Uri url, string serialization = null)
  25. {
  26. this.mUrl = url;
  27. if (serialization != null)
  28. {
  29. this.protocols = serialization;
  30. }
  31. string protocol = mUrl.Scheme;
  32. if (!protocol.Equals("ws") && !protocol.Equals("wss"))
  33. throw new ArgumentException("Unsupported protocol: " + protocol);
  34. }
  35. public void SendString(string str)
  36. {
  37. Send(Encoding.UTF8.GetBytes (str));
  38. }
  39. public string RecvString()
  40. {
  41. byte[] retval = Recv();
  42. if (retval == null)
  43. return null;
  44. return Encoding.UTF8.GetString (retval);
  45. }
  46. #if UNITY_WEBGL && !UNITY_EDITOR
  47. [DllImport("__Internal")]
  48. private static extern int SocketCreate (string url, string protocols);
  49. [DllImport("__Internal")]
  50. private static extern int SocketState (int socketInstance);
  51. [DllImport("__Internal")]
  52. private static extern void SocketSend (int socketInstance, byte[] ptr, int length);
  53. [DllImport("__Internal")]
  54. private static extern void SocketRecv (int socketInstance, byte[] ptr, int length);
  55. [DllImport("__Internal")]
  56. private static extern int SocketRecvLength (int socketInstance);
  57. [DllImport("__Internal")]
  58. private static extern void SocketClose (int socketInstance);
  59. [DllImport("__Internal")]
  60. private static extern int SocketError (int socketInstance, byte[] ptr, int length);
  61. int m_NativeRef = 0;
  62. public void Send(byte[] buffer)
  63. {
  64. SocketSend (m_NativeRef, buffer, buffer.Length);
  65. }
  66. public byte[] Recv()
  67. {
  68. int length = SocketRecvLength (m_NativeRef);
  69. if (length == 0)
  70. return null;
  71. byte[] buffer = new byte[length];
  72. SocketRecv (m_NativeRef, buffer, length);
  73. return buffer;
  74. }
  75. public void Connect()
  76. {
  77. m_NativeRef = SocketCreate (mUrl.ToString(), this.protocols);
  78. //while (SocketState(m_NativeRef) == 0)
  79. // yield return 0;
  80. }
  81. public void Close()
  82. {
  83. SocketClose(m_NativeRef);
  84. }
  85. public bool Connected
  86. {
  87. get { return SocketState(m_NativeRef) != 0; }
  88. }
  89. public string Error
  90. {
  91. get {
  92. const int bufsize = 1024;
  93. byte[] buffer = new byte[bufsize];
  94. int result = SocketError (m_NativeRef, buffer, bufsize);
  95. if (result == 0)
  96. return null;
  97. return Encoding.UTF8.GetString (buffer);
  98. }
  99. }
  100. #else
  101. WebSocketSharp.WebSocket m_Socket;
  102. Queue<byte[]> m_Messages = new Queue<byte[]>();
  103. bool m_IsConnected = false;
  104. string m_Error = null;
  105. public void Connect()
  106. {
  107. m_Socket = new WebSocketSharp.WebSocket(mUrl.ToString(), new string[] { this.protocols });
  108. m_Socket.SslConfiguration.EnabledSslProtocols = m_Socket.SslConfiguration.EnabledSslProtocols | (SslProtocols)(3072| 768);
  109. m_Socket.OnMessage += (sender, e) => m_Messages.Enqueue(e.RawData);
  110. m_Socket.OnOpen += (sender, e) => m_IsConnected = true;
  111. //this.m_Socket.Log.Level = LogLevel.Debug;
  112. //this.m_Socket.Log.Output += Output;
  113. this.m_Socket.OnClose += SocketOnClose;
  114. m_Socket.OnError += (sender, e) => m_Error = e.Message + (e.Exception == null ? "" : " / " + e.Exception);
  115. m_Socket.ConnectAsync();
  116. }
  117. private void SocketOnClose(object sender, CloseEventArgs e)
  118. {
  119. //UnityEngine.Debug.Log(e.Code.ToString());
  120. // this code is used for cases when the socket failed to get created (specifically used to detect "blocked by Windows firewall")
  121. // for some reason this situation is not calling OnError
  122. if (e.Code == 1006)
  123. {
  124. this.m_Error = e.Reason;
  125. this.m_IsConnected = false;
  126. }
  127. }
  128. public bool Connected { get { return m_IsConnected; } }// added by TS
  129. public void Send(byte[] buffer)
  130. {
  131. m_Socket.Send(buffer);
  132. }
  133. public byte[] Recv()
  134. {
  135. if (m_Messages.Count == 0)
  136. return null;
  137. return m_Messages.Dequeue();
  138. }
  139. public void Close()
  140. {
  141. m_Socket.Close();
  142. }
  143. public string Error
  144. {
  145. get
  146. {
  147. return m_Error;
  148. }
  149. }
  150. #endif
  151. }
  152. }
  153. #endif