4using System.Threading.Tasks;
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;
78 LocalPort = LocalPort,
79 ExternalPort = ExternalPort,
85 this.backlog = Backlog;
87 this.tcpListener =
null;
88 this.udpClient =
null;
115 this.tcpListener =
new TcpListener(this.localAddress, this.ports[0].ExternalPort);
116 this.tcpListener.Start(this.backlog);
118 PublicPort = (ushort)((IPEndPoint)this.tcpListener.LocalEndpoint).Port;
120 this.localEndpoint =
new IPEndPoint(this.localAddress, PublicPort);
121 this.externalEndpoint =
new IPEndPoint(this.externalAddress, PublicPort);
123 this.udpClient =
new UdpClient(this.localEndpoint.AddressFamily);
124 this.udpClient.Client.Bind(this.localEndpoint);
128 this.AcceptTcpClients();
129 this.BeginReceiveUdp();
136 this.tcpListener?.Stop();
137 this.tcpListener =
null;
139 this.udpClient?.Dispose();
140 this.udpClient =
null;
147 private async
void AcceptTcpClients()
151 while (!this.disposed && !(this.tcpListener is
null))
159 TcpClient = await this.tcpListener.AcceptTcpClientAsync();
163 catch (InvalidOperationException)
167 this.tcpListener?.Stop();
168 this.tcpListener =
null;
170 this.udpClient?.Dispose();
171 this.udpClient =
null;
176 if (!(TcpClient is
null))
178 PeerConnection Connection =
null;
185 Connection =
new PeerConnection(Client,
this,
186 (IPEndPoint)TcpClient.Client.RemoteEndPoint,
this.encapsulatePackets);
196 if (!(Connection is
null))
197 await Connection.DisposeAsync();
201 catch (SocketException)
205 catch (ObjectDisposedException)
209 catch (NullReferenceException)
269 get => this.encapsulatePackets;
270 set => this.encapsulatePackets = value;
280 Dictionary<ushort, bool> TcpPortMapped, Dictionary<ushort, bool> UdpPortMapped)
286 this.tcpListener =
new TcpListener(this.localAddress, Registration.
LocalPort);
287 this.tcpListener.Start(this.backlog);
289 int i = ((IPEndPoint)this.tcpListener.LocalEndpoint).Port;
291 if (i < 0 || i > ushort.MaxValue ||
292 TcpPortMapped.ContainsKey((ushort)i) ||
293 UdpPortMapped.ContainsKey((ushort)i))
295 this.tcpListener.Stop();
296 this.tcpListener =
null;
302 this.udpClient =
new UdpClient(this.tcpListener.LocalEndpoint.AddressFamily);
303 this.udpClient.Client.Bind((IPEndPoint)this.tcpListener.LocalEndpoint);
305 Registration.LocalPort = (ushort)i;
307 TcpPortMapped.ContainsKey((ushort)Registration.
ExternalPort) ||
308 UdpPortMapped.ContainsKey((ushort)Registration.
ExternalPort))
310 Registration.ExternalPort = Registration.
LocalPort;
315 this.tcpListener.Stop();
316 this.tcpListener =
null;
320 while (this.tcpListener is
null);
322 this.localEndpoint =
new IPEndPoint(this.localAddress, Registration.
LocalPort);
323 this.externalEndpoint =
new IPEndPoint(this.externalAddress, Registration.
ExternalPort);
325 this.AcceptTcpClients();
326 this.BeginReceiveUdp();
354 this.tcpListener?.Stop();
355 this.tcpListener =
null;
357 this.udpClient?.Dispose();
358 this.udpClient =
null;
360 return base.DisposeAsync();
372 throw new IOException(
"Peer-to-peer network not ready.");
375 IPEndPoint RemoteEndPoint2 = RemoteEndPoint;
380 await Client.
ConnectAsync(RemoteEndPoint2.Address, RemoteEndPoint2.Port,
true);
385 System.
Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw();
390 Result.StartIdleTimer();
395 private async
void BeginReceiveUdp()
399 while (!this.disposed)
401 UdpReceiveResult Data = await this.udpClient.ReceiveAsync();
423 public async Task
SendUdp(IPEndPoint RemoteEndpoint,
byte[] Datagram)
425 lock (this.writeQueue)
429 this.writeQueue.AddLast(
new KeyValuePair<IPEndPoint,
byte[]>(RemoteEndpoint, Datagram));
433 this.isWriting =
true;
438 while (!this.disposed && !(Datagram is
null))
440 await this.udpClient.SendAsync(Datagram, Datagram.Length, RemoteEndpoint);
444 lock (this.writeQueue)
446 if (!(this.writeQueue.First is
null))
448 KeyValuePair<IPEndPoint, byte[]> Rec = this.writeQueue.First.Value;
449 this.writeQueue.RemoveFirst();
451 RemoteEndpoint = Rec.Key;
452 Datagram = Rec.Value;
456 this.isWriting =
false;
464 lock (this.writeQueue)
466 this.isWriting =
false;
467 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.
virtual Task DisposeAsync()
Disposes of the object asynchronously. The underlying TcpClient is either disposed directly,...
Task< bool > ConnectAsync(string Host, int Port)
Connects to a host using TCP.
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.