From 44336488f375adcdd5aa696790706b38483381fe Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 14 Nov 2016 14:48:01 -0500 Subject: [PATCH] update udp sockets --- .../Net/SocketFactory.cs | 1 + Emby.Common.Implementations/Net/UdpSocket.cs | 11 ++----- Emby.Dlna/Main/DlnaEntryPoint.cs | 30 ++++++++++++++----- Emby.Dlna/Ssdp/DeviceDiscovery.cs | 20 +++++-------- RSSDP/SsdpCommunicationsServer.cs | 17 +++++------ 5 files changed, 42 insertions(+), 37 deletions(-) diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs index f261376834..c65593242e 100644 --- a/Emby.Common.Implementations/Net/SocketFactory.cs +++ b/Emby.Common.Implementations/Net/SocketFactory.cs @@ -131,6 +131,7 @@ namespace Emby.Common.Implementations.Net #else retVal.ExclusiveAddressUse = false; #endif + //retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive); retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse(ipAddress), _LocalIP)); diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs index eca82034b0..b9b7d8a2db 100644 --- a/Emby.Common.Implementations/Net/UdpSocket.cs +++ b/Emby.Common.Implementations/Net/UdpSocket.cs @@ -63,7 +63,7 @@ namespace Emby.Common.Implementations.Net } }, state); #else - _Socket.BeginReceiveFrom(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, ref state.EndPoint, new AsyncCallback(this.ProcessResponse), state); + _Socket.BeginReceiveFrom(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, ref state.EndPoint, ProcessResponse, state); #endif return tcs.Task; @@ -99,7 +99,7 @@ namespace Emby.Common.Implementations.Net _Socket.EndSend(result); taskSource.TrySetResult(true); } - catch (SocketException ex) + catch (Exception ex) { taskSource.TrySetException(ex); } @@ -200,13 +200,6 @@ namespace Emby.Common.Implementations.Net { state.TaskCompletionSource.SetCanceled(); } - catch (SocketException se) - { - if (se.SocketErrorCode != SocketError.Interrupted && se.SocketErrorCode != SocketError.OperationAborted && se.SocketErrorCode != SocketError.Shutdown) - state.TaskCompletionSource.SetException(se); - else - state.TaskCompletionSource.SetCanceled(); - } catch (Exception ex) { state.TaskCompletionSource.SetException(ex); diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index ef27c029dc..49bb9a74f2 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -55,6 +55,8 @@ namespace Emby.Dlna.Main private readonly ISocketFactory _socketFactory; private readonly IEnvironmentInfo _environmentInfo; + private ISsdpCommunicationsServer _communicationsServer; + public DlnaEntryPoint(IServerConfigurationManager config, ILogManager logManager, IServerApplicationHost appHost, @@ -152,10 +154,18 @@ namespace Emby.Dlna.Main { try { - StartPublishing(); + if (_communicationsServer == null) + { + _communicationsServer = new SsdpCommunicationsServer(_socketFactory) + { + IsShared = true + }; + } + + StartPublishing(_communicationsServer); _ssdpHandlerStarted = true; - StartDeviceDiscovery(); + StartDeviceDiscovery(_communicationsServer); } catch (Exception ex) { @@ -165,20 +175,20 @@ namespace Emby.Dlna.Main private void LogMessage(string msg) { - //_logger.Debug(msg); + _logger.Debug(msg); } - private void StartPublishing() + private void StartPublishing(ISsdpCommunicationsServer communicationsServer) { SsdpDevicePublisherBase.LogFunction = LogMessage; - _Publisher = new SsdpDevicePublisher(_socketFactory, _timerFactory, _environmentInfo.OperatingSystemName, _environmentInfo.OperatingSystemVersion); + _Publisher = new SsdpDevicePublisher(communicationsServer, _timerFactory, _environmentInfo.OperatingSystemName, _environmentInfo.OperatingSystemVersion); } - private void StartDeviceDiscovery() + private void StartDeviceDiscovery(ISsdpCommunicationsServer communicationsServer) { try { - ((DeviceDiscovery)_deviceDiscovery).Start(); + ((DeviceDiscovery)_deviceDiscovery).Start(communicationsServer); } catch (Exception ex) { @@ -374,6 +384,12 @@ namespace Emby.Dlna.Main DisposeDlnaServer(); DisposePlayToManager(); DisposeSsdpHandler(); + + if (_communicationsServer != null) + { + _communicationsServer.Dispose(); + _communicationsServer = null; + } } public void DisposeDlnaServer() diff --git a/Emby.Dlna/Ssdp/DeviceDiscovery.cs b/Emby.Dlna/Ssdp/DeviceDiscovery.cs index 6f58429680..1cd19d010c 100644 --- a/Emby.Dlna/Ssdp/DeviceDiscovery.cs +++ b/Emby.Dlna/Ssdp/DeviceDiscovery.cs @@ -15,6 +15,7 @@ using MediaBrowser.Model.Events; using MediaBrowser.Model.Net; using MediaBrowser.Model.Threading; using Rssdp; +using Rssdp.Infrastructure; namespace Emby.Dlna.Ssdp { @@ -29,7 +30,7 @@ namespace Emby.Dlna.Ssdp public event EventHandler> DeviceDiscovered; public event EventHandler> DeviceLeft; - private SsdpDeviceLocator _DeviceLocator; + private SsdpDeviceLocator _deviceLocator; private readonly ITimerFactory _timerFactory; private readonly ISocketFactory _socketFactory; @@ -45,9 +46,9 @@ namespace Emby.Dlna.Ssdp } // Call this method from somewhere in your code to start the search. - public void BeginSearch() + public void Start(ISsdpCommunicationsServer communicationsServer) { - _DeviceLocator = new SsdpDeviceLocator(_socketFactory, _timerFactory); + _deviceLocator = new SsdpDeviceLocator(communicationsServer, _timerFactory); // (Optional) Set the filter so we only see notifications for devices we care about // (can be any search target value i.e device type, uuid value etc - any value that appears in the @@ -55,8 +56,8 @@ namespace Emby.Dlna.Ssdp //_DeviceLocator.NotificationFilter = "upnp:rootdevice"; // Connect our event handler so we process devices as they are found - _DeviceLocator.DeviceAvailable += deviceLocator_DeviceAvailable; - _DeviceLocator.DeviceUnavailable += _DeviceLocator_DeviceUnavailable; + _deviceLocator.DeviceAvailable += deviceLocator_DeviceAvailable; + _deviceLocator.DeviceUnavailable += _DeviceLocator_DeviceUnavailable; // Perform a search so we don't have to wait for devices to broadcast notifications // again to get any results right away (notifications are broadcast periodically). @@ -72,9 +73,9 @@ namespace Emby.Dlna.Ssdp try { // Enable listening for notifications (optional) - _DeviceLocator.StartListeningForNotifications(); + _deviceLocator.StartListeningForNotifications(); - await _DeviceLocator.SearchAsync().ConfigureAwait(false); + await _deviceLocator.SearchAsync().ConfigureAwait(false); } catch (Exception ex) { @@ -130,11 +131,6 @@ namespace Emby.Dlna.Ssdp EventHelper.FireEventIfNotNull(DeviceLeft, this, args, _logger); } - public void Start() - { - BeginSearch(); - } - public void Dispose() { if (!_disposed) diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index c0b9c6542d..4de47f3d33 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -170,12 +170,11 @@ namespace Rssdp.Infrastructure /// /// Sends a message to the SSDP multicast address and port. /// - /// A byte array containing the data to send. - /// Thrown if the argument is null. - /// Thrown if the property is true (because has been called previously). - public async Task SendMulticastMessage(byte[] messageData) + public async Task SendMulticastMessage(string message) { - if (messageData == null) throw new ArgumentNullException("messageData"); + if (message == null) throw new ArgumentNullException("messageData"); + + byte[] messageData = Encoding.UTF8.GetBytes(message); ThrowIfDisposed(); @@ -294,21 +293,19 @@ namespace Rssdp.Infrastructure // Tasks are captured to local variables even if we don't use them just to avoid compiler warnings. var t = Task.Run(async () => { - var cancelled = false; while (!cancelled) { try { - var result = await socket.ReceiveAsync(); + var result = await socket.ReceiveAsync().ConfigureAwait(false); if (result.ReceivedBytes > 0) { // Strange cannot convert compiler error here if I don't explicitly // assign or cast to Action first. Assignment is easier to read, // so went with that. - Action processWork = () => ProcessMessage(System.Text.UTF8Encoding.UTF8.GetString(result.Buffer, 0, result.ReceivedBytes), result.RemoteEndPoint); - var processTask = Task.Run(processWork); + ProcessMessage(System.Text.UTF8Encoding.UTF8.GetString(result.Buffer, 0, result.ReceivedBytes), result.RemoteEndPoint); } } catch (ObjectDisposedException) @@ -330,7 +327,9 @@ namespace Rssdp.Infrastructure lock (_SendSocketSynchroniser) { if (_SendSocket == null) + { _SendSocket = CreateSocketAndListenForResponsesAsync(); + } } } }