commit
9b383f6b1a
|
@ -43,8 +43,8 @@ namespace Emby.Dlna.ContentDirectory
|
|||
|
||||
options.RequestContent = GetRequestBody(request);
|
||||
|
||||
var response = await _httpClient.SendAsync(options, "POST");
|
||||
|
||||
using (var response = await _httpClient.SendAsync(options, "POST"))
|
||||
{
|
||||
using (var reader = new StreamReader(response.Content))
|
||||
{
|
||||
var doc = XDocument.Parse(reader.ReadToEnd(), LoadOptions.PreserveWhitespace);
|
||||
|
@ -76,6 +76,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||
return queryResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetRequestBody(ContentDirectoryBrowseRequest request)
|
||||
{
|
||||
|
|
|
@ -182,7 +182,10 @@ namespace Emby.Dlna.Eventing
|
|||
|
||||
try
|
||||
{
|
||||
await _httpClient.SendAsync(options, "NOTIFY").ConfigureAwait(false);
|
||||
using (await _httpClient.SendAsync(options, "NOTIFY").ConfigureAwait(false))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
|
|
@ -31,9 +31,9 @@ namespace Emby.Dlna.PlayTo
|
|||
bool logRequest = true,
|
||||
string header = null)
|
||||
{
|
||||
var response = await PostSoapDataAsync(NormalizeServiceUrl(baseUrl, service.ControlUrl), "\"" + service.ServiceType + "#" + command + "\"", postData, header, logRequest)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
using (var response = await PostSoapDataAsync(NormalizeServiceUrl(baseUrl, service.ControlUrl), "\"" + service.ServiceType + "#" + command + "\"", postData, header, logRequest)
|
||||
.ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
||||
|
@ -42,6 +42,7 @@ namespace Emby.Dlna.PlayTo
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string NormalizeServiceUrl(string baseUrl, string serviceUrl)
|
||||
{
|
||||
|
@ -79,7 +80,10 @@ namespace Emby.Dlna.PlayTo
|
|||
options.RequestHeaders["NT"] = "upnp:event";
|
||||
options.RequestHeaders["TIMEOUT"] = "Second-" + timeOut.ToString(_usCulture);
|
||||
|
||||
await _httpClient.SendAsync(options, "SUBSCRIBE").ConfigureAwait(false);
|
||||
using (await _httpClient.SendAsync(options, "SUBSCRIBE").ConfigureAwait(false))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<XDocument> GetDataAsync(string url)
|
||||
|
@ -94,7 +98,9 @@ namespace Emby.Dlna.PlayTo
|
|||
|
||||
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
|
||||
|
||||
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||
using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
|
@ -102,6 +108,7 @@ namespace Emby.Dlna.PlayTo
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Task<HttpResponseInfo> PostSoapDataAsync(string url,
|
||||
string soapAction,
|
||||
|
|
|
@ -279,39 +279,9 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|||
public async Task<Stream> Get(HttpRequestOptions options)
|
||||
{
|
||||
var response = await GetResponse(options).ConfigureAwait(false);
|
||||
|
||||
return response.Content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a GET request and returns the resulting stream
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="resourcePool">The resource pool.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{Stream}.</returns>
|
||||
public Task<Stream> Get(string url, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
|
||||
{
|
||||
return Get(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
ResourcePool = resourcePool,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = resourcePool != null
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified URL.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{Stream}.</returns>
|
||||
public Task<Stream> Get(string url, CancellationToken cancellationToken)
|
||||
{
|
||||
return Get(url, null, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// send as an asynchronous operation.
|
||||
/// </summary>
|
||||
|
@ -589,26 +559,6 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|||
return response.Content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a POST request
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="postData">Params to add to the POST data.</param>
|
||||
/// <param name="resourcePool">The resource pool.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>stream on success, null on failure</returns>
|
||||
public Task<Stream> Post(string url, Dictionary<string, string> postData, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
|
||||
{
|
||||
return Post(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
ResourcePool = resourcePool,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = resourcePool != null
|
||||
|
||||
}, postData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Downloads the contents of a given url into a temporary location
|
||||
/// </summary>
|
||||
|
@ -891,18 +841,6 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts the specified URL.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="postData">The post data.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{Stream}.</returns>
|
||||
public Task<Stream> Post(string url, Dictionary<string, string> postData, CancellationToken cancellationToken)
|
||||
{
|
||||
return Post(url, postData, null, cancellationToken);
|
||||
}
|
||||
|
||||
private Task<WebResponse> GetResponseAsync(WebRequest request, TimeSpan timeout)
|
||||
{
|
||||
var taskCompletion = new TaskCompletionSource<WebResponse>();
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
|||
|
||||
season.Name = seasonNumber == 0 ?
|
||||
args.LibraryOptions.SeasonZeroDisplayName :
|
||||
string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture));
|
||||
string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage);
|
||||
}
|
||||
|
||||
return season;
|
||||
|
|
|
@ -1463,6 +1463,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
_timerProvider.AddOrUpdate(timer, false);
|
||||
|
||||
await SaveRecordingMetadata(timer, recordPath, seriesPath).ConfigureAwait(false);
|
||||
|
||||
CreateRecordingFolders();
|
||||
|
||||
TriggerRefresh(recordPath);
|
||||
EnforceKeepUpTo(timer, seriesPath);
|
||||
};
|
||||
|
|
|
@ -541,7 +541,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
|
||||
try
|
||||
{
|
||||
using (Stream responce = await Get(options, false, info).ConfigureAwait(false))
|
||||
using (var httpResponse = await Get(options, false, info).ConfigureAwait(false))
|
||||
{
|
||||
using (Stream responce = httpResponse.Content)
|
||||
{
|
||||
var root = _jsonSerializer.DeserializeFromStream<List<ScheduleDirect.Headends>>(responce);
|
||||
|
||||
|
@ -565,6 +567,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error("Error getting headends", ex);
|
||||
|
@ -671,13 +674,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
return await Post(options, false, providerInfo).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<Stream> Get(HttpRequestOptions options,
|
||||
private async Task<HttpResponseInfo> Get(HttpRequestOptions options,
|
||||
bool enableRetry,
|
||||
ListingsProviderInfo providerInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _httpClient.Get(options).ConfigureAwait(false);
|
||||
return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
|
@ -797,13 +800,16 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
|
||||
try
|
||||
{
|
||||
using (var response = await Get(options, false, null).ConfigureAwait(false))
|
||||
using (var httpResponse = await Get(options, false, null).ConfigureAwait(false))
|
||||
{
|
||||
using (var response = httpResponse.Content)
|
||||
{
|
||||
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Lineups>(response);
|
||||
|
||||
return root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
// Apparently we're supposed to swallow this
|
||||
|
@ -879,7 +885,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
|
||||
var list = new List<ChannelInfo>();
|
||||
|
||||
using (var response = await Get(httpOptions, true, info).ConfigureAwait(false))
|
||||
using (var httpResponse = await Get(httpOptions, true, info).ConfigureAwait(false))
|
||||
{
|
||||
using (var response = httpResponse.Content)
|
||||
{
|
||||
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
|
||||
_logger.Info("Found " + root.map.Count + " channels on the lineup on ScheduleDirect");
|
||||
|
@ -928,6 +936,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
list.Add(channelInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -86,7 +86,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
CancellationToken = cancellationToken,
|
||||
BufferContent = false
|
||||
};
|
||||
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||
using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var lineup = JsonSerializer.DeserializeFromStream<List<Channels>>(stream) ?? new List<Channels>();
|
||||
|
||||
|
@ -98,6 +100,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
return lineup.Where(i => !i.DRM).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class HdHomerunChannelInfo : ChannelInfo
|
||||
{
|
||||
|
@ -143,26 +146,29 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
|
||||
try
|
||||
{
|
||||
using (var stream = await _httpClient.Get(new HttpRequestOptions()
|
||||
using (var response = await _httpClient.SendAsync(new HttpRequestOptions()
|
||||
{
|
||||
Url = string.Format("{0}/discover.json", GetApiUrl(info, false)),
|
||||
CancellationToken = cancellationToken,
|
||||
TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds),
|
||||
BufferContent = false
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
var response = JsonSerializer.DeserializeFromStream<DiscoverResponse>(stream);
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var discoverResponse = JsonSerializer.DeserializeFromStream<DiscoverResponse>(stream);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(info.Id))
|
||||
{
|
||||
lock (_modelCache)
|
||||
{
|
||||
_modelCache[info.Id] = response;
|
||||
_modelCache[info.Id] = discoverResponse;
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
return discoverResponse;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (HttpException ex)
|
||||
|
|
|
@ -91,6 +91,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
EnableHttpCompression = false
|
||||
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
Logger.Info("Opened HDHR stream from {0}", url);
|
||||
|
||||
|
@ -99,7 +101,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
FileSystem.CreateDirectory(FileSystem.GetDirectoryName(TempFilePath));
|
||||
using (var fileStream = FileSystem.GetFileStream(TempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None))
|
||||
{
|
||||
StreamHelper.CopyTo(response.Content, fileStream, 81920, () => Resolve(openTaskCompletionSource), cancellationToken);
|
||||
StreamHelper.CopyTo(stream, fileStream, 81920, () => Resolve(openTaskCompletionSource), cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -315,6 +315,11 @@ namespace Emby.Server.Implementations.Localization
|
|||
|
||||
public string GetLocalizedString(string phrase, string culture)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(culture))
|
||||
{
|
||||
culture = _configurationManager.Configuration.UICulture;
|
||||
}
|
||||
|
||||
var dictionary = GetLocalizationDictionary(culture);
|
||||
|
||||
string value;
|
||||
|
|
|
@ -88,7 +88,9 @@ namespace Emby.Server.Implementations.News
|
|||
BufferContent = false
|
||||
};
|
||||
|
||||
using (var stream = await _httpClient.Get(requestOptions).ConfigureAwait(false))
|
||||
using (var response = await _httpClient.SendAsync(requestOptions, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
using (var reader = XmlReader.Create(stream))
|
||||
{
|
||||
|
@ -100,6 +102,7 @@ namespace Emby.Server.Implementations.News
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Task CreateNotifications(List<NewsItem> items, DateTime? lastUpdate, CancellationToken cancellationToken)
|
||||
{
|
||||
|
|
|
@ -293,11 +293,14 @@ namespace Emby.Server.Implementations.Security
|
|||
|
||||
options.SetPostData(data);
|
||||
|
||||
using (var json = (await _httpClient.Post(options).ConfigureAwait(false)).Content)
|
||||
using (var response = (await _httpClient.Post(options).ConfigureAwait(false)))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
reg = _jsonSerializer.DeserializeFromStream<RegRecord>(json);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (reg.registered)
|
||||
{
|
||||
|
|
|
@ -66,19 +66,22 @@ namespace Emby.Server.Implementations.Session
|
|||
return SendMessage(name, new Dictionary<string, string>(), cancellationToken);
|
||||
}
|
||||
|
||||
private Task SendMessage(string name,
|
||||
private async Task SendMessage(string name,
|
||||
Dictionary<string, string> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var url = PostUrl + "/" + name + ToQueryString(args);
|
||||
|
||||
return _httpClient.Post(new HttpRequestOptions
|
||||
using ((await _httpClient.Post(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = false
|
||||
|
||||
});
|
||||
}).ConfigureAwait(false)))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken)
|
||||
|
|
|
@ -175,7 +175,17 @@ namespace Emby.Server.Implementations.Updates
|
|||
{ "systemid", _applicationHost.SystemId }
|
||||
};
|
||||
|
||||
using (var json = await _httpClient.Post("https://www.mb3admin.com/admin/service/package/retrieveall?includeAllRuntimes=true", data, cancellationToken).ConfigureAwait(false))
|
||||
var options = new HttpRequestOptions
|
||||
{
|
||||
Url = "https://www.mb3admin.com/admin/service/package/retrieveall?includeAllRuntimes=true",
|
||||
CancellationToken = cancellationToken
|
||||
};
|
||||
|
||||
options.SetPostData(data);
|
||||
|
||||
using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
|
@ -184,6 +194,7 @@ namespace Emby.Server.Implementations.Updates
|
|||
return FilterPackages(packages, packageType, applicationVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
|
||||
|
|
|
@ -262,13 +262,13 @@ namespace MediaBrowser.Api.Images
|
|||
/// <returns>Task.</returns>
|
||||
private async Task DownloadImage(string url, Guid urlHash, string pointerCachePath)
|
||||
{
|
||||
var result = await _httpClient.GetResponse(new HttpRequestOptions
|
||||
using (var result = await _httpClient.GetResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
BufferContent = false
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
var ext = result.ContentType.Split('/').Last();
|
||||
|
||||
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
|
||||
|
@ -285,6 +285,7 @@ namespace MediaBrowser.Api.Images
|
|||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath));
|
||||
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full cache path.
|
||||
|
|
|
@ -18,24 +18,6 @@ namespace MediaBrowser.Common.Net
|
|||
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||
Task<HttpResponseInfo> GetResponse(HttpRequestOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Performs a GET request and returns the resulting stream
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="resourcePool">The resource pool.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{Stream}.</returns>
|
||||
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
|
||||
Task<Stream> Get(string url, SemaphoreSlim resourcePool, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified URL.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{Stream}.</returns>
|
||||
Task<Stream> Get(string url, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified options.
|
||||
/// </summary>
|
||||
|
@ -51,35 +33,6 @@ namespace MediaBrowser.Common.Net
|
|||
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||
Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod);
|
||||
|
||||
/// <summary>
|
||||
/// Performs a POST request
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="postData">Params to add to the POST data.</param>
|
||||
/// <param name="resourcePool">The resource pool.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>stream on success, null on failure</returns>
|
||||
/// <exception cref="System.ArgumentNullException">postData</exception>
|
||||
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
|
||||
Task<Stream> Post(string url, Dictionary<string, string> postData, SemaphoreSlim resourcePool, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Posts the specified URL.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="postData">The post data.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{Stream}.</returns>
|
||||
Task<Stream> Post(string url, Dictionary<string, string> postData, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Posts the specified options with post data
|
||||
/// </summary>
|
||||
/// <param name="options">The options</param>
|
||||
/// <param name="postData">The post data</param>
|
||||
/// <returns>Task{Stream}</returns>
|
||||
Task<Stream> Post(HttpRequestOptions options, Dictionary<string, string> postData);
|
||||
|
||||
/// <summary>
|
||||
/// Posts the specified options.
|
||||
/// </summary>
|
||||
|
|
|
@ -40,13 +40,16 @@ namespace MediaBrowser.Common.Updates
|
|||
options.CacheLength = cacheLength;
|
||||
}
|
||||
|
||||
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||
using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);
|
||||
|
||||
return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CheckForUpdateResult CheckForUpdateResult(RootObject[] obj, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename)
|
||||
{
|
||||
|
@ -110,7 +113,9 @@ namespace MediaBrowser.Common.Updates
|
|||
BufferContent = false
|
||||
};
|
||||
|
||||
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||
using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);
|
||||
|
||||
|
@ -123,6 +128,7 @@ namespace MediaBrowser.Common.Updates
|
|||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Version GetVersion(RootObject obj)
|
||||
{
|
||||
|
|
|
@ -179,16 +179,19 @@ namespace MediaBrowser.Providers.BoxSets
|
|||
|
||||
RootObject mainResult = null;
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbSearch.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
mainResult = _json.DeserializeFromStream<RootObject>(json);
|
||||
}
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
|
@ -204,18 +207,21 @@ namespace MediaBrowser.Providers.BoxSets
|
|||
url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language);
|
||||
}
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbSearch.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
mainResult = _json.DeserializeFromStream<RootObject>(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mainResult;
|
||||
}
|
||||
|
||||
|
|
|
@ -153,16 +153,16 @@ namespace MediaBrowser.Providers.Manager
|
|||
|
||||
public async Task SaveImage(IHasMetadata item, string url, ImageType type, int? imageIndex, CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await _httpClient.GetResponse(new HttpRequestOptions
|
||||
using (var response = await _httpClient.GetResponse(new HttpRequestOptions
|
||||
{
|
||||
CancellationToken = cancellationToken,
|
||||
Url = url,
|
||||
BufferContent = false
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
await SaveImage(item, response.Content, response.ContentType, type, imageIndex, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
await SaveImage(item, response.Content, response.ContentType, type, imageIndex, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public Task SaveImage(IHasMetadata item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken)
|
||||
|
|
|
@ -274,13 +274,15 @@ namespace MediaBrowser.Providers.Movies
|
|||
|
||||
try
|
||||
{
|
||||
using (var response = await _httpClient.Get(new HttpRequestOptions
|
||||
using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = true
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var response = httpResponse.Content)
|
||||
{
|
||||
using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
||||
{
|
||||
|
@ -288,6 +290,7 @@ namespace MediaBrowser.Providers.Movies
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (HttpException exception)
|
||||
{
|
||||
if (exception.StatusCode.HasValue && exception.StatusCode.Value == HttpStatusCode.NotFound)
|
||||
|
|
|
@ -146,19 +146,22 @@ namespace MediaBrowser.Providers.Movies
|
|||
return _tmdbSettings;
|
||||
}
|
||||
|
||||
using (var json = await GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = string.Format(TmdbConfigUrl, ApiKey),
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
_tmdbSettings = _jsonSerializer.DeserializeFromStream<TmdbSettingsResult>(json);
|
||||
|
||||
return _tmdbSettings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const string TmdbConfigUrl = "https://api.themoviedb.org/3/configuration?api_key={0}";
|
||||
private const string GetMovieInfo3 = @"https://api.themoviedb.org/3/movie/{0}?api_key={1}&append_to_response=casts,releases,images,keywords,trailers";
|
||||
|
@ -339,7 +342,7 @@ namespace MediaBrowser.Providers.Movies
|
|||
|
||||
try
|
||||
{
|
||||
using (var json = await GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
|
@ -348,10 +351,13 @@ namespace MediaBrowser.Providers.Movies
|
|||
CacheLength = cacheLength
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
mainResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
// Return null so that callers know there is no metadata for this id
|
||||
|
@ -381,7 +387,7 @@ namespace MediaBrowser.Providers.Movies
|
|||
url += "&include_image_language=" + GetImageLanguagesParam(language);
|
||||
}
|
||||
|
||||
using (var json = await GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
|
@ -390,12 +396,15 @@ namespace MediaBrowser.Providers.Movies
|
|||
CacheLength = cacheLength
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
var englishResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json);
|
||||
|
||||
mainResult.overview = englishResult.overview;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mainResult;
|
||||
}
|
||||
|
@ -407,7 +416,7 @@ namespace MediaBrowser.Providers.Movies
|
|||
/// <summary>
|
||||
/// Gets the movie db response.
|
||||
/// </summary>
|
||||
internal async Task<Stream> GetMovieDbResponse(HttpRequestOptions options)
|
||||
internal async Task<HttpResponseInfo> GetMovieDbResponse(HttpRequestOptions options)
|
||||
{
|
||||
var delayTicks = (requestIntervalMs * 10000) - (DateTime.UtcNow.Ticks - _lastRequestTicks);
|
||||
var delayMs = Math.Min(delayTicks / 10000, requestIntervalMs);
|
||||
|
@ -423,7 +432,7 @@ namespace MediaBrowser.Providers.Movies
|
|||
options.BufferContent = true;
|
||||
options.UserAgent = "Emby/" + _appHost.ApplicationVersion;
|
||||
|
||||
return await _httpClient.Get(options).ConfigureAwait(false);
|
||||
return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -154,13 +154,15 @@ namespace MediaBrowser.Providers.Movies
|
|||
|
||||
var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, type);
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url3,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
var searchResults = _json.DeserializeFromStream<TmdbMovieSearchResults>(json);
|
||||
|
||||
|
@ -196,6 +198,7 @@ namespace MediaBrowser.Providers.Movies
|
|||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<List<RemoteSearchResult>> GetSearchResultsTv(string name, int? year, string language, string baseImageUrl, CancellationToken cancellationToken)
|
||||
{
|
||||
|
@ -206,13 +209,15 @@ namespace MediaBrowser.Providers.Movies
|
|||
|
||||
var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, "tv");
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url3,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
var searchResults = _json.DeserializeFromStream<TmdbTvSearchResults>(json);
|
||||
|
||||
|
@ -248,6 +253,7 @@ namespace MediaBrowser.Providers.Movies
|
|||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class TmdbMovieSearchResult
|
||||
|
|
|
@ -161,12 +161,14 @@ namespace MediaBrowser.Providers.Music
|
|||
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
using (var response = await _httpClient.Get(new HttpRequestOptions
|
||||
using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var response = httpResponse.Content)
|
||||
{
|
||||
using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
||||
{
|
||||
|
@ -174,6 +176,7 @@ namespace MediaBrowser.Providers.Music
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetAlbumDataPath(IApplicationPaths appPaths, string musicBrainzReleaseGroupId)
|
||||
{
|
||||
|
|
|
@ -147,13 +147,15 @@ namespace MediaBrowser.Providers.Music
|
|||
|
||||
var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
|
||||
|
||||
using (var response = await _httpClient.Get(new HttpRequestOptions
|
||||
using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = true
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var response = httpResponse.Content)
|
||||
{
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
|
@ -163,6 +165,7 @@ namespace MediaBrowser.Providers.Music
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the artist data path.
|
||||
|
|
|
@ -251,13 +251,15 @@ namespace MediaBrowser.Providers.Music
|
|||
|
||||
try
|
||||
{
|
||||
using (var response = await _httpClient.Get(new HttpRequestOptions
|
||||
using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = true
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var response = httpResponse.Content)
|
||||
{
|
||||
using (var saveFileStream = _fileSystem.GetFileStream(jsonPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
||||
{
|
||||
|
@ -265,6 +267,7 @@ namespace MediaBrowser.Providers.Music
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
|
||||
|
|
|
@ -83,11 +83,14 @@ namespace MediaBrowser.Providers.Music
|
|||
|
||||
if (!string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
using (var stream = await GetMusicBrainzResponse(url, isNameSearch, forceMusicBrainzProper, cancellationToken).ConfigureAwait(false))
|
||||
using (var response = await GetMusicBrainzResponse(url, isNameSearch, forceMusicBrainzProper, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
return GetResultsFromResponse(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new List<RemoteSearchResult>();
|
||||
}
|
||||
|
@ -226,7 +229,9 @@ namespace MediaBrowser.Providers.Music
|
|||
WebUtility.UrlEncode(albumName),
|
||||
artistId);
|
||||
|
||||
using (var stream = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
using (var response = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
|
@ -243,6 +248,7 @@ namespace MediaBrowser.Providers.Music
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<ReleaseResult> GetReleaseResultByArtistName(string albumName, string artistName, CancellationToken cancellationToken)
|
||||
{
|
||||
|
@ -250,7 +256,9 @@ namespace MediaBrowser.Providers.Music
|
|||
WebUtility.UrlEncode(albumName),
|
||||
WebUtility.UrlEncode(artistName));
|
||||
|
||||
using (var stream = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
using (var response = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
|
@ -267,6 +275,7 @@ namespace MediaBrowser.Providers.Music
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReleaseResult
|
||||
{
|
||||
|
@ -431,7 +440,9 @@ namespace MediaBrowser.Providers.Music
|
|||
{
|
||||
var url = string.Format("/ws/2/release?release-group={0}", releaseGroupId);
|
||||
|
||||
using (var stream = await GetMusicBrainzResponse(url, true, true, cancellationToken).ConfigureAwait(false))
|
||||
using (var response = await GetMusicBrainzResponse(url, true, true, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
|
@ -452,6 +463,7 @@ namespace MediaBrowser.Providers.Music
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -466,7 +478,9 @@ namespace MediaBrowser.Providers.Music
|
|||
{
|
||||
var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId);
|
||||
|
||||
using (var stream = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
|
||||
using (var response = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
|
@ -517,6 +531,7 @@ namespace MediaBrowser.Providers.Music
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetFirstReleaseGroupId(XmlReader reader)
|
||||
{
|
||||
|
@ -598,12 +613,15 @@ namespace MediaBrowser.Providers.Music
|
|||
UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion
|
||||
};
|
||||
|
||||
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||
using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var results = _json.DeserializeFromStream<List<MbzUrl>>(stream);
|
||||
|
||||
list = results;
|
||||
}
|
||||
}
|
||||
_lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -626,7 +644,7 @@ namespace MediaBrowser.Providers.Music
|
|||
return list;
|
||||
}
|
||||
|
||||
internal Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
|
||||
internal Task<HttpResponseInfo> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
|
||||
{
|
||||
return GetMusicBrainzResponse(url, isSearch, false, cancellationToken);
|
||||
}
|
||||
|
@ -634,7 +652,7 @@ namespace MediaBrowser.Providers.Music
|
|||
/// <summary>
|
||||
/// Gets the music brainz response.
|
||||
/// </summary>
|
||||
internal async Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, bool forceMusicBrainzProper, CancellationToken cancellationToken)
|
||||
internal async Task<HttpResponseInfo> GetMusicBrainzResponse(string url, bool isSearch, bool forceMusicBrainzProper, CancellationToken cancellationToken)
|
||||
{
|
||||
var urlInfo = await GetMbzUrl(forceMusicBrainzProper).ConfigureAwait(false);
|
||||
var throttleMs = urlInfo.throttleMs;
|
||||
|
@ -656,7 +674,7 @@ namespace MediaBrowser.Providers.Music
|
|||
BufferContent = throttleMs > 0
|
||||
};
|
||||
|
||||
return await _httpClient.Get(options).ConfigureAwait(false);
|
||||
return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public int Order
|
||||
|
|
|
@ -35,12 +35,14 @@ namespace MediaBrowser.Providers.Music
|
|||
{
|
||||
var url = string.Format("/ws/2/artist/?query=arid:{0}", musicBrainzId);
|
||||
|
||||
using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken)
|
||||
.ConfigureAwait(false))
|
||||
using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
return GetResultsFromResponse(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// They seem to throw bad request failures on any term with a slash
|
||||
|
@ -48,7 +50,9 @@ namespace MediaBrowser.Providers.Music
|
|||
|
||||
var url = String.Format("/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch));
|
||||
|
||||
using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var results = GetResultsFromResponse(stream);
|
||||
|
||||
|
@ -57,18 +61,22 @@ namespace MediaBrowser.Providers.Music
|
|||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HasDiacritics(searchInfo.Name))
|
||||
{
|
||||
// Try again using the search with accent characters url
|
||||
url = String.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
|
||||
|
||||
using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
return GetResultsFromResponse(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new List<RemoteSearchResult>();
|
||||
}
|
||||
|
|
|
@ -126,7 +126,9 @@ namespace MediaBrowser.Providers.Omdb
|
|||
|
||||
var url = OmdbProvider.GetOmdbUrl(urlQuery, cancellationToken);
|
||||
|
||||
using (var stream = await OmdbProvider.GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
|
||||
using (var response = await OmdbProvider.GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var resultList = new List<SearchResult>();
|
||||
|
||||
|
@ -187,6 +189,7 @@ namespace MediaBrowser.Providers.Omdb
|
|||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
|
|
|
@ -301,12 +301,15 @@ namespace MediaBrowser.Providers.Omdb
|
|||
|
||||
var url = GetOmdbUrl(string.Format("i={0}&plot=short&tomatoes=true&r=json", imdbParam), cancellationToken);
|
||||
|
||||
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
|
||||
using (var response = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var rootObject = _jsonSerializer.DeserializeFromStream<RootObject>(stream);
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
_jsonSerializer.SerializeToFile(rootObject, path);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
@ -335,25 +338,28 @@ namespace MediaBrowser.Providers.Omdb
|
|||
|
||||
var url = GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), cancellationToken);
|
||||
|
||||
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
|
||||
using (var response = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var rootObject = _jsonSerializer.DeserializeFromStream<SeasonRootObject>(stream);
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
_jsonSerializer.SerializeToFile(rootObject, path);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static Task<Stream> GetOmdbResponse(IHttpClient httpClient, string url, CancellationToken cancellationToken)
|
||||
public static Task<HttpResponseInfo> GetOmdbResponse(IHttpClient httpClient, string url, CancellationToken cancellationToken)
|
||||
{
|
||||
return httpClient.Get(new HttpRequestOptions
|
||||
return httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = true,
|
||||
EnableDefaultUserAgent = true
|
||||
});
|
||||
}, "GET");
|
||||
}
|
||||
|
||||
internal string GetDataFilePath(string imdbId)
|
||||
|
|
|
@ -91,13 +91,15 @@ namespace MediaBrowser.Providers.People
|
|||
|
||||
var url = string.Format(@"https://api.themoviedb.org/3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), MovieDbProvider.ApiKey);
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbProvider.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
var result = _jsonSerializer.DeserializeFromStream<PersonSearchResults>(json) ??
|
||||
new PersonSearchResults();
|
||||
|
@ -105,6 +107,7 @@ namespace MediaBrowser.Providers.People
|
|||
return result.Results.Select(i => GetSearchResult(i, tmdbImageUrl));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RemoteSearchResult GetSearchResult(PersonSearchResult i, string baseImageUrl)
|
||||
{
|
||||
|
@ -223,13 +226,15 @@ namespace MediaBrowser.Providers.People
|
|||
|
||||
var url = string.Format(@"https://api.themoviedb.org/3/person/{1}?api_key={0}&append_to_response=credits,images,external_ids", MovieDbProvider.ApiKey, id);
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbProvider.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
|
||||
|
||||
|
@ -239,6 +244,7 @@ namespace MediaBrowser.Providers.People
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetPersonDataPath(IApplicationPaths appPaths, string tmdbId)
|
||||
{
|
||||
|
|
|
@ -316,13 +316,15 @@ namespace MediaBrowser.Providers.TV
|
|||
|
||||
try
|
||||
{
|
||||
using (var response = await _httpClient.Get(new HttpRequestOptions
|
||||
using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = true
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var response = httpResponse.Content)
|
||||
{
|
||||
using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
||||
{
|
||||
|
@ -330,6 +332,7 @@ namespace MediaBrowser.Providers.TV
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (HttpException exception)
|
||||
{
|
||||
if (exception.StatusCode.HasValue && exception.StatusCode.Value == HttpStatusCode.NotFound)
|
||||
|
|
|
@ -125,17 +125,20 @@ namespace MediaBrowser.Providers.TV
|
|||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbProvider.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
return _jsonSerializer.DeserializeFromStream<RootObject>(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Task<HttpResponseInfo> GetResponse(string url, CancellationToken cancellationToken)
|
||||
{
|
||||
|
|
|
@ -214,17 +214,20 @@ namespace MediaBrowser.Providers.TV
|
|||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbProvider.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
return _jsonSerializer.DeserializeFromStream<RootObject>(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Episode
|
||||
{
|
||||
|
|
|
@ -352,13 +352,15 @@ namespace MediaBrowser.Providers.TV
|
|||
|
||||
RootObject mainResult;
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbProvider.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
mainResult = _jsonSerializer.DeserializeFromStream<RootObject>(json);
|
||||
|
||||
|
@ -367,6 +369,7 @@ namespace MediaBrowser.Providers.TV
|
|||
mainResult.ResultLanguage = language;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
|
@ -386,13 +389,15 @@ namespace MediaBrowser.Providers.TV
|
|||
url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language);
|
||||
}
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbProvider.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
var englishResult = _jsonSerializer.DeserializeFromStream<RootObject>(json);
|
||||
|
||||
|
@ -400,6 +405,7 @@ namespace MediaBrowser.Providers.TV
|
|||
mainResult.ResultLanguage = "en";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mainResult;
|
||||
}
|
||||
|
@ -449,13 +455,15 @@ namespace MediaBrowser.Providers.TV
|
|||
MovieDbProvider.ApiKey,
|
||||
externalSource);
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbProvider.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = response.Content)
|
||||
{
|
||||
var result = _jsonSerializer.DeserializeFromStream<MovieDbSearch.ExternalIdLookupResult>(json);
|
||||
|
||||
|
@ -481,6 +489,7 @@ namespace MediaBrowser.Providers.TV
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -142,17 +142,21 @@ namespace MediaBrowser.Providers.TV
|
|||
if (string.IsNullOrEmpty(lastUpdateTime))
|
||||
{
|
||||
// First get tvdb server time
|
||||
using (var stream = await _httpClient.Get(new HttpRequestOptions
|
||||
using (var response = await _httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = ServerTimeUrl,
|
||||
CancellationToken = cancellationToken,
|
||||
EnableHttpCompression = true,
|
||||
BufferContent = false
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
// First get tvdb server time
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
newUpdateTime = GetUpdateTime(stream);
|
||||
}
|
||||
}
|
||||
|
||||
existingDirectories.AddRange(missingSeries);
|
||||
|
||||
|
@ -238,14 +242,16 @@ namespace MediaBrowser.Providers.TV
|
|||
private async Task<Tuple<IEnumerable<string>, string>> GetSeriesIdsToUpdate(IEnumerable<string> existingSeriesIds, string lastUpdateTime, CancellationToken cancellationToken)
|
||||
{
|
||||
// First get last time
|
||||
using (var stream = await _httpClient.Get(new HttpRequestOptions
|
||||
using (var response = await _httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = string.Format(UpdatesUrl, lastUpdateTime),
|
||||
CancellationToken = cancellationToken,
|
||||
EnableHttpCompression = true,
|
||||
BufferContent = false
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var data = GetUpdatedSeriesIdList(stream);
|
||||
|
||||
|
@ -257,6 +263,7 @@ namespace MediaBrowser.Providers.TV
|
|||
return new Tuple<IEnumerable<string>, string>(seriesList, data.Item2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Tuple<List<string>, string> GetUpdatedSeriesIdList(Stream stream)
|
||||
{
|
||||
|
|
|
@ -216,13 +216,15 @@ namespace MediaBrowser.Providers.TV
|
|||
|
||||
var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, NormalizeLanguage(preferredMetadataLanguage));
|
||||
|
||||
using (var zipStream = await _httpClient.Get(new HttpRequestOptions
|
||||
using (var response = await _httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = false
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var zipStream = response.Content)
|
||||
{
|
||||
// Delete existing files
|
||||
DeleteXmlFiles(seriesDataPath);
|
||||
|
@ -236,6 +238,7 @@ namespace MediaBrowser.Providers.TV
|
|||
_zipClient.ExtractAllFromZip(ms, seriesDataPath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize all files, except for extracted episode files
|
||||
foreach (var file in _fileSystem.GetFilePaths(seriesDataPath, true).ToList()
|
||||
|
@ -260,17 +263,20 @@ namespace MediaBrowser.Providers.TV
|
|||
{
|
||||
var url = string.Format(GetSeriesByImdbId, id, NormalizeLanguage(language));
|
||||
|
||||
using (var result = await _httpClient.Get(new HttpRequestOptions
|
||||
using (var response = await _httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = false
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var result = response.Content)
|
||||
{
|
||||
return FindSeriesId(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string FindSeriesId(Stream stream)
|
||||
{
|
||||
|
@ -514,13 +520,15 @@ namespace MediaBrowser.Providers.TV
|
|||
|
||||
var comparableName = GetComparableName(name);
|
||||
|
||||
using (var stream = await _httpClient.Get(new HttpRequestOptions
|
||||
using (var response = await _httpClient.SendAsync(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
BufferContent = false
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
}, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var settings = _xmlSettings.Create(false);
|
||||
|
||||
|
@ -577,6 +585,7 @@ namespace MediaBrowser.Providers.TV
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchResults.Count == 0)
|
||||
{
|
||||
|
|
|
@ -33,6 +33,7 @@ using System.Collections.Generic;
|
|||
using System.Text;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mono.Nat
|
||||
{
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
<Compile Include="Upnp\Messages\Responses\CreatePortMappingResponseMessage.cs" />
|
||||
<Compile Include="Upnp\Messages\UpnpMessage.cs" />
|
||||
<Compile Include="Upnp\Searchers\UpnpSearcher.cs" />
|
||||
<Compile Include="Upnp\Upnp.cs" />
|
||||
<Compile Include="Upnp\UpnpNatDevice.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -208,14 +208,14 @@ namespace Mono.Nat
|
|||
}
|
||||
}
|
||||
|
||||
public static void Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint, NatProtocol protocol)
|
||||
public static async Task Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint, NatProtocol protocol)
|
||||
{
|
||||
switch (protocol)
|
||||
{
|
||||
case NatProtocol.Upnp:
|
||||
var searcher = new UpnpSearcher(Logger, HttpClient);
|
||||
searcher.DeviceFound += Searcher_DeviceFound;
|
||||
searcher.Handle(localAddress, deviceInfo, endpoint);
|
||||
await searcher.Handle(localAddress, deviceInfo, endpoint).ConfigureAwait(false);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unexpected protocol: " + protocol);
|
||||
|
|
|
@ -39,6 +39,7 @@ using System.Net.NetworkInformation;
|
|||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mono.Nat
|
||||
{
|
||||
|
@ -61,7 +62,7 @@ namespace Mono.Nat
|
|||
{
|
||||
}
|
||||
|
||||
public void Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint)
|
||||
public async Task Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint)
|
||||
{
|
||||
// No matter what, this method should never throw an exception. If something goes wrong
|
||||
// we should still be in a position to handle the next reply correctly.
|
||||
|
@ -82,6 +83,8 @@ namespace Mono.Nat
|
|||
UpnpNatDevice d = new UpnpNatDevice(localAddress, deviceInfo, endpoint, string.Empty, _logger, _httpClient);
|
||||
|
||||
NatUtility.Log("Fetching service list: {0}", d.HostEndPoint);
|
||||
await d.GetServicesList().ConfigureAwait(false);
|
||||
|
||||
OnDeviceFound(new DeviceEventArgs(d));
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Ben Motmans <ben.motmans@gmail.com>
|
||||
// Nicholas Terry <nick.i.terry@gmail.com>
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2007 Ben Motmans
|
||||
// Copyright (C) 2014 Nicholas Terry
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
internal class Upnp
|
||||
{
|
||||
protected readonly ILogger Logger;
|
||||
protected readonly IHttpClient HttpClient;
|
||||
|
||||
public Upnp(ILogger logger, IHttpClient httpClient)
|
||||
{
|
||||
Logger = logger;
|
||||
HttpClient = httpClient;
|
||||
}
|
||||
|
||||
public virtual Task<UpnpNatDevice> Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
|
||||
{
|
||||
// Convert it to a string for easy parsing
|
||||
string dataString = null;
|
||||
|
||||
|
||||
string urn;
|
||||
dataString = Encoding.UTF8.GetString(response);
|
||||
|
||||
if (NatUtility.Verbose)
|
||||
NatUtility.Log("UPnP Response: {0}", dataString);
|
||||
|
||||
/* For UPnP Port Mapping we need ot find either WANPPPConnection or WANIPConnection.
|
||||
Any other device type is no good to us for this purpose. See the IGP overview paper
|
||||
page 5 for an overview of device types and their hierarchy.
|
||||
http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf */
|
||||
|
||||
/* TODO: Currently we are assuming version 1 of the protocol. We should figure out which
|
||||
version it is and apply the correct URN. */
|
||||
|
||||
/* Some routers don't correctly implement the version ID on the URN, so we only search for the type
|
||||
prefix. */
|
||||
|
||||
string log = "UPnP Response: Router advertised a '{0}' service";
|
||||
StringComparison c = StringComparison.OrdinalIgnoreCase;
|
||||
if (dataString.IndexOf("urn:schemas-upnp-org:service:WANIPConnection:", c) != -1)
|
||||
{
|
||||
urn = "urn:schemas-upnp-org:service:WANIPConnection:1";
|
||||
NatUtility.Log(log, "urn:schemas-upnp-org:service:WANIPConnection:1");
|
||||
}
|
||||
else if (dataString.IndexOf("urn:schemas-upnp-org:service:WANPPPConnection:", c) != -1)
|
||||
{
|
||||
urn = "urn:schemas-upnp-org:service:WANPPPConnection:1";
|
||||
NatUtility.Log(log, "urn:schemas-upnp-org:service:WANPPPConnection:");
|
||||
}
|
||||
else
|
||||
throw new NotSupportedException("Received non-supported device type");
|
||||
|
||||
// We have an internet gateway device now
|
||||
var device = new UpnpNatDevice(localAddress, dataString, urn, Logger, HttpClient);
|
||||
return Task.FromResult(device);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -90,52 +90,101 @@ namespace Mono.Nat.Upnp
|
|||
}
|
||||
}
|
||||
|
||||
internal UpnpNatDevice(IPAddress localAddress, string deviceDetails, string serviceType, ILogger logger, IHttpClient httpClient)
|
||||
public async Task GetServicesList()
|
||||
{
|
||||
_logger = logger;
|
||||
_httpClient = httpClient;
|
||||
this.LastSeen = DateTime.Now;
|
||||
this.localAddress = localAddress;
|
||||
// Create a HTTPWebRequest to download the list of services the device offers
|
||||
var message = new GetServicesMessage(this.serviceDescriptionUrl, this.hostEndPoint, _logger);
|
||||
|
||||
// Split the string at the "location" section so i can extract the ipaddress and service description url
|
||||
string locationDetails = deviceDetails.Substring(deviceDetails.IndexOf("Location", StringComparison.OrdinalIgnoreCase) + 9).Split('\r')[0];
|
||||
this.serviceType = serviceType;
|
||||
|
||||
// Make sure we have no excess whitespace
|
||||
locationDetails = locationDetails.Trim();
|
||||
|
||||
// FIXME: Is this reliable enough. What if we get a hostname as opposed to a proper http address
|
||||
// Are we going to get addresses with the "http://" attached?
|
||||
if (locationDetails.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
|
||||
using (var response = await _httpClient.SendAsync(message.Encode(), message.Method).ConfigureAwait(false))
|
||||
{
|
||||
NatUtility.Log("Found device at: {0}", locationDetails);
|
||||
// This bit strings out the "http://" from the string
|
||||
locationDetails = locationDetails.Substring(7);
|
||||
|
||||
// We then split off the end of the string to get something like: 192.168.0.3:241 in our string
|
||||
string hostAddressAndPort = locationDetails.Remove(locationDetails.IndexOf('/'));
|
||||
|
||||
// From this we parse out the IP address and Port
|
||||
if (hostAddressAndPort.IndexOf(':') > 0)
|
||||
{
|
||||
this.hostEndPoint = new IPEndPoint(IPAddress.Parse(hostAddressAndPort.Remove(hostAddressAndPort.IndexOf(':'))),
|
||||
Convert.ToUInt16(hostAddressAndPort.Substring(hostAddressAndPort.IndexOf(':') + 1), System.Globalization.CultureInfo.InvariantCulture));
|
||||
OnServicesReceived(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
// there is no port specified, use default port (80)
|
||||
this.hostEndPoint = new IPEndPoint(IPAddress.Parse(hostAddressAndPort), 80);
|
||||
}
|
||||
|
||||
NatUtility.Log("Parsed device as: {0}", this.hostEndPoint.ToString());
|
||||
|
||||
// The service description URL is the remainder of the "locationDetails" string. The bit that was originally after the ip
|
||||
// and port information
|
||||
this.serviceDescriptionUrl = locationDetails.Substring(locationDetails.IndexOf('/'));
|
||||
}
|
||||
else
|
||||
private void OnServicesReceived(HttpResponseInfo response)
|
||||
{
|
||||
logger.Warn("Couldn't decode address: " + deviceDetails);
|
||||
int abortCount = 0;
|
||||
int bytesRead = 0;
|
||||
byte[] buffer = new byte[10240];
|
||||
StringBuilder servicesXml = new StringBuilder();
|
||||
XmlDocument xmldoc = new XmlDocument();
|
||||
|
||||
using (var s = response.Content)
|
||||
{
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
NatUtility.Log("{0}: Couldn't get services list: {1}", HostEndPoint, response.StatusCode);
|
||||
return; // FIXME: This the best thing to do??
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
bytesRead = s.Read(buffer, 0, buffer.Length);
|
||||
servicesXml.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead));
|
||||
try
|
||||
{
|
||||
xmldoc.LoadXml(servicesXml.ToString());
|
||||
break;
|
||||
}
|
||||
catch (XmlException)
|
||||
{
|
||||
// If we can't receive the entire XML within 500ms, then drop the connection
|
||||
// Unfortunately not all routers supply a valid ContentLength (mine doesn't)
|
||||
// so this hack is needed to keep testing our recieved data until it gets successfully
|
||||
// parsed by the xmldoc. Without this, the code will never pick up my router.
|
||||
if (abortCount++ > 50)
|
||||
{
|
||||
return;
|
||||
}
|
||||
NatUtility.Log("{0}: Couldn't parse services list", HostEndPoint);
|
||||
System.Threading.Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
NatUtility.Log("{0}: Parsed services list", HostEndPoint);
|
||||
XmlNamespaceManager ns = new XmlNamespaceManager(xmldoc.NameTable);
|
||||
ns.AddNamespace("ns", "urn:schemas-upnp-org:device-1-0");
|
||||
XmlNodeList nodes = xmldoc.SelectNodes("//*/ns:serviceList", ns);
|
||||
|
||||
foreach (XmlNode node in nodes)
|
||||
{
|
||||
//Go through each service there
|
||||
foreach (XmlNode service in node.ChildNodes)
|
||||
{
|
||||
//If the service is a WANIPConnection, then we have what we want
|
||||
string type = service["serviceType"].InnerText;
|
||||
NatUtility.Log("{0}: Found service: {1}", HostEndPoint, type);
|
||||
StringComparison c = StringComparison.OrdinalIgnoreCase;
|
||||
// TODO: Add support for version 2 of UPnP.
|
||||
if (type.Equals("urn:schemas-upnp-org:service:WANPPPConnection:1", c) ||
|
||||
type.Equals("urn:schemas-upnp-org:service:WANIPConnection:1", c))
|
||||
{
|
||||
this.controlUrl = service["controlURL"].InnerText;
|
||||
NatUtility.Log("{0}: Found upnp service at: {1}", HostEndPoint, controlUrl);
|
||||
try
|
||||
{
|
||||
Uri u = new Uri(controlUrl);
|
||||
if (u.IsAbsoluteUri)
|
||||
{
|
||||
EndPoint old = hostEndPoint;
|
||||
this.hostEndPoint = new IPEndPoint(IPAddress.Parse(u.Host), u.Port);
|
||||
NatUtility.Log("{0}: Absolute URI detected. Host address is now: {1}", old, HostEndPoint);
|
||||
this.controlUrl = controlUrl.Substring(u.GetLeftPart(UriPartial.Authority).Length);
|
||||
NatUtility.Log("{0}: New control url: {1}", HostEndPoint, controlUrl);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
NatUtility.Log("{0}: Assuming control Uri is relative: {1}", HostEndPoint, controlUrl);
|
||||
}
|
||||
NatUtility.Log("{0}: Handshake Complete", HostEndPoint);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If we get here, it means that we didn't get WANIPConnection service, which means no uPnP forwarding
|
||||
//So we don't invoke the callback, so this device is never added to our lists
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,10 +220,13 @@ namespace Mono.Nat.Upnp
|
|||
get { return serviceType; }
|
||||
}
|
||||
|
||||
public override Task CreatePortMap(Mapping mapping)
|
||||
public override async Task CreatePortMap(Mapping mapping)
|
||||
{
|
||||
CreatePortMappingMessage message = new CreatePortMappingMessage(mapping, localAddress, this);
|
||||
return _httpClient.SendAsync(message.Encode(), message.Method);
|
||||
using (await _httpClient.SendAsync(message.Encode(), message.Method).ConfigureAwait(false))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("3.2.33.13")]
|
||||
[assembly: AssemblyVersion("3.2.33.14")]
|
||||
|
|
Loading…
Reference in New Issue
Block a user