Pun-01/Assets/Photon/PhotonLibs/WebSocket/WebSocket.cs
2022-07-08 09:14:55 +08:00

188 lines
5.9 KiB
C#

#if UNITY_WEBGL || WEBSOCKET || ((UNITY_XBOXONE || UNITY_GAMECORE) && UNITY_EDITOR)
// --------------------------------------------------------------------------------------------------------------------
// <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;
#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;
/// <summary>Photon uses this to agree on a serialization protocol. Either: GpBinaryV16 or GpBinaryV18. Based on enum SerializationProtocol.</summary>
private string protocols = "GpBinaryV16";
public WebSocket(Uri url, string serialization = null)
{
this.mUrl = url;
if (serialization != null)
{
this.protocols = serialization;
}
string protocol = mUrl.Scheme;
if (!protocol.Equals("ws") && !protocol.Equals("wss"))
throw new ArgumentException("Unsupported protocol: " + protocol);
}
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.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;
//this.m_Socket.Log.Level = LogLevel.Debug;
//this.m_Socket.Log.Output += Output;
this.m_Socket.OnClose += SocketOnClose;
m_Socket.OnError += (sender, e) => m_Error = e.Message + (e.Exception == null ? "" : " / " + e.Exception);
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; } }// added by TS
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