Files
2026-02-21 16:45:37 +08:00

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();
}
}
}