suck it unity collab
This commit is contained in:
parent
2630db1920
commit
dad44ef0cf
456 changed files with 1861 additions and 128 deletions
37
Assets/Code/Photon/Plugins/PhotonWebSocket/PingHttp.cs
Normal file
37
Assets/Code/Photon/Plugins/PhotonWebSocket/PingHttp.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
#if UNITY_WEBGL
|
||||
|
||||
namespace ExitGames.Client.Photon
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
public class PingHttp : PhotonPing
|
||||
{
|
||||
private WWW webRequest;
|
||||
|
||||
public override bool StartPing(string address)
|
||||
{
|
||||
address = "https://" + address + "/photon/m/?ping&r=" + UnityEngine.Random.Range(0, 10000);
|
||||
Debug.Log("StartPing: " + address);
|
||||
this.webRequest = new WWW(address);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Done()
|
||||
{
|
||||
if (this.webRequest.isDone)
|
||||
{
|
||||
Successful = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
this.webRequest.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
11
Assets/Code/Photon/Plugins/PhotonWebSocket/PingHttp.cs.meta
Normal file
11
Assets/Code/Photon/Plugins/PhotonWebSocket/PingHttp.cs.meta
Normal file
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 88e56dcdd2ef1f942b8f19c74c4cf805
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,22 @@
|
|||
To use WebSockets with the Photon C# library, you need to import this folder into your project.
|
||||
|
||||
SocketWebTcpThread can be used in all cases where the Thread class is available
|
||||
SocketWebTcpCoroutine must be used for WebGL exports and when the Thread class is unavailable
|
||||
|
||||
WebSocket.cs is used in all exports
|
||||
websocket-sharp.dll is used when not exporting to a browser (and in Unity Editor)
|
||||
WebSocket.jslib is used for WebGL exports by Unity (and must be setup accordingly)
|
||||
|
||||
|
||||
A WebGL export from Unity will find and use these files internally.
|
||||
Any other project will have to setup a few things in code:
|
||||
|
||||
Define "WEBSOCKET" for your project to make the SocketWebTcp classes available.
|
||||
To make a connection by WebSocket, setup the PhotonPeer (LoadBalancingPeer, ChatPeer, etc) similar to this:
|
||||
|
||||
Debug.Log("WSS Setup");
|
||||
PhotonPeer.TransportProtocol = ConnectionProtocol.WebSocket; // or WebSocketSecure for a release
|
||||
PhotonPeer.SocketImplementationConfig[ConnectionProtocol.WebSocket] = typeof(SocketWebTcpThread);
|
||||
PhotonPeer.SocketImplementationConfig[ConnectionProtocol.WebSocketSecure] = typeof(SocketWebTcpThread);
|
||||
|
||||
//PhotonPeer.DebugOut = DebugLevel.INFO; // this would show some logs from the SocketWebTcp implementation
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 81339ade5de3e2d419b360cfde8630c1
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,312 @@
|
|||
#if UNITY_WEBGL || UNITY_XBOXONE || WEBSOCKET
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="SocketWebTcpCoroutine.cs" company="Exit Games GmbH">
|
||||
// Copyright (c) Exit Games GmbH. All rights reserved.
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Internal class to encapsulate the network i/o functionality for the realtime libary.
|
||||
// </summary>
|
||||
// <author>developer@exitgames.com</author>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using SupportClassPun = ExitGames.Client.Photon.SupportClass;
|
||||
|
||||
|
||||
namespace ExitGames.Client.Photon
|
||||
{
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
/// <summary>
|
||||
/// Yield Instruction to Wait for real seconds. Very important to keep connection working if Time.TimeScale is altered, we still want accurate network events
|
||||
/// </summary>
|
||||
public sealed class WaitForRealSeconds : CustomYieldInstruction
|
||||
{
|
||||
private readonly float _endTime;
|
||||
|
||||
public override bool keepWaiting
|
||||
{
|
||||
get { return _endTime > Time.realtimeSinceStartup; }
|
||||
}
|
||||
|
||||
public WaitForRealSeconds(float seconds)
|
||||
{
|
||||
_endTime = Time.realtimeSinceStartup + seconds;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Internal class to encapsulate the network i/o functionality for the realtime libary.
|
||||
/// </summary>
|
||||
public class SocketWebTcpCoroutine : IPhotonSocket, IDisposable
|
||||
{
|
||||
private WebSocket sock;
|
||||
|
||||
private GameObject websocketConnectionObject;
|
||||
|
||||
/// <summary>Constructor. Checks if "expected" protocol matches.</summary>
|
||||
public SocketWebTcpCoroutine(PeerBase npeer) : base(npeer)
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.INFO))
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.INFO, "new SocketWebTcpCoroutine(). Server: " + this.ConnectAddress + " protocol: " + this.Protocol);
|
||||
}
|
||||
|
||||
switch (this.Protocol)
|
||||
{
|
||||
case ConnectionProtocol.WebSocket:
|
||||
break;
|
||||
case ConnectionProtocol.WebSocketSecure:
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Protocol '" + this.Protocol + "' not supported by WebSocket");
|
||||
}
|
||||
|
||||
this.PollReceive = false;
|
||||
}
|
||||
|
||||
/// <summary>Connect the websocket (base checks if this was already connected).</summary>
|
||||
public override bool Connect()
|
||||
{
|
||||
bool baseOk = base.Connect();
|
||||
if (!baseOk)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this.State = PhotonSocketState.Connecting;
|
||||
|
||||
|
||||
if (this.websocketConnectionObject != null)
|
||||
{
|
||||
UnityEngine.Object.Destroy(this.websocketConnectionObject);
|
||||
}
|
||||
|
||||
this.websocketConnectionObject = new GameObject("websocketConnectionObject");
|
||||
MonoBehaviour mb = this.websocketConnectionObject.AddComponent<MonoBehaviourExt>();
|
||||
this.websocketConnectionObject.hideFlags = HideFlags.HideInHierarchy;
|
||||
UnityEngine.Object.DontDestroyOnLoad(this.websocketConnectionObject);
|
||||
|
||||
|
||||
this.sock = new WebSocket(new Uri(this.ConnectAddress));
|
||||
// connecting the socket is off-loaded into the coroutine which we start now
|
||||
|
||||
mb.StartCoroutine(this.ReceiveLoop());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Disconnect the websocket (no matter what it does right now).</summary>
|
||||
public override bool Disconnect()
|
||||
{
|
||||
if (this.State == PhotonSocketState.Disconnecting || this.State == PhotonSocketState.Disconnected)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.ReportDebugOfLevel(DebugLevel.INFO))
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.INFO, "SocketWebTcpCoroutine.Disconnect()");
|
||||
}
|
||||
|
||||
this.State = PhotonSocketState.Disconnecting;
|
||||
if (this.sock != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.sock.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
this.sock = null;
|
||||
}
|
||||
|
||||
if (this.websocketConnectionObject != null)
|
||||
{
|
||||
UnityEngine.Object.Destroy(this.websocketConnectionObject);
|
||||
}
|
||||
|
||||
this.State = PhotonSocketState.Disconnected;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Calls Disconnect.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.Disconnect();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Used by TPeer to send.</summary>
|
||||
public override PhotonSocketError Send(byte[] data, int length)
|
||||
{
|
||||
if (this.State != PhotonSocketState.Connected)
|
||||
{
|
||||
return PhotonSocketError.Skipped;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.ALL))
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ALL, "Sending: " + SupportClassPun.ByteArrayToString(data));
|
||||
}
|
||||
|
||||
this.sock.Send(data);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ERROR, "Cannot send to: " + this.ConnectAddress + ". " + e.Message);
|
||||
|
||||
if (this.State == PhotonSocketState.Connected)
|
||||
{
|
||||
this.HandleException(StatusCode.Exception);
|
||||
}
|
||||
return PhotonSocketError.Exception;
|
||||
}
|
||||
|
||||
return PhotonSocketError.Success;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Not used currently.</summary>
|
||||
public override PhotonSocketError Receive(out byte[] data)
|
||||
{
|
||||
data = null;
|
||||
return PhotonSocketError.NoData;
|
||||
}
|
||||
|
||||
/// <summary>Used by TPeer to receive.</summary>
|
||||
public IEnumerator ReceiveLoop()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.sock.Connect();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (this.State != PhotonSocketState.Disconnecting && this.State != PhotonSocketState.Disconnected)
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.ERROR))
|
||||
{
|
||||
this.EnqueueDebugReturn(DebugLevel.ERROR, "Receive issue. State: " + this.State + ". Server: '" + this.ConnectAddress + "' Exception: " + e);
|
||||
}
|
||||
|
||||
this.HandleException(StatusCode.ExceptionOnReceive);
|
||||
}
|
||||
}
|
||||
|
||||
while (this.State == PhotonSocketState.Connecting && this.sock != null && !this.sock.Connected && this.sock.Error == null)
|
||||
{
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
yield return new WaitForRealSeconds(0.02f);
|
||||
#else
|
||||
float waittime = Time.realtimeSinceStartup + 0.2f;
|
||||
while (Time.realtimeSinceStartup < waittime) yield return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (this.sock == null || this.sock.Error != null)
|
||||
{
|
||||
if (this.State != PhotonSocketState.Disconnecting && this.State != PhotonSocketState.Disconnected)
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ERROR, "Exiting receive thread. Server: " + this.ConnectAddress + " Error: " + ((this.sock!=null)?this.sock.Error:"socket==null"));
|
||||
this.HandleException(StatusCode.ExceptionOnConnect);
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
// connected
|
||||
this.State = PhotonSocketState.Connected;
|
||||
this.peerBase.OnConnect();
|
||||
|
||||
|
||||
byte[] inBuff = null;
|
||||
|
||||
// receiving
|
||||
while (this.State == PhotonSocketState.Connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.sock.Error != null)
|
||||
{
|
||||
if (this.State != PhotonSocketState.Disconnecting && this.State != PhotonSocketState.Disconnected)
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ERROR, "Exiting receive thread (inside loop). Server: " + this.ConnectAddress + " Error: " + this.sock.Error);
|
||||
this.HandleException(StatusCode.ExceptionOnReceive);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
inBuff = this.sock.Recv();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (this.State != PhotonSocketState.Disconnecting && this.State != PhotonSocketState.Disconnected)
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.ERROR))
|
||||
{
|
||||
this.EnqueueDebugReturn(DebugLevel.ERROR, "Receive issue. State: " + this.State + ". Server: '" + this.ConnectAddress + "' Exception: " + e);
|
||||
}
|
||||
|
||||
this.HandleException(StatusCode.ExceptionOnReceive);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (inBuff == null || inBuff.Length == 0)
|
||||
{
|
||||
// nothing received. wait a bit, try again
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
yield return new WaitForRealSeconds(0.02f);
|
||||
#else
|
||||
float waittime = Time.realtimeSinceStartup + 0.02f;
|
||||
while (Time.realtimeSinceStartup < waittime) yield return 0;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
if (inBuff.Length < 0)
|
||||
{
|
||||
// got disconnected (from remote or net)
|
||||
if (this.State != PhotonSocketState.Disconnecting && this.State != PhotonSocketState.Disconnected)
|
||||
{
|
||||
this.HandleException(StatusCode.DisconnectByServer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.ALL))
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ALL, "TCP << " + inBuff.Length + " = " + SupportClassPun.ByteArrayToString(inBuff));
|
||||
}
|
||||
|
||||
this.HandleReceivedDatagram(inBuff, inBuff.Length, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (this.State != PhotonSocketState.Disconnecting && this.State != PhotonSocketState.Disconnected)
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.ERROR))
|
||||
{
|
||||
this.EnqueueDebugReturn(DebugLevel.ERROR, "Receive issue. State: " + this.State + ". Server: '" + this.ConnectAddress + "' Exception: " + e);
|
||||
}
|
||||
|
||||
this.HandleException(StatusCode.ExceptionOnReceive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
internal class MonoBehaviourExt : MonoBehaviour { }
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 02e6576dec44f344eb5d58b9dfe5bdc0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
268
Assets/Code/Photon/Plugins/PhotonWebSocket/SocketWebTcpThread.cs
Normal file
268
Assets/Code/Photon/Plugins/PhotonWebSocket/SocketWebTcpThread.cs
Normal file
|
@ -0,0 +1,268 @@
|
|||
#if WEBSOCKET
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="SocketWebTcpThread.cs" company="Exit Games GmbH">
|
||||
// Copyright (c) Exit Games GmbH. All rights reserved.
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Internal class to encapsulate the network i/o functionality for the realtime libary.
|
||||
// </summary>
|
||||
// <author>developer@photonengine.com</author>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Security;
|
||||
using System.Threading;
|
||||
|
||||
|
||||
namespace ExitGames.Client.Photon
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal class to encapsulate the network i/o functionality for the realtime libary.
|
||||
/// </summary>
|
||||
public class SocketWebTcpThread : IPhotonSocket, IDisposable
|
||||
{
|
||||
private WebSocket sock;
|
||||
|
||||
|
||||
/// <summary>Constructor. Checks if "expected" protocol matches.</summary>
|
||||
public SocketWebTcpThread(PeerBase npeer) : base(npeer)
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.INFO))
|
||||
{
|
||||
this.EnqueueDebugReturn(DebugLevel.INFO, "new SocketWebTcpThread(). Server: " + this.ConnectAddress + " protocol: " + this.Protocol+ " State: " + this.State);
|
||||
}
|
||||
|
||||
switch (this.Protocol)
|
||||
{
|
||||
case ConnectionProtocol.WebSocket:
|
||||
break;
|
||||
case ConnectionProtocol.WebSocketSecure:
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Protocol '" + this.Protocol + "' not supported by WebSocket");
|
||||
}
|
||||
|
||||
this.PollReceive = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Connect the websocket (base checks if this was already connected).</summary>
|
||||
public override bool Connect()
|
||||
{
|
||||
bool baseOk = base.Connect();
|
||||
if (!baseOk)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this.State = PhotonSocketState.Connecting;
|
||||
|
||||
Thread dns = new Thread(this.DnsAndConnect);
|
||||
dns.Name = "photon dns thread";
|
||||
dns.IsBackground = true;
|
||||
dns.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Internally used by this class to resolve the hostname to IP.</summary>
|
||||
internal void DnsAndConnect()
|
||||
{
|
||||
try
|
||||
{
|
||||
IPAddress ipAddress = IPhotonSocket.GetIpAddress(this.ServerAddress);
|
||||
if (ipAddress == null)
|
||||
{
|
||||
throw new ArgumentException("DNS failed to resolve for address: " + this.ServerAddress);
|
||||
}
|
||||
|
||||
this.AddressResolvedAsIpv6 = ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6;
|
||||
|
||||
|
||||
if (this.State != PhotonSocketState.Connecting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.sock = new WebSocket(new Uri(this.ConnectAddress));
|
||||
this.sock.Connect();
|
||||
|
||||
while (this.sock != null && !this.sock.Connected && this.sock.Error == null)
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
}
|
||||
|
||||
if (this.sock.Error != null)
|
||||
{
|
||||
this.EnqueueDebugReturn(DebugLevel.ERROR, "Exiting receive thread. Server: " + this.ConnectAddress + " Error: " + this.sock.Error);
|
||||
this.HandleException(StatusCode.ExceptionOnConnect);
|
||||
return;
|
||||
}
|
||||
|
||||
this.State = PhotonSocketState.Connected;
|
||||
this.peerBase.OnConnect();
|
||||
}
|
||||
catch (SecurityException se)
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.ERROR))
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ERROR, "Connect() to '" + this.ConnectAddress + "' failed: " + se.ToString());
|
||||
}
|
||||
|
||||
this.HandleException(StatusCode.SecurityExceptionOnConnect);
|
||||
return;
|
||||
}
|
||||
catch (Exception se)
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.ERROR))
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ERROR, "Connect() to '" + this.ConnectAddress + "' failed: " + se.ToString());
|
||||
}
|
||||
|
||||
this.HandleException(StatusCode.ExceptionOnConnect);
|
||||
return;
|
||||
}
|
||||
|
||||
Thread run = new Thread(new ThreadStart(this.ReceiveLoop));
|
||||
run.Name = "photon receive thread";
|
||||
run.IsBackground = true;
|
||||
run.Start();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Disconnect the websocket (no matter what it does right now).</summary>
|
||||
public override bool Disconnect()
|
||||
{
|
||||
if (this.State == PhotonSocketState.Disconnecting || this.State == PhotonSocketState.Disconnected)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.ReportDebugOfLevel(DebugLevel.INFO))
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.INFO, "SocketWebTcpThread.Disconnect()");
|
||||
}
|
||||
|
||||
this.State = PhotonSocketState.Disconnecting;
|
||||
if (this.sock != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.sock.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
this.sock = null;
|
||||
}
|
||||
|
||||
this.State = PhotonSocketState.Disconnected;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Calls Disconnect.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.Disconnect();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Used by TPeer to send.</summary>
|
||||
public override PhotonSocketError Send(byte[] data, int length)
|
||||
{
|
||||
if (this.State != PhotonSocketState.Connected)
|
||||
{
|
||||
return PhotonSocketError.Skipped;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.ALL))
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ALL, "Sending: " + SupportClass.ByteArrayToString(data));
|
||||
}
|
||||
|
||||
this.sock.Send(data);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ERROR, "Cannot send to: " + this.ConnectAddress + ". " + e.Message);
|
||||
|
||||
if (this.State == PhotonSocketState.Connected)
|
||||
{
|
||||
this.HandleException(StatusCode.Exception);
|
||||
}
|
||||
return PhotonSocketError.Exception;
|
||||
}
|
||||
|
||||
return PhotonSocketError.Success;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Not used currently.</summary>
|
||||
public override PhotonSocketError Receive(out byte[] data)
|
||||
{
|
||||
data = null;
|
||||
return PhotonSocketError.NoData;
|
||||
}
|
||||
|
||||
/// <summary>Used by TPeer to receive.</summary>
|
||||
public void ReceiveLoop()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (this.State == PhotonSocketState.Connected)
|
||||
{
|
||||
if (this.sock.Error != null)
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ERROR, "Exiting receive thread (inside loop). Server: " + this.ConnectAddress + " Error: " + this.sock.Error);
|
||||
this.HandleException(StatusCode.ExceptionOnReceive);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
byte[] inBuff = this.sock.Recv();
|
||||
if (inBuff == null || inBuff.Length == 0)
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
continue;
|
||||
}
|
||||
if (inBuff.Length < 0)
|
||||
{
|
||||
// got disconnected (from remote or net)
|
||||
if (this.State != PhotonSocketState.Disconnecting && this.State != PhotonSocketState.Disconnected)
|
||||
{
|
||||
this.HandleException(StatusCode.DisconnectByServer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.ReportDebugOfLevel(DebugLevel.ALL))
|
||||
{
|
||||
this.Listener.DebugReturn(DebugLevel.ALL, "TCP << " + inBuff.Length + " = " + SupportClass.ByteArrayToString(inBuff));
|
||||
}
|
||||
|
||||
this.HandleReceivedDatagram(inBuff, inBuff.Length, false);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (this.State != PhotonSocketState.Disconnecting && this.State != PhotonSocketState.Disconnected)
|
||||
{
|
||||
if (this.ReportDebugOfLevel(DebugLevel.ERROR))
|
||||
{
|
||||
this.EnqueueDebugReturn(DebugLevel.ERROR, "Receive issue. State: " + this.State + ". Server: '" + this.ConnectAddress + "' Exception: " + e);
|
||||
}
|
||||
|
||||
this.HandleException(StatusCode.ExceptionOnReceive);
|
||||
}
|
||||
}
|
||||
|
||||
this.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f621e51e5c8aead49bd766c4b959a859
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ff7e276bdb10f1a4f9bdbfeaafadf2f2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,155 @@
|
|||
#if UNITY_WEBGL || UNITY_XBOXONE || WEBSOCKET
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||
using System.Runtime.InteropServices;
|
||||
#else
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Authentication;
|
||||
#endif
|
||||
|
||||
|
||||
public class WebSocket
|
||||
{
|
||||
private Uri mUrl;
|
||||
|
||||
public WebSocket(Uri url)
|
||||
{
|
||||
mUrl = url;
|
||||
|
||||
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);
|
||||
|
||||
[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());
|
||||
|
||||
//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[] { "GpBinaryV16" });// modified by TS
|
||||
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);
|
||||
m_Socket.ConnectAsync();
|
||||
}
|
||||
|
||||
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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cfe55c94da5ac634db8d4ca3d1891173
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,116 @@
|
|||
var LibraryWebSockets = {
|
||||
$webSocketInstances: [],
|
||||
|
||||
SocketCreate: function(url)
|
||||
{
|
||||
var str = Pointer_stringify(url);
|
||||
var socket = {
|
||||
socket: new WebSocket(str, ['GpBinaryV16']),
|
||||
buffer: new Uint8Array(0),
|
||||
error: null,
|
||||
messages: []
|
||||
}
|
||||
socket.socket.binaryType = 'arraybuffer';
|
||||
socket.socket.onmessage = function (e) {
|
||||
// if (e.data instanceof Blob)
|
||||
// {
|
||||
// var reader = new FileReader();
|
||||
// reader.addEventListener("loadend", function() {
|
||||
// var array = new Uint8Array(reader.result);
|
||||
// socket.messages.push(array);
|
||||
// });
|
||||
// reader.readAsArrayBuffer(e.data);
|
||||
// }
|
||||
if (e.data instanceof ArrayBuffer)
|
||||
{
|
||||
var array = new Uint8Array(e.data);
|
||||
socket.messages.push(array);
|
||||
}
|
||||
};
|
||||
socket.socket.onclose = function (e) {
|
||||
if (e.code != 1000)
|
||||
{
|
||||
if (e.reason != null && e.reason.length > 0)
|
||||
socket.error = e.reason;
|
||||
else
|
||||
{
|
||||
switch (e.code)
|
||||
{
|
||||
case 1001:
|
||||
socket.error = "Endpoint going away.";
|
||||
break;
|
||||
case 1002:
|
||||
socket.error = "Protocol error.";
|
||||
break;
|
||||
case 1003:
|
||||
socket.error = "Unsupported message.";
|
||||
break;
|
||||
case 1005:
|
||||
socket.error = "No status.";
|
||||
break;
|
||||
case 1006:
|
||||
socket.error = "Abnormal disconnection.";
|
||||
break;
|
||||
case 1009:
|
||||
socket.error = "Data frame too large.";
|
||||
break;
|
||||
default:
|
||||
socket.error = "Error "+e.code;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var instance = webSocketInstances.push(socket) - 1;
|
||||
return instance;
|
||||
},
|
||||
|
||||
SocketState: function (socketInstance)
|
||||
{
|
||||
var socket = webSocketInstances[socketInstance];
|
||||
return socket.socket.readyState;
|
||||
},
|
||||
|
||||
SocketError: function (socketInstance, ptr, bufsize)
|
||||
{
|
||||
var socket = webSocketInstances[socketInstance];
|
||||
if (socket.error == null)
|
||||
return 0;
|
||||
var str = socket.error.slice(0, Math.max(0, bufsize - 1));
|
||||
writeStringToMemory(str, ptr, false);
|
||||
return 1;
|
||||
},
|
||||
|
||||
SocketSend: function (socketInstance, ptr, length)
|
||||
{
|
||||
var socket = webSocketInstances[socketInstance];
|
||||
socket.socket.send (HEAPU8.buffer.slice(ptr, ptr+length));
|
||||
},
|
||||
|
||||
SocketRecvLength: function(socketInstance)
|
||||
{
|
||||
var socket = webSocketInstances[socketInstance];
|
||||
if (socket.messages.length == 0)
|
||||
return 0;
|
||||
return socket.messages[0].length;
|
||||
},
|
||||
|
||||
SocketRecv: function (socketInstance, ptr, length)
|
||||
{
|
||||
var socket = webSocketInstances[socketInstance];
|
||||
if (socket.messages.length == 0)
|
||||
return 0;
|
||||
if (socket.messages[0].length > length)
|
||||
return 0;
|
||||
HEAPU8.set(socket.messages[0], ptr);
|
||||
socket.messages = socket.messages.slice(1);
|
||||
},
|
||||
|
||||
SocketClose: function (socketInstance)
|
||||
{
|
||||
var socket = webSocketInstances[socketInstance];
|
||||
socket.socket.close();
|
||||
}
|
||||
};
|
||||
|
||||
autoAddDeps(LibraryWebSockets, '$webSocketInstances');
|
||||
mergeInto(LibraryManager.library, LibraryWebSockets);
|
|
@ -0,0 +1,34 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 21d8d0d3e9f68ae43975534c13f23964
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,3 @@
|
|||
websocket-sharp.dll built from https://github.com/sta/websocket-sharp.git, commit 869dfb09778de51081b0ae64bd2c3217cffe0699 on Aug 24, 2016.
|
||||
|
||||
websocket-sharp is provided under The MIT License as mentioned here: https://github.com/sta/websocket-sharp#license
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 004b47cc08839884586e6b91d620b418
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,30 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0fb606431450aa343839e85c42dd9660
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue