123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- #if UNITY_WEBGL || WEBSOCKET || WEBSOCKET_PROXYCONFIG
- // --------------------------------------------------------------------------------------------------------------------
- // <summary>
- // Provided originally by Unity to cover WebSocket support in WebGL and the Editor. Modified by Exit Games GmbH.
- // </summary>
- // <author>developer@exitgames.com</author>
- // --------------------------------------------------------------------------------------------------------------------
- namespace ExitGames.Client.Photon
- {
- using System;
- using System.Text;
- using ExitGames.Client.Photon;
- #if UNITY_WEBGL && !UNITY_EDITOR
- using System.Runtime.InteropServices;
- #else
- using WebSocketSharp;
- using System.Collections.Generic;
- using System.Security.Authentication;
- #endif
- public class WebSocket
- {
- private Uri mUrl;
- private string mProxyAddress;
- /// <summary>Photon uses this to agree on a serialization protocol. Either: GpBinaryV16 or GpBinaryV18. Based on enum SerializationProtocol.</summary>
- private string protocols = "GpBinaryV16";
- public Action<DebugLevel, string> DebugReturn { get; set; }
- public WebSocket(Uri url, string proxyAddress, string protocols = null)
- {
- this.mUrl = url;
- this.mProxyAddress = proxyAddress;
- if (protocols != null)
- {
- this.protocols = protocols;
- }
- string protocol = mUrl.Scheme;
- if (!protocol.Equals("ws") && !protocol.Equals("wss"))
- {
- throw new ArgumentException("Unsupported protocol: " + protocol);
- }
- }
- public string ProxyAddress
- {
- get { return mProxyAddress; }
- }
- public void SendString(string str)
- {
- Send(Encoding.UTF8.GetBytes(str));
- }
- public string RecvString()
- {
- byte[] retval = Recv();
- if (retval == null)
- return null;
- return Encoding.UTF8.GetString(retval);
- }
- #if UNITY_WEBGL && !UNITY_EDITOR
- [DllImport("__Internal")]
- private static extern int SocketCreate (string url, string protocols);
- [DllImport("__Internal")]
- private static extern int SocketState (int socketInstance);
- [DllImport("__Internal")]
- private static extern void SocketSend (int socketInstance, byte[] ptr, int length);
- [DllImport("__Internal")]
- private static extern void SocketRecv (int socketInstance, byte[] ptr, int length);
- [DllImport("__Internal")]
- private static extern int SocketRecvLength (int socketInstance);
- [DllImport("__Internal")]
- private static extern void SocketClose (int socketInstance);
- [DllImport("__Internal")]
- private static extern int SocketError (int socketInstance, byte[] ptr, int length);
- int m_NativeRef = 0;
- public void Send(byte[] buffer)
- {
- SocketSend (m_NativeRef, buffer, buffer.Length);
- }
- public byte[] Recv()
- {
- int length = SocketRecvLength (m_NativeRef);
- if (length == 0)
- return null;
- byte[] buffer = new byte[length];
- SocketRecv (m_NativeRef, buffer, length);
- return buffer;
- }
- public void Connect()
- {
- m_NativeRef = SocketCreate (mUrl.ToString(), this.protocols);
- //while (SocketState(m_NativeRef) == 0)
- // yield return 0;
- }
- public void Close()
- {
- SocketClose(m_NativeRef);
- }
- public bool Connected
- {
- get { return SocketState(m_NativeRef) != 0; }
- }
- public string Error
- {
- get {
- const int bufsize = 1024;
- byte[] buffer = new byte[bufsize];
- int result = SocketError (m_NativeRef, buffer, bufsize);
- if (result == 0)
- return null;
- return Encoding.UTF8.GetString (buffer);
- }
- }
- #else
- WebSocketSharp.WebSocket m_Socket;
- Queue<byte[]> m_Messages = new Queue<byte[]>();
- bool m_IsConnected = false;
- string m_Error = null;
- public void Connect()
- {
- m_Socket = new WebSocketSharp.WebSocket(mUrl.ToString(), new string[] {this.protocols});
- m_Socket.Log.Output = (ld, f) =>
- {
- var s = string.Format("WebSocketSharp: {0}", ld.Message);
- switch (ld.Level)
- {
- case WebSocketSharp.LogLevel.Trace:
- case WebSocketSharp.LogLevel.Debug:
- DebugReturn(DebugLevel.ALL, s);
- break;
- case WebSocketSharp.LogLevel.Info:
- DebugReturn(DebugLevel.INFO, s);
- break;
- case WebSocketSharp.LogLevel.Warn:
- DebugReturn(DebugLevel.WARNING, s);
- break;
- case WebSocketSharp.LogLevel.Error:
- case WebSocketSharp.LogLevel.Fatal:
- DebugReturn(DebugLevel.ERROR, s);
- break;
- }
- };
- string user = null;
- string pass = null;
- if (!String.IsNullOrEmpty(mProxyAddress))
- {
- var authDelim = mProxyAddress.IndexOf("@");
- if (authDelim != -1)
- {
- user = mProxyAddress.Substring(0, authDelim);
- mProxyAddress = mProxyAddress.Substring(authDelim + 1);
- var passDelim = user.IndexOf(":");
- if (passDelim != -1)
- {
- pass = user.Substring(passDelim + 1);
- user = user.Substring(0, passDelim);
- }
- }
- // throws an exception, if scheme not specified
- m_Socket.SetProxy("http://" + mProxyAddress, user, pass);
- }
- if (m_Socket.IsSecure)
- {
- m_Socket.SslConfiguration.EnabledSslProtocols = m_Socket.SslConfiguration.EnabledSslProtocols | (SslProtocols)(3072 | 768);
- }
- m_Socket.OnMessage += (sender, e) => { m_Messages.Enqueue(e.RawData); };
- m_Socket.OnOpen += (sender, e) => { m_IsConnected = true; };
- m_Socket.OnError += (sender, e) => { m_Error = e.Message + (e.Exception == null ? "" : " / " + e.Exception); };
- this.m_Socket.OnClose += SocketOnClose;
- m_Socket.ConnectAsync();
- }
- private void SocketOnClose(object sender, CloseEventArgs e)
- {
- //UnityEngine.Debug.Log(e.Code.ToString());
- // this code is used for cases when the socket failed to get created (specifically used to detect "blocked by Windows firewall")
- // for some reason this situation is not calling OnError
- if (e.Code == 1006)
- {
- this.m_Error = e.Reason;
- this.m_IsConnected = false;
- }
- }
- public bool Connected
- {
- get { return m_IsConnected; }
- }
- public void Send(byte[] buffer)
- {
- m_Socket.Send(buffer);
- }
- public byte[] Recv()
- {
- if (m_Messages.Count == 0)
- return null;
- return m_Messages.Dequeue();
- }
- public void Close()
- {
- m_Socket.Close();
- }
- public string Error
- {
- get { return m_Error; }
- }
- #endif
- }
- }
- #endif
|