From da07a91016d10dc8006a8b4d488020db8be5e0c3 Mon Sep 17 00:00:00 2001
From: Smeulf <smeulf@team-mediaportal.com>
Date: Sun, 9 Oct 2011 23:18:14 +0200
Subject: [PATCH] Last 2 HTTPWebRequest forced to use a specific network adapter

---
 .../IRemoteResourceInformationService.cs           |    8 ++++++++
 .../CachedMultiSegmentHttpStream.cs                |   15 +++++++++++----
 .../MediaManagement/RemoteResourceAccessorBase.cs  |    4 +++-
 .../RemoteResourceInformationService.cs            |   17 +++++++++++++++++
 .../Infrastructure/Dv/GENA/EventSubscription.cs    |    4 +++-
 .../Utils/HTTP/HTTPEndpointBinder.cs               |    4 ++--
 6 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/MediaPortal/Source/Core/MediaPortal.Common/MediaManagement/ResourceAccess/IRemoteResourceInformationService.cs b/MediaPortal/Source/Core/MediaPortal.Common/MediaManagement/ResourceAccess/IRemoteResourceInformationService.cs
index 322abe9..212ec01 100644
--- a/MediaPortal/Source/Core/MediaPortal.Common/MediaManagement/ResourceAccess/IRemoteResourceInformationService.cs
+++ b/MediaPortal/Source/Core/MediaPortal.Common/MediaManagement/ResourceAccess/IRemoteResourceInformationService.cs
@@ -24,6 +24,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Net;
 using MediaPortal.Common.Exceptions;
 
 namespace MediaPortal.Common.MediaManagement.ResourceAccess
@@ -116,5 +117,12 @@ namespace MediaPortal.Common.MediaManagement.ResourceAccess
     /// <exception cref="NotConnectedException">If the system of the given <paramref name="nativeSystemId"/> is not
     /// connected.</exception>
     string GetFileHttpUrl(string nativeSystemId, ResourcePath nativeResourcePath);
+
+    /// <summary>
+    /// Gets the IPAddress of the prefered link of the system with the given <paramref name="nativeSystemId"/>
+    /// </summary>
+    /// <param name="nativeSystemId">Id of the system to retreive the prefered link ip address</param>
+    /// <returns>THe IPAddress of the prefered link of the system</returns>
+    IPAddress GetRemoteEndPoint(string nativeSystemId);
   }
 }
\ No newline at end of file
diff --git a/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/CachedMultiSegmentHttpStream.cs b/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/CachedMultiSegmentHttpStream.cs
index df86719..b422a96 100644
--- a/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/CachedMultiSegmentHttpStream.cs
+++ b/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/CachedMultiSegmentHttpStream.cs
@@ -31,6 +31,7 @@ using MediaPortal.Utilities.Network;
 using System.Threading;
 using MediaPortal.Utilities.SystemAPI;
 using UPnP.Infrastructure.Utils;
+using UPnP.Infrastructure.Utils.HTTP;
 
 namespace MediaPortal.Common.Services.MediaManagement
 {
@@ -51,6 +52,7 @@ namespace MediaPortal.Common.Services.MediaManagement
     #region Private & protected fields
 
     protected readonly string _url;
+    protected readonly IPAddress _remoteEndpoint;
     protected readonly long _length;
     protected long _position = 0;
     private IList<HttpRangeChunk> _chunkCache = new List<HttpRangeChunk>();
@@ -82,6 +84,7 @@ namespace MediaPortal.Common.Services.MediaManagement
       protected readonly long _startIndex; // Inclusive
       protected readonly long _endIndex; // Exclusive
       protected readonly string _url;
+      protected readonly IPAddress _remoteEndpoint;
 
       // Data for async request control
       protected readonly object _syncObject = new object();
@@ -98,11 +101,12 @@ namespace MediaPortal.Common.Services.MediaManagement
         _userAgent = WindowsAPI.GetOsVersionString() + " HTTP/1.1 " + PRODUCT_VERSION;
       }
 
-      public HttpRangeChunk(long start, long end, long wholeStreamLength, string url)
+      public HttpRangeChunk(long start, long end, long wholeStreamLength, string url, IPAddress remoteEndpoint)
       {
         _startIndex = start;
         _endIndex = Math.Min(wholeStreamLength, end);
         _url = url;
+        _remoteEndpoint = remoteEndpoint;
         Load_Async();
       }
 
@@ -133,7 +137,9 @@ namespace MediaPortal.Common.Services.MediaManagement
       protected void Load_Async()
       {
         HttpWebRequest request = (HttpWebRequest) WebRequest.Create(_url);
-        //TODO : Smeulf -> Bind request to a specific network adapter
+        //Smeulf : Bind request to a specific network adapter
+        request = new HTTPEndpointBinder(_remoteEndpoint, request).GetRequestWithEndpoint();
+
         request.Method = "GET";
         request.KeepAlive = true;
         request.AllowAutoRedirect = true;
@@ -274,10 +280,11 @@ namespace MediaPortal.Common.Services.MediaManagement
     /// <summary>
     /// Creates a <see cref="CachedMultiSegmentHttpStream"/> that can read data over HTTP.
     /// </summary>
-    public CachedMultiSegmentHttpStream(string url, long streamLength)
+    public CachedMultiSegmentHttpStream(string url, long streamLength, IPAddress remoteEndpoint)
     {
       _length = streamLength;
       _url = url;
+      _remoteEndpoint = remoteEndpoint;
     }
 
     protected override void Dispose(bool disposing)
@@ -461,7 +468,7 @@ namespace MediaPortal.Common.Services.MediaManagement
         _chunkCache[0].Dispose();
         _chunkCache.RemoveAt(0);
       }
-      _chunkCache.Add(chunk = new HttpRangeChunk(start, start + CHUNK_SIZE, Length, _url));
+      _chunkCache.Add(chunk = new HttpRangeChunk(start, start + CHUNK_SIZE, Length, _url, _remoteEndpoint));
     }
 
     protected HttpRangeChunk ProvideReadAhead(long position, int numReadaheadChunks)
diff --git a/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/RemoteResourceAccessorBase.cs b/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/RemoteResourceAccessorBase.cs
index 016da34..c83e0b3 100644
--- a/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/RemoteResourceAccessorBase.cs
+++ b/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/RemoteResourceAccessorBase.cs
@@ -24,6 +24,7 @@
 
 using System;
 using System.IO;
+using System.Net;
 using MediaPortal.Common.MediaManagement.ResourceAccess;
 using MediaPortal.Utilities.Exceptions;
 
@@ -109,9 +110,10 @@ namespace MediaPortal.Common.Services.MediaManagement
         return;
       IRemoteResourceInformationService rris = ServiceRegistration.Get<IRemoteResourceInformationService>();
       string resourceURL = rris.GetFileHttpUrl(_resourceLocator.NativeSystemId, _resourceLocator.NativeResourcePath);
+      IPAddress remoteEndpoint = rris.GetRemoteEndPoint(_resourceLocator.NativeSystemId);
       lock (_syncObj)
       {
-        _underlayingStream = new CachedMultiSegmentHttpStream(resourceURL, Size);
+        _underlayingStream = new CachedMultiSegmentHttpStream(resourceURL, Size, remoteEndpoint);
       }
     }
 
diff --git a/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/RemoteResourceInformationService.cs b/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/RemoteResourceInformationService.cs
index 6cb334c..51d7a77 100644
--- a/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/RemoteResourceInformationService.cs
+++ b/MediaPortal/Source/Core/MediaPortal.Common/Services/MediaManagement/RemoteResourceInformationService.cs
@@ -24,6 +24,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Net;
 using System.Xml.XPath;
 using MediaPortal.Common.Exceptions;
 using MediaPortal.Common.Logging;
@@ -119,6 +120,17 @@ namespace MediaPortal.Common.Services.MediaManagement
       return null;
     }
 
+    protected IPAddress FindResourceIPAddress(string systemId)
+    {
+      lock (_networkTracker.SharedControlPointData.SyncObj)
+        foreach (RootDescriptor rootDeviceDescriptor in _networkTracker.KnownRootDevices.Values)
+          if (rootDeviceDescriptor.SSDPRootEntry.RootDeviceID == systemId)
+          {
+            return rootDeviceDescriptor.SSDPRootEntry.PreferredLink.Endpoint.EndPointIPAddress;
+          }
+      return null;
+    }
+
     protected IResourceInformationService GetResourceInformationService(string systemId)
     {
       IResourceInformationService result = FindResourceInformationService(systemId);
@@ -169,5 +181,10 @@ namespace MediaPortal.Common.Services.MediaManagement
     {
       return ResourceHttpAccessUrlUtils.GetResourceURL(GetResourceInformationService(nativeSystemId).GetResourceServerBaseURL(), nativeResourcePath);
     }
+
+    public IPAddress GetRemoteEndPoint(string nativeSystemId)
+    {
+      return FindResourceIPAddress(nativeSystemId);
+    }
   }
 }
\ No newline at end of file
diff --git a/MediaPortal/Source/Core/UPnP/Infrastructure/Dv/GENA/EventSubscription.cs b/MediaPortal/Source/Core/UPnP/Infrastructure/Dv/GENA/EventSubscription.cs
index 7377968..83dd84a 100644
--- a/MediaPortal/Source/Core/UPnP/Infrastructure/Dv/GENA/EventSubscription.cs
+++ b/MediaPortal/Source/Core/UPnP/Infrastructure/Dv/GENA/EventSubscription.cs
@@ -30,6 +30,7 @@ using System.Text;
 using System.Threading;
 using UPnP.Infrastructure.Dv.DeviceTree;
 using UPnP.Infrastructure.Utils;
+using UPnP.Infrastructure.Utils.HTTP;
 
 namespace UPnP.Infrastructure.Dv.GENA
 {
@@ -155,8 +156,9 @@ namespace UPnP.Infrastructure.Dv.GENA
       }
       string callbackURL = e.Current;
       state.PendingCallbackURLs.Remove(callbackURL);
-      //TODO : Smeulf => bind this request to a specific network adapter
       HttpWebRequest request = (HttpWebRequest) WebRequest.Create(callbackURL);
+      //Smeulf : Bind request to a specific network adapter
+      request = new HTTPEndpointBinder(_config.EndPointIPAddress, request).GetRequestWithEndpoint();
       request.Method = "NOTIFY";
       request.KeepAlive = false;
       request.ContentType = "text/xml; charset=\"utf-8\"";
diff --git a/MediaPortal/Source/Core/UPnP/Infrastructure/Utils/HTTP/HTTPEndpointBinder.cs b/MediaPortal/Source/Core/UPnP/Infrastructure/Utils/HTTP/HTTPEndpointBinder.cs
index 13abb92..24557f7 100644
--- a/MediaPortal/Source/Core/UPnP/Infrastructure/Utils/HTTP/HTTPEndpointBinder.cs
+++ b/MediaPortal/Source/Core/UPnP/Infrastructure/Utils/HTTP/HTTPEndpointBinder.cs
@@ -1,12 +1,12 @@
 ﻿//using System;
 //using System.Collections.Generic;
 using System.Net;
-using UPnP.Infrastructure.CP.SSDP;
+//using UPnP.Infrastructure.CP.SSDP;
 
 
 namespace UPnP.Infrastructure.Utils.HTTP
 {
-  class HTTPEndpointBinder
+  public class HTTPEndpointBinder
   {
     private IPAddress _remoteIpAddress;
     private HttpWebRequest _request;
-- 
1.7.4.msysgit.0

