From 1cad93c276fef512d6d4731d32704e05433aed01 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 29 Jul 2019 15:26:17 +0200 Subject: Use System.Net abstractions instead of raw socket --- Emby.Server.Implementations/Net/SocketFactory.cs | 42 ------------------------ 1 file changed, 42 deletions(-) (limited to 'Emby.Server.Implementations/Net/SocketFactory.cs') diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index 42ffa4e22..cb53ce50c 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -2,54 +2,12 @@ using System; using System.IO; using System.Net; using System.Net.Sockets; -using Emby.Server.Implementations.Networking; using MediaBrowser.Model.Net; namespace Emby.Server.Implementations.Net { public class SocketFactory : ISocketFactory { - // THIS IS A LINKED FILE - SHARED AMONGST MULTIPLE PLATFORMS - // Be careful to check any changes compile and work for all platform projects it is shared in. - - // Not entirely happy with this. Would have liked to have done something more generic/reusable, - // but that wasn't really the point so kept to YAGNI principal for now, even if the - // interfaces are a bit ugly, specific and make assumptions. - - public ISocket CreateTcpSocket(IPAddress remoteAddress, int remotePort) - { - if (remotePort < 0) - { - throw new ArgumentException("remotePort cannot be less than zero.", nameof(remotePort)); - } - - var addressFamily = remoteAddress.AddressFamily == AddressFamily.InterNetwork - ? AddressFamily.InterNetwork - : AddressFamily.InterNetworkV6; - - var retVal = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); - - try - { - retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - } - catch (SocketException) - { - // This is not supported on all operating systems (qnap) - } - - try - { - return new UdpSocket(retVal, new IPEndPoint(remoteAddress, remotePort)); - } - catch - { - retVal?.Dispose(); - - throw; - } - } - /// /// Creates a new UDP acceptSocket and binds it to the specified local port. /// -- cgit v1.2.3 From 5dd332b63d423f7c6a4b70cb826a35a957c4e6fa Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 16 Aug 2019 18:52:16 +0200 Subject: Attempt to fix #1391 --- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 44 ++++++++++++---------- Emby.Server.Implementations/Net/SocketFactory.cs | 3 +- 2 files changed, 26 insertions(+), 21 deletions(-) (limited to 'Emby.Server.Implementations/Net/SocketFactory.cs') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index fbbab07f8..820ba1c36 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -1,5 +1,4 @@ using System; -using System.Buffers; using System.Collections.Generic; using System.IO; using System.Net; @@ -82,7 +81,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - var udpClient = _socketFactory.CreateUdpSocket(localPort); + var udpClient = new UdpClient(localPort, AddressFamily.InterNetwork); var hdHomerunManager = new HdHomerunManager(); try @@ -133,7 +132,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun await taskCompletionSource.Task.ConfigureAwait(false); } - private Task StartStreaming(MediaBrowser.Model.Net.ISocket udpClient, HdHomerunManager hdHomerunManager, IPAddress remoteAddress, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) + private Task StartStreaming(UdpClient udpClient, HdHomerunManager hdHomerunManager, IPAddress remoteAddress, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) { return Task.Run(async () => { @@ -162,28 +161,37 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun }); } - private async Task CopyTo(MediaBrowser.Model.Net.ISocket udpClient, string file, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) + private async Task CopyTo(UdpClient udpClient, string file, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) { - byte[] buffer = ArrayPool.Shared.Rent(StreamDefaults.DefaultCopyToBufferSize); - try + var resolved = false; + + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) { - using (var source = _socketFactory.CreateNetworkStream(udpClient, false)) - using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) + while (true) { - var currentCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token).Token; - int read; - var resolved = false; - while ((read = await source.ReadAsync(buffer, 0, buffer.Length, currentCancellationToken).ConfigureAwait(false)) != 0) + cancellationToken.ThrowIfCancellationRequested(); + using (var timeOutSource = new CancellationTokenSource()) + using (var linkedSource = CancellationTokenSource.CreateLinkedTokenSource( + cancellationToken, + timeOutSource.Token)) { - cancellationToken.ThrowIfCancellationRequested(); + var resTask = udpClient.ReceiveAsync(); + if (await Task.WhenAny(resTask, Task.Delay(30000, linkedSource.Token)).ConfigureAwait(false) != resTask) + { + resTask.Dispose(); + break; + } - currentCancellationToken = cancellationToken; + // We don't want all these delay tasks to keep running + timeOutSource.Cancel(); + var res = await resTask.ConfigureAwait(false); + var buffer = res.Buffer; - read -= RtpHeaderBytes; + var read = buffer.Length - RtpHeaderBytes; if (read > 0) { - await fileStream.WriteAsync(buffer, RtpHeaderBytes, read).ConfigureAwait(false); + fileStream.Write(buffer, RtpHeaderBytes, read); } if (!resolved) @@ -195,10 +203,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } } - finally - { - ArrayPool.Shared.Return(buffer); - } } } } diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index cb53ce50c..0870db003 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -19,7 +19,8 @@ namespace Emby.Server.Implementations.Net throw new ArgumentException("localPort cannot be less than zero.", nameof(localPort)); } - var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); + var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + try { retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); -- cgit v1.2.3