193 lines
4.6 KiB
C#
193 lines
4.6 KiB
C#
using System;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Security;
|
|
using System.Threading;
|
|
|
|
namespace ExitGames.Client.Photon
|
|
{
|
|
internal class SocketUdp : IPhotonSocket, IDisposable
|
|
{
|
|
private Socket sock;
|
|
|
|
private readonly object syncer = new object();
|
|
|
|
public SocketUdp(PeerBase npeer)
|
|
: base(npeer)
|
|
{
|
|
if (ReportDebugOfLevel(DebugLevel.ALL))
|
|
{
|
|
base.Listener.DebugReturn(DebugLevel.ALL, "CSharpSocket: UDP, Unity3d.");
|
|
}
|
|
base.Protocol = ConnectionProtocol.Udp;
|
|
PollReceive = false;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
base.State = PhotonSocketState.Disconnecting;
|
|
if (sock != null)
|
|
{
|
|
try
|
|
{
|
|
if (sock.Connected)
|
|
{
|
|
sock.Close();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
EnqueueDebugReturn(DebugLevel.INFO, "Exception in Dispose(): " + ex);
|
|
}
|
|
}
|
|
sock = null;
|
|
base.State = PhotonSocketState.Disconnected;
|
|
}
|
|
|
|
public override bool Connect()
|
|
{
|
|
lock (syncer)
|
|
{
|
|
if (!base.Connect())
|
|
{
|
|
return false;
|
|
}
|
|
base.State = PhotonSocketState.Connecting;
|
|
Thread thread = new Thread(DnsAndConnect);
|
|
thread.Name = "photon dns thread";
|
|
thread.IsBackground = true;
|
|
thread.Start();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public override bool Disconnect()
|
|
{
|
|
if (ReportDebugOfLevel(DebugLevel.INFO))
|
|
{
|
|
EnqueueDebugReturn(DebugLevel.INFO, "CSharpSocket.Disconnect()");
|
|
}
|
|
base.State = PhotonSocketState.Disconnecting;
|
|
lock (syncer)
|
|
{
|
|
if (sock != null)
|
|
{
|
|
try
|
|
{
|
|
sock.Close();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
EnqueueDebugReturn(DebugLevel.INFO, "Exception in Disconnect(): " + ex);
|
|
}
|
|
sock = null;
|
|
}
|
|
}
|
|
base.State = PhotonSocketState.Disconnected;
|
|
return true;
|
|
}
|
|
|
|
public override PhotonSocketError Send(byte[] data, int length)
|
|
{
|
|
lock (syncer)
|
|
{
|
|
if (sock == null || !sock.Connected)
|
|
{
|
|
return PhotonSocketError.Skipped;
|
|
}
|
|
try
|
|
{
|
|
sock.Send(data, 0, length, SocketFlags.None);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (ReportDebugOfLevel(DebugLevel.ERROR))
|
|
{
|
|
EnqueueDebugReturn(DebugLevel.ERROR, "Cannot send to: " + base.ServerAddress + ". " + ex.Message);
|
|
}
|
|
return PhotonSocketError.Exception;
|
|
}
|
|
}
|
|
return PhotonSocketError.Success;
|
|
}
|
|
|
|
public override PhotonSocketError Receive(out byte[] data)
|
|
{
|
|
data = null;
|
|
return PhotonSocketError.NoData;
|
|
}
|
|
|
|
internal void DnsAndConnect()
|
|
{
|
|
IPAddress iPAddress = null;
|
|
try
|
|
{
|
|
iPAddress = IPhotonSocket.GetIpAddress(base.ServerAddress);
|
|
if (iPAddress == null)
|
|
{
|
|
throw new ArgumentException("Invalid IPAddress. Address: " + base.ServerAddress);
|
|
}
|
|
lock (syncer)
|
|
{
|
|
if (base.State == PhotonSocketState.Disconnecting || base.State == PhotonSocketState.Disconnected)
|
|
{
|
|
return;
|
|
}
|
|
sock = new Socket(iPAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
|
|
sock.Connect(iPAddress, base.ServerPort);
|
|
base.AddressResolvedAsIpv6 = IsIpv6SimpleCheck(iPAddress);
|
|
base.State = PhotonSocketState.Connected;
|
|
peerBase.OnConnect();
|
|
}
|
|
}
|
|
catch (SecurityException ex)
|
|
{
|
|
if (ReportDebugOfLevel(DebugLevel.ERROR))
|
|
{
|
|
base.Listener.DebugReturn(DebugLevel.ERROR, "Connect() to '" + base.ServerAddress + "' (" + ((iPAddress != null) ? iPAddress.AddressFamily.ToString() : string.Empty) + ") failed: " + ex.ToString());
|
|
}
|
|
HandleException(StatusCode.SecurityExceptionOnConnect);
|
|
return;
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
if (ReportDebugOfLevel(DebugLevel.ERROR))
|
|
{
|
|
base.Listener.DebugReturn(DebugLevel.ERROR, "Connect() to '" + base.ServerAddress + "' (" + ((iPAddress != null) ? iPAddress.AddressFamily.ToString() : string.Empty) + ") failed: " + ex2.ToString());
|
|
}
|
|
HandleException(StatusCode.ExceptionOnConnect);
|
|
return;
|
|
}
|
|
Thread thread = new Thread(ReceiveLoop);
|
|
thread.Name = "photon receive thread";
|
|
thread.IsBackground = true;
|
|
thread.Start();
|
|
}
|
|
|
|
public void ReceiveLoop()
|
|
{
|
|
byte[] array = new byte[base.MTU];
|
|
while (base.State == PhotonSocketState.Connected)
|
|
{
|
|
try
|
|
{
|
|
int length = sock.Receive(array);
|
|
HandleReceivedDatagram(array, length, true);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (base.State != PhotonSocketState.Disconnecting && base.State != PhotonSocketState.Disconnected)
|
|
{
|
|
if (ReportDebugOfLevel(DebugLevel.ERROR))
|
|
{
|
|
EnqueueDebugReturn(DebugLevel.ERROR, string.Concat("Receive issue. State: ", base.State, ". Server: '", base.ServerAddress, "' Exception: ", ex));
|
|
}
|
|
HandleException(StatusCode.ExceptionOnReceive);
|
|
}
|
|
}
|
|
}
|
|
Disconnect();
|
|
}
|
|
}
|
|
}
|