3using System.Collections.Generic;
4using System.Threading.Tasks;
6using System.Net.Sockets;
27 private readonly LinkedList<KeyValuePair<IPEndPoint, byte[]>> writeQueue =
new LinkedList<KeyValuePair<IPEndPoint, byte[]>>();
28 private TcpListener tcpListener;
29 private UdpClient udpClient;
30 private IPEndPoint localEndpoint;
31 private IPEndPoint externalEndpoint;
32 private readonly
int backlog;
33 private bool encapsulatePackets =
true;
34 private bool isWriting =
false;
76 LocalPort = LocalPort,
77 ExternalPort = ExternalPort,
82 this.backlog = Backlog;
84 this.tcpListener =
null;
85 this.udpClient =
null;
111 this.tcpListener =
new TcpListener(this.localAddress, this.ports[0].ExternalPort);
112 this.tcpListener.Start(this.backlog);
114 PublicPort = (ushort)((IPEndPoint)this.tcpListener.LocalEndpoint).Port;
116 this.localEndpoint =
new IPEndPoint(this.localAddress, PublicPort);
117 this.externalEndpoint =
new IPEndPoint(this.externalAddress, PublicPort);
119 this.udpClient =
new UdpClient(this.localEndpoint.AddressFamily);
120 this.udpClient.Client.Bind(this.localEndpoint);
124 this.AcceptTcpClients();
125 this.BeginReceiveUdp();
132 this.tcpListener?.Stop();
133 this.tcpListener =
null;
135 this.udpClient?.Dispose();
136 this.udpClient =
null;
143 private async
void AcceptTcpClients()
147 while (!this.disposed && !(this.tcpListener is
null))
155 TcpClient = await this.tcpListener.AcceptTcpClientAsync();
159 catch (InvalidOperationException)
163 this.tcpListener?.Stop();
164 this.tcpListener =
null;
166 this.udpClient?.Dispose();
167 this.udpClient =
null;
172 if (!(TcpClient is
null))
174 PeerConnection Connection =
null;
181 Connection =
new PeerConnection(Client,
this,
182 (IPEndPoint)TcpClient.Client.RemoteEndPoint,
this.encapsulatePackets);
192 if (!(Connection is
null))
193 await Connection.DisposeAsync();
197 catch (SocketException)
201 catch (ObjectDisposedException)
205 catch (NullReferenceException)
266 get => this.encapsulatePackets;
267 set => this.encapsulatePackets = value;
277 Dictionary<ushort, bool> TcpPortMapped, Dictionary<ushort, bool> UdpPortMapped)
283 this.tcpListener =
new TcpListener(this.localAddress, Registration.
LocalPort);
284 this.tcpListener.Start(this.backlog);
286 int i = ((IPEndPoint)this.tcpListener.LocalEndpoint).Port;
288 if (i < 0 || i > ushort.MaxValue ||
289 TcpPortMapped.ContainsKey((ushort)i) ||
290 UdpPortMapped.ContainsKey((ushort)i))
292 this.tcpListener.Stop();
293 this.tcpListener =
null;
299 this.udpClient =
new UdpClient(this.tcpListener.LocalEndpoint.AddressFamily);
300 this.udpClient.Client.Bind((IPEndPoint)this.tcpListener.LocalEndpoint);
302 Registration.LocalPort = (ushort)i;
304 TcpPortMapped.ContainsKey((ushort)Registration.
ExternalPort) ||
305 UdpPortMapped.ContainsKey((ushort)Registration.
ExternalPort))
307 Registration.ExternalPort = Registration.
LocalPort;
312 this.tcpListener.Stop();
313 this.tcpListener =
null;
317 while (this.tcpListener is
null);
319 this.localEndpoint =
new IPEndPoint(this.localAddress, Registration.
LocalPort);
320 this.externalEndpoint =
new IPEndPoint(this.externalAddress, Registration.
ExternalPort);
322 this.AcceptTcpClients();
323 this.BeginReceiveUdp();
351 this.tcpListener?.Stop();
352 this.tcpListener =
null;
354 this.udpClient?.Dispose();
355 this.udpClient =
null;
357 return base.DisposeAsync();
369 throw new IOException(
"Peer-to-peer network not ready.");
372 IPEndPoint RemoteEndPoint2 = RemoteEndPoint;
377 await Client.
ConnectAsync(RemoteEndPoint2.Address, RemoteEndPoint2.Port,
true);
382 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw();
387 Result.StartIdleTimer();
392 private async
void BeginReceiveUdp()
396 while (!this.disposed)
398 UdpReceiveResult Data = await this.udpClient.ReceiveAsync();
419 public async Task
SendUdp(IPEndPoint RemoteEndpoint,
byte[] Datagram)
421 lock (this.writeQueue)
425 this.writeQueue.AddLast(
new KeyValuePair<IPEndPoint,
byte[]>(RemoteEndpoint, Datagram));
429 this.isWriting =
true;
434 while (!this.disposed && !(Datagram is
null))
436 await this.udpClient.SendAsync(Datagram, Datagram.Length, RemoteEndpoint);
440 lock (this.writeQueue)
442 if (!(this.writeQueue.First is
null))
444 KeyValuePair<IPEndPoint, byte[]> Rec = this.writeQueue.First.Value;
445 this.writeQueue.RemoveFirst();
447 RemoteEndpoint = Rec.Key;
448 Datagram = Rec.Value;
452 this.isWriting =
false;
460 lock (this.writeQueue)
462 this.isWriting =
false;
463 this.writeQueue.Clear();
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Implements a binary TCP Client, by encapsulating a TcpClient. It also makes the use of TcpClient safe...
void Bind()
Binds to a TcpClient that was already connected when provided to the constructor.
Task< bool > ConnectAsync(string Host, int Port)
Connects to a host using TCP.
virtual void Dispose()
Disposes of the object. The underlying TcpClient is either disposed directly, or when asynchronous op...
Implements a binary TCP Server. The server adapts to network changes, maintains a list of current con...
const int DefaultC2CConnectionBacklog
Default Client-to-Client Connection backlog (10).
Represents a registraing in an UPnP-compatible Internet Gateway.
ushort LocalPort
Port on local machine.
ushort ExternalPort
Port on external side of gateway.
string ApplicationName
Name of application to be registered.
Manages registration of TCP and UDP ports in an Internet Gateway
Exception Exception
In case State=PeerToPeerNetworkState.Error, this exception object contains details about the error.
IPEndPoint CheckLocalRemoteEndpoint(IPEndPoint RemoteEndPoint)
Checks if a remote endpoint resides in the internal network, and if so, replaces it with the correspo...
bool OnPublicNetwork()
If the machine is on a public network.
PeerToPeerNetworkState State
Current state of the peer-to-peer network object.
Maintains a peer connection
Manages a peer-to-peer network that can receive connections from outside of a NAT-enabled firewall.
const ushort DefaultPort
Default desired port number. (0 = any port number.)
EventHandlerAsync< PeerConnection > OnPeerConnected
Event raised when a new peer has connected.
bool EncapsulatePackets
If packets are to be encapsulated and delivered as ordered units (true), or if fragmentation in the T...
virtual Task PeerConnected(PeerConnection Connection)
Called when a new peer has connected.
PeerToPeerNetwork(string ApplicationName, params ISniffer[] Sniffers)
Manages a peer-to-peer network that can receive connections from outside of a NAT-enabled firewall.
string ApplicationName
Application Name
PeerToPeerNetwork(string ApplicationName, ushort LocalPort, ushort ExternalPort, int Backlog, params ISniffer[] Sniffers)
Manages a peer-to-peer network that can receive connections from outside of a NAT-enabled firewall.
async Task< PeerConnection > ConnectToPeer(IPEndPoint RemoteEndPoint)
Connects to a peer in the peer-to-peer network. If the remote end point resides behind the same firew...
EventHandlerAsync< UdpDatagramEventArgs > OnUdpDatagramReceived
Event raised when an incoming UDP datagram has been received.
PeerToPeerNetwork(string ApplicationName, ushort LocalPort, ushort ExternalPort, params ISniffer[] Sniffers)
Manages a peer-to-peer network that can receive connections from outside of a NAT-enabled firewall.
async Task SendUdp(IPEndPoint RemoteEndpoint, byte[] Datagram)
Sends an UDP datagram to a remote destination.
EventHandlerAsync< UdpDatagramEventArgs > OnUdpDatagramSent
Event raised when an outgoing UDP datagram has been sent.
ushort DesiredLocalPort
Desired local port number. If 0, a dynamic port number will be assigned.
IPEndPoint ExternalEndpoint
External IP Endpoint.
override Task DisposeAsync()
IDisposable.Dispose
ushort DesiredExternalPort
Desired external port number. If 0, a dynamic port number will be assigned.
override async Task Start()
Starts searching for Internet Gateways. Once found, ports will be registered.
const int DefaultBacklog
Default connection backlog (10).
IPEndPoint LocalEndpoint
Local IP Endpoint.
override async Task BeforeRegistration(InternetGatewayRegistration Registration, Dictionary< ushort, bool > TcpPortMapped, Dictionary< ushort, bool > UdpPortMapped)
is called before performing a registration.
Event arguments for UDP Datagram events.
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
PeerToPeerNetworkState
State of Peer-to-peer network.