123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- #pragma warning disable CS1591
- using System;
- using System.Globalization;
- using System.IO;
- using System.Net.Http;
- using System.Net.Http.Headers;
- using System.Net.Mime;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Xml.Linq;
- using Emby.Dlna.Common;
- using MediaBrowser.Common.Net;
- namespace Emby.Dlna.PlayTo
- {
- public class SsdpHttpClient
- {
- private const string USERAGENT = "Microsoft-Windows/6.2 UPnP/1.0 Microsoft-DLNA DLNADOC/1.50";
- private const string FriendlyName = "Jellyfin";
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- private readonly IHttpClientFactory _httpClientFactory;
- public SsdpHttpClient(IHttpClientFactory httpClientFactory)
- {
- _httpClientFactory = httpClientFactory;
- }
- public async Task<XDocument> SendCommandAsync(
- string baseUrl,
- DeviceService service,
- string command,
- string postData,
- string header = null,
- CancellationToken cancellationToken = default)
- {
- var url = NormalizeServiceUrl(baseUrl, service.ControlUrl);
- using var response = await PostSoapDataAsync(
- url,
- $"\"{service.ServiceType}#{command}\"",
- postData,
- header,
- cancellationToken)
- .ConfigureAwait(false);
- await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
- using var reader = new StreamReader(stream, Encoding.UTF8);
- return XDocument.Parse(
- await reader.ReadToEndAsync().ConfigureAwait(false),
- LoadOptions.PreserveWhitespace);
- }
- private static string NormalizeServiceUrl(string baseUrl, string serviceUrl)
- {
- // If it's already a complete url, don't stick anything onto the front of it
- if (serviceUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase))
- {
- return serviceUrl;
- }
- if (!serviceUrl.StartsWith("/", StringComparison.Ordinal))
- {
- serviceUrl = "/" + serviceUrl;
- }
- return baseUrl + serviceUrl;
- }
- public async Task SubscribeAsync(
- string url,
- string ip,
- int port,
- string localIp,
- int eventport,
- int timeOut = 3600)
- {
- using var options = new HttpRequestMessage(new HttpMethod("SUBSCRIBE"), url);
- options.Headers.UserAgent.ParseAdd(USERAGENT);
- options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(_usCulture));
- options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(_usCulture) + ">");
- options.Headers.TryAddWithoutValidation("NT", "upnp:event");
- options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(_usCulture));
- using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
- .SendAsync(options, HttpCompletionOption.ResponseHeadersRead)
- .ConfigureAwait(false);
- }
- public async Task<XDocument> GetDataAsync(string url, CancellationToken cancellationToken)
- {
- using var options = new HttpRequestMessage(HttpMethod.Get, url);
- options.Headers.UserAgent.ParseAdd(USERAGENT);
- options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
- using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
- await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
- using var reader = new StreamReader(stream, Encoding.UTF8);
- return XDocument.Parse(
- await reader.ReadToEndAsync().ConfigureAwait(false),
- LoadOptions.PreserveWhitespace);
- }
- private async Task<HttpResponseMessage> PostSoapDataAsync(
- string url,
- string soapAction,
- string postData,
- string header,
- CancellationToken cancellationToken)
- {
- if (soapAction[0] != '\"')
- {
- soapAction = $"\"{soapAction}\"";
- }
- using var options = new HttpRequestMessage(HttpMethod.Post, url);
- options.Headers.UserAgent.ParseAdd(USERAGENT);
- options.Headers.TryAddWithoutValidation("SOAPACTION", soapAction);
- options.Headers.TryAddWithoutValidation("Pragma", "no-cache");
- options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
- if (!string.IsNullOrEmpty(header))
- {
- options.Headers.TryAddWithoutValidation("contentFeatures.dlna.org", header);
- }
- options.Content = new StringContent(postData, Encoding.UTF8, MediaTypeNames.Text.Xml);
- return await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
- }
- }
- }
|