📄 p2psessionfinder.cs
字号:
namespace Imps.Client.Core.P2P.ICE
{
using Imps.Client;
using Imps.Client.Core;
using Imps.Client.Core.P2P.FileTransportor;
using Imps.Client.Utils;
using NCindy;
using NCindy.Packet;
using NCindy.Session.AIO;
using NCindy.Util.Logging;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
public class P2PSessionFinder
{
private readonly List<IPEndPoint> allRemoteEndpoints;
private bool canStop;
private AsyncUdpSession innerSession;
private Socket innerSocket;
private bool isAckRecevied;
private bool isRemotePeerValid;
private readonly bool isSender;
private readonly StunNetType localNetType;
private readonly Peer localPeer;
private User localUser;
private static readonly ILogger log = LogFactory.CreateLogger(MethodBase.GetCurrentMethod().ReflectedType);
private const byte MAX_RETRY_TIMES = 40;
private readonly Peer remotePeer;
private readonly int stunPort;
private readonly string stunServer;
private const int WAIT_TIME = 100;
public event EventHandler<SessionEventArgs> P2PSessionFound;
public P2PSessionFinder(long remoteSid, bool isSender) : this(P2PManager.Instace.LocalUser, new Peer(remoteSid), P2PManager.Instace.StunHost, P2PManager.Instace.StunPort)
{
this.isSender = isSender;
}
protected P2PSessionFinder(User localUser, Peer remotePeer, string stunServer, int stunPort)
{
this.allRemoteEndpoints = new List<IPEndPoint>();
ClientLogger.WriteGeneral(string.Format("Stun server - {0}:{1}", stunServer, stunPort));
this.localUser = localUser;
this.stunPort = stunPort;
this.stunServer = stunServer;
this.localPeer = new Peer(localUser.Sid);
this.localPeer.Mode = TransportMode.P2PV3;
this.remotePeer = remotePeer;
this.localNetType = StunNetType.OpenInternet;
}
private bool CheckACKObject(object o)
{
if (!object.Equals(this.localPeer, o))
{
return false;
}
if (log.IsInfoEnabled)
{
log.Info("Enter Send response stage.");
}
return true;
}
private bool CheckReceivedObject(object o)
{
if (!object.Equals(this.remotePeer, o))
{
return false;
}
if (log.IsInfoEnabled)
{
log.Info("Enter Send ack stage.");
}
return true;
}
private bool CheckRemotePeerObject(object o)
{
return this.CheckReceivedObject(o);
}
public AllEndPoints GetLocalEndpoints()
{
try
{
this.innerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
this.innerSocket.Bind(new IPEndPoint(IPAddress.Any, 0));
IPEndPoint point = StunClient.GetPublicEndpoint(this.innerSocket, this.stunServer, this.stunPort);
this.innerSession = new AsyncUdpSession(this.innerSocket);
List<IPEndPoint> localNetworkInterfaceEndpoints = GetLocalNetworkInterfaceEndpoints(this.innerSession.LocalPort);
AllEndPoints points = new AllEndPoints();
if (point != null)
{
ClientLogger.WriteGeneral("检测NAT映射地址成功");
}
else
{
ClientLogger.WriteGeneral("检测NAT映射地址失败");
}
points.OuterEndPoint = point;
points.InnerEndPoints = localNetworkInterfaceEndpoints;
return points;
}
catch (Exception exception)
{
ClientLogger.WriteException("GetLocalEndpoints失败", exception);
}
return null;
}
public static List<IPEndPoint> GetLocalNetworkInterfaceEndpoints(int localPort)
{
NetworkInterface[] allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
List<IPEndPoint> list = new List<IPEndPoint>();
foreach (NetworkInterface interface2 in allNetworkInterfaces)
{
if ((interface2.get_NetworkInterfaceType() != 0x18) && (interface2.get_NetworkInterfaceType() != 1))
{
try
{
using (IEnumerator<UnicastIPAddressInformation> enumerator = interface2.GetIPProperties().get_UnicastAddresses().GetEnumerator())
{
while (enumerator.MoveNext())
{
UnicastIPAddressInformation information = enumerator.get_Current();
if (information.get_Address().AddressFamily == AddressFamily.InterNetwork)
{
list.Add(new IPEndPoint(information.get_Address(), localPort));
}
}
}
}
catch
{
}
}
}
return list;
}
private void OnObjectReceived(object sender, SessionEventArgs e)
{
if (this.CheckRemotePeerObject(e.Obj))
{
this.isRemotePeerValid = true;
}
else if (this.CheckACKObject(e.Obj))
{
this.isAckRecevied = true;
}
if (log.IsInfoEnabled)
{
log.Info(string.Format("Receive content: IsRemotePeerValid = {0}, IsAckRecevied = {1}, isSender={2}", this.isRemotePeerValid, this.isAckRecevied, this.isSender));
}
if ((this.isRemotePeerValid && !this.isSender) || (this.isRemotePeerValid && this.isAckRecevied))
{
if (log.IsInfoEnabled)
{
log.Info("P2P session OK!");
}
this.CanStop = true;
e.Session.ObjectReceived -= new EventHandler<SessionEventArgs>(this, (IntPtr) this.OnObjectReceived);
}
}
private void SendAckResponse()
{
this.SendAckResponse(string.Format("P2PV3:{0}", this.remotePeer.PeerToken));
this.SendAckResponse(this.remotePeer);
}
private void SendAckResponse(object obj)
{
List<IPEndPoint> list;
AsyncUdpSession innerSession = this.innerSession;
lock (this.allRemoteEndpoints)
{
list = new List<IPEndPoint>(this.allRemoteEndpoints);
}
for (int i = 0; i < 3; i++)
{
List<IPEndPoint>.Enumerator enumerator = list.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
IPEndPoint point = enumerator.get_Current();
try
{
lock (this.innerSession)
{
innerSession.RemoteEndPoint = point;
innerSession.Send(obj).Complete();
innerSession.Send("P2PV3:" + this.localPeer.PeerToken).Complete();
innerSession.Send(this.localPeer).Complete();
}
if (log.IsInfoEnabled)
{
log.Info(string.Format("Send Ack to {0}, content: {1}", point, this.remotePeer.PeerToken));
}
Thread.Sleep(100);
continue;
}
catch
{
continue;
}
}
}
finally
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -