avoid buffering http responses

This commit is contained in:
Luke Pulverenti
2016-10-06 14:55:01 -04:00
parent 83606d82d5
commit a69ca6c55b
63 changed files with 448 additions and 267 deletions

View File

@@ -127,7 +127,8 @@ namespace MediaBrowser.Server.Implementations.Connect
// Seeing block length errors with our server
EnableHttpCompression = false,
PreferIpv4 = preferIpv4
PreferIpv4 = preferIpv4,
BufferContent = false
}).ConfigureAwait(false))
{

View File

@@ -266,7 +266,8 @@ namespace MediaBrowser.Server.Implementations.Connect
var options = new HttpRequestOptions
{
Url = url,
CancellationToken = CancellationToken.None
CancellationToken = CancellationToken.None,
BufferContent = false
};
options.SetPostData(postData);
@@ -314,7 +315,8 @@ namespace MediaBrowser.Server.Implementations.Connect
var options = new HttpRequestOptions
{
Url = url,
CancellationToken = CancellationToken.None
CancellationToken = CancellationToken.None,
BufferContent = false
};
options.SetPostData(postData);
@@ -464,7 +466,8 @@ namespace MediaBrowser.Server.Implementations.Connect
var options = new HttpRequestOptions
{
Url = url,
CancellationToken = CancellationToken.None
CancellationToken = CancellationToken.None,
BufferContent = false
};
var accessToken = Guid.NewGuid().ToString("N");
@@ -599,7 +602,8 @@ namespace MediaBrowser.Server.Implementations.Connect
var options = new HttpRequestOptions
{
Url = url,
CancellationToken = CancellationToken.None
CancellationToken = CancellationToken.None,
BufferContent = false
};
var accessToken = Guid.NewGuid().ToString("N");
@@ -652,7 +656,8 @@ namespace MediaBrowser.Server.Implementations.Connect
var options = new HttpRequestOptions
{
Url = url,
CancellationToken = CancellationToken.None
CancellationToken = CancellationToken.None,
BufferContent = false
};
var postData = new Dictionary<string, string>
@@ -726,7 +731,8 @@ namespace MediaBrowser.Server.Implementations.Connect
var options = new HttpRequestOptions
{
CancellationToken = cancellationToken,
Url = url
Url = url,
BufferContent = false
};
SetServerAccessToken(options);
@@ -790,7 +796,8 @@ namespace MediaBrowser.Server.Implementations.Connect
var options = new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken
CancellationToken = cancellationToken,
BufferContent = false
};
SetServerAccessToken(options);
@@ -1078,7 +1085,8 @@ namespace MediaBrowser.Server.Implementations.Connect
var options = new HttpRequestOptions
{
Url = url,
CancellationToken = CancellationToken.None
CancellationToken = CancellationToken.None,
BufferContent = false
};
var postData = new Dictionary<string, string>
@@ -1126,7 +1134,8 @@ namespace MediaBrowser.Server.Implementations.Connect
var options = new HttpRequestOptions
{
Url = GetConnectUrl("user/authenticate")
Url = GetConnectUrl("user/authenticate"),
BufferContent = false
};
options.SetPostData(new Dictionary<string, string>

View File

@@ -1176,6 +1176,12 @@ namespace MediaBrowser.Server.Implementations.Dto
.Except(foundArtists, new DistinctNameComparer())
.Select(i =>
{
// This should not be necessary but we're seeing some cases of it
if (string.IsNullOrWhiteSpace(i))
{
return null;
}
var artist = _libraryManager.GetArtist(i);
if (artist != null)
{

View File

@@ -64,7 +64,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
EnableHttpCompression = false,
LogRequest = false,
LogErrors = logErrors
LogErrors = logErrors,
BufferContent = false
};
options.SetPostData(data);
@@ -114,7 +115,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
EnableHttpCompression = false,
LogRequest = false,
LogErrors = logErrors
LogErrors = logErrors,
BufferContent = false
};
options.SetPostData(data);

View File

@@ -19,6 +19,7 @@ using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Security;
using MediaBrowser.Model.Extensions;
@@ -45,16 +46,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private readonly IServerConfigurationManager _config;
private readonly INetworkManager _networkManager;
private readonly IMemoryStreamProvider _memoryStreamProvider;
public HttpListenerHost(IApplicationHost applicationHost,
ILogManager logManager,
IServerConfigurationManager config,
string serviceName,
string defaultRedirectPath, INetworkManager networkManager, params Assembly[] assembliesWithServices)
string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamProvider memoryStreamProvider, params Assembly[] assembliesWithServices)
: base(serviceName, assembliesWithServices)
{
DefaultRedirectPath = defaultRedirectPath;
_networkManager = networkManager;
_memoryStreamProvider = memoryStreamProvider;
_config = config;
_logger = logManager.GetLogger("HttpServer");
@@ -95,6 +98,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
container.Adapter = _containerAdapter;
Plugins.RemoveAll(x => x is NativeTypesFeature);
Plugins.Add(new SwaggerFeature());
Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization"));
@@ -179,7 +183,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private IHttpListener GetListener()
{
return new WebSocketSharpListener(_logger, CertificatePath);
return new WebSocketSharpListener(_logger, CertificatePath, _memoryStreamProvider);
}
private void OnWebSocketConnecting(WebSocketConnectingEventArgs args)

View File

@@ -1,4 +1,5 @@
using MediaBrowser.Common;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net;
@@ -15,23 +16,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <summary>
/// Creates the server.
/// </summary>
/// <param name="applicationHost">The application host.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="config">The configuration.</param>
/// <param name="_networkmanager">The _networkmanager.</param>
/// <param name="serverName">Name of the server.</param>
/// <param name="defaultRedirectpath">The default redirectpath.</param>
/// <returns>IHttpServer.</returns>
public static IHttpServer CreateServer(IApplicationHost applicationHost,
ILogManager logManager,
IServerConfigurationManager config,
INetworkManager _networkmanager,
IMemoryStreamProvider streamProvider,
string serverName,
string defaultRedirectpath)
{
LogManager.LogFactory = new ServerLogFactory(logManager);
return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, _networkmanager);
return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, _networkmanager, streamProvider);
}
}
}

View File

@@ -39,11 +39,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
if (boundary == null)
return;
using (var requestStream = GetSubStream(InputStream))
using (var requestStream = GetSubStream(InputStream, _memoryStreamProvider))
{
//DB: 30/01/11 - Hack to get around non-seekable stream and received HTTP request
//Not ending with \r\n?
var ms = new MemoryStream(32 * 1024);
var ms = _memoryStreamProvider.CreateNew(32 * 1024);
await requestStream.CopyToAsync(ms).ConfigureAwait(false);
var input = ms;
@@ -229,9 +229,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
async Task LoadWwwForm()
{
using (Stream input = GetSubStream(InputStream))
using (Stream input = GetSubStream(InputStream, _memoryStreamProvider))
{
using (var ms = new MemoryStream())
using (var ms = _memoryStreamProvider.CreateNew())
{
await input.CopyToAsync(ms).ConfigureAwait(false);
ms.Position = 0;

View File

@@ -9,6 +9,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{
@@ -18,11 +19,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
private readonly ILogger _logger;
private readonly string _certificatePath;
private readonly IMemoryStreamProvider _memoryStreamProvider;
public WebSocketSharpListener(ILogger logger, string certificatePath)
public WebSocketSharpListener(ILogger logger, string certificatePath, IMemoryStreamProvider memoryStreamProvider)
{
_logger = logger;
_certificatePath = certificatePath;
_memoryStreamProvider = memoryStreamProvider;
}
public Action<Exception, IRequest> ErrorHandler { get; set; }
@@ -148,7 +151,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{
var operationName = httpContext.Request.GetOperationName();
var req = new WebSocketSharpRequest(httpContext, operationName, RequestAttributes.None, _logger);
var req = new WebSocketSharpRequest(httpContext, operationName, RequestAttributes.None, _logger, _memoryStreamProvider);
req.RequestAttributes = req.GetAttributes();
return req;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
using Funq;
using MediaBrowser.Common.IO;
using MediaBrowser.Model.Logging;
using ServiceStack;
using ServiceStack.Host;
@@ -16,11 +17,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
public Container Container { get; set; }
private readonly HttpListenerRequest request;
private readonly IHttpResponse response;
private IMemoryStreamProvider _memoryStreamProvider;
public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, RequestAttributes requestAttributes, ILogger logger)
public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, RequestAttributes requestAttributes, ILogger logger, IMemoryStreamProvider memoryStreamProvider)
{
this.OperationName = operationName;
this.RequestAttributes = requestAttributes;
_memoryStreamProvider = memoryStreamProvider;
this.request = httpContext.Request;
this.response = new WebSocketSharpResponse(logger, httpContext.Response, this);
@@ -403,7 +406,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
set
{
bufferedStream = value
? bufferedStream ?? new MemoryStream(request.InputStream.ReadFully())
? bufferedStream ?? _memoryStreamProvider.CreateNew(request.InputStream.ReadFully())
: null;
}
}
@@ -447,7 +450,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
}
}
static Stream GetSubStream(Stream stream)
static Stream GetSubStream(Stream stream, IMemoryStreamProvider streamProvider)
{
if (stream is MemoryStream)
{

View File

@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using MediaBrowser.Common.IO;
using ServiceStack;
namespace MediaBrowser.Server.Implementations.HttpServer
@@ -17,7 +18,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private ILogger Logger { get; set; }
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
/// <summary>
/// Gets or sets the source stream.
/// </summary>
@@ -39,6 +40,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public Action OnComplete { get; set; }
public Action OnError { get; set; }
private readonly byte[] _bytes;
/// <summary>
/// Initializes a new instance of the <see cref="StreamWriter" /> class.
@@ -73,6 +75,17 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public StreamWriter(byte[] source, string contentType, ILogger logger)
: this(new MemoryStream(source), contentType, logger)
{
if (string.IsNullOrEmpty(contentType))
{
throw new ArgumentNullException("contentType");
}
_bytes = source;
Logger = logger;
Options["Content-Type"] = contentType;
Options["Content-Length"] = source.Length.ToString(UsCulture);
}
private const int BufferSize = 81920;
@@ -85,9 +98,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{
try
{
using (var src = SourceStream)
if (_bytes != null)
{
src.CopyTo(responseStream, BufferSize);
responseStream.Write(_bytes, 0, _bytes.Length);
}
else
{
using (var src = SourceStream)
{
src.CopyTo(responseStream, BufferSize);
}
}
}
catch (Exception ex)
@@ -114,9 +134,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{
try
{
using (var src = SourceStream)
if (_bytes != null)
{
await src.CopyToAsync(responseStream, BufferSize).ConfigureAwait(false);
await responseStream.WriteAsync(_bytes, 0, _bytes.Length);
}
else
{
using (var src = SourceStream)
{
await src.CopyToAsync(responseStream, BufferSize).ConfigureAwait(false);
}
}
}
catch (Exception ex)

View File

@@ -846,7 +846,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
Url = ApiUrl + "/lineups/" + info.ListingsId,
UserAgent = UserAgent,
CancellationToken = cancellationToken,
LogErrorResponseBody = true
LogErrorResponseBody = true,
BufferContent = false
};
httpOptions.RequestHeaders["token"] = token;

View File

@@ -558,7 +558,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return item;
}
private async Task<LiveTvProgram> GetProgram(ProgramInfo info, Dictionary<Guid, LiveTvProgram> allExistingPrograms, LiveTvChannel channel, ChannelType channelType, string serviceName, CancellationToken cancellationToken)
private Tuple<LiveTvProgram, bool, bool> GetProgram(ProgramInfo info, Dictionary<Guid, LiveTvProgram> allExistingPrograms, LiveTvChannel channel, ChannelType channelType, string serviceName, CancellationToken cancellationToken)
{
var id = _tvDtoService.GetInternalProgramId(serviceName, info.Id);
@@ -671,13 +671,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
}
var isUpdated = false;
if (isNew)
{
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
}
else if (forceUpdate || string.IsNullOrWhiteSpace(info.Etag))
{
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
isUpdated = true;
}
else
{
@@ -687,13 +687,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (!string.Equals(etag, item.ExternalEtag, StringComparison.OrdinalIgnoreCase))
{
item.ExternalEtag = etag;
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
isUpdated = true;
}
}
_providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem));
return item;
return new Tuple<LiveTvProgram, bool, bool>(item, isNew, isUpdated);
}
private async Task<Guid> CreateRecordingRecord(RecordingInfo info, string serviceName, Guid parentFolderId, CancellationToken cancellationToken)
@@ -1289,9 +1287,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}).Cast<LiveTvProgram>().ToDictionary(i => i.Id);
var newPrograms = new List<LiveTvProgram>();
var updatedPrograms = new List<LiveTvProgram>();
foreach (var program in channelPrograms)
{
var programItem = await GetProgram(program, existingPrograms, currentChannel, currentChannel.ChannelType, service.Name, cancellationToken).ConfigureAwait(false);
var programTuple = GetProgram(program, existingPrograms, currentChannel, currentChannel.ChannelType, service.Name, cancellationToken);
var programItem = programTuple.Item1;
if (programTuple.Item2)
{
newPrograms.Add(programItem);
}
else if (programTuple.Item3)
{
updatedPrograms.Add(programItem);
}
programs.Add(programItem.Id);
@@ -1321,6 +1332,26 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
}
if (newPrograms.Count > 0)
{
await _libraryManager.CreateItems(newPrograms, cancellationToken).ConfigureAwait(false);
}
// TODO: Do this in bulk
foreach (var program in updatedPrograms)
{
await _libraryManager.UpdateItem(program, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
}
foreach (var program in newPrograms)
{
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem));
}
foreach (var program in updatedPrograms)
{
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem));
}
currentChannel.IsMovie = isMovie;
currentChannel.IsNews = isNews;
currentChannel.IsSports = isSports;

View File

@@ -12,6 +12,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Dlna;
namespace MediaBrowser.Server.Implementations.LiveTv
{
@@ -138,7 +139,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
try
{
await AddMediaInfo(stream, isAudio, cancellationToken).ConfigureAwait(false);
await AddMediaInfoInternal(stream, isAudio, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -207,6 +208,85 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
}
private async Task AddMediaInfoInternal(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
{
var originalRuntime = mediaSource.RunTimeTicks;
var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
{
InputPath = mediaSource.Path,
Protocol = mediaSource.Protocol,
MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
ExtractChapters = false
}, cancellationToken).ConfigureAwait(false);
mediaSource.Bitrate = info.Bitrate;
mediaSource.Container = info.Container;
mediaSource.Formats = info.Formats;
mediaSource.MediaStreams = info.MediaStreams;
mediaSource.RunTimeTicks = info.RunTimeTicks;
mediaSource.Size = info.Size;
mediaSource.Timestamp = info.Timestamp;
mediaSource.Video3DFormat = info.Video3DFormat;
mediaSource.VideoType = info.VideoType;
mediaSource.DefaultSubtitleStreamIndex = null;
// Null this out so that it will be treated like a live stream
if (!originalRuntime.HasValue)
{
mediaSource.RunTimeTicks = null;
}
var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
if (audioStream == null || audioStream.Index == -1)
{
mediaSource.DefaultAudioStreamIndex = null;
}
else
{
mediaSource.DefaultAudioStreamIndex = audioStream.Index;
}
var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video);
if (videoStream != null)
{
if (!videoStream.BitRate.HasValue)
{
var width = videoStream.Width ?? 1920;
if (width >= 1900)
{
videoStream.BitRate = 8000000;
}
else if (width >= 1260)
{
videoStream.BitRate = 3000000;
}
else if (width >= 700)
{
videoStream.BitRate = 1000000;
}
}
}
// Try to estimate this
if (!mediaSource.Bitrate.HasValue)
{
var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
if (total > 0)
{
mediaSource.Bitrate = total;
}
}
}
public Task CloseMediaSource(string liveStreamId)
{
return _liveTvManager.CloseLiveStream(liveStreamId);

View File

@@ -252,84 +252,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
//}
}
private async Task AddMediaInfoInternal(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
{
var originalRuntime = mediaSource.RunTimeTicks;
var info = await MediaEncoder.GetMediaInfo(new MediaInfoRequest
{
InputPath = mediaSource.Path,
Protocol = mediaSource.Protocol,
MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
ExtractChapters = false
}, cancellationToken).ConfigureAwait(false);
mediaSource.Bitrate = info.Bitrate;
mediaSource.Container = info.Container;
mediaSource.Formats = info.Formats;
mediaSource.MediaStreams = info.MediaStreams;
mediaSource.RunTimeTicks = info.RunTimeTicks;
mediaSource.Size = info.Size;
mediaSource.Timestamp = info.Timestamp;
mediaSource.Video3DFormat = info.Video3DFormat;
mediaSource.VideoType = info.VideoType;
mediaSource.DefaultSubtitleStreamIndex = null;
// Null this out so that it will be treated like a live stream
if (!originalRuntime.HasValue)
{
mediaSource.RunTimeTicks = null;
}
var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
if (audioStream == null || audioStream.Index == -1)
{
mediaSource.DefaultAudioStreamIndex = null;
}
else
{
mediaSource.DefaultAudioStreamIndex = audioStream.Index;
}
var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video);
if (videoStream != null)
{
if (!videoStream.BitRate.HasValue)
{
var width = videoStream.Width ?? 1920;
if (width >= 1900)
{
videoStream.BitRate = 8000000;
}
else if (width >= 1260)
{
videoStream.BitRate = 3000000;
}
else if (width >= 700)
{
videoStream.BitRate = 1000000;
}
}
}
// Try to estimate this
if (!mediaSource.Bitrate.HasValue)
{
var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
if (total > 0)
{
mediaSource.Bitrate = total;
}
}
}
protected abstract bool IsValidChannelId(string channelId);
protected LiveTvOptions GetConfiguration()

View File

@@ -88,7 +88,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
using (var stream = await _httpClient.Get(new HttpRequestOptions
{
Url = string.Format("{0}/discover.json", url),
CancellationToken = CancellationToken.None
CancellationToken = CancellationToken.None,
BufferContent = false
}))
{
var response = _json.DeserializeFromStream<HdHomerunHost.DiscoverResponse>(stream);

View File

@@ -72,7 +72,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
var options = new HttpRequestOptions
{
Url = string.Format("{0}/lineup.json", GetApiUrl(info, false)),
CancellationToken = cancellationToken
CancellationToken = cancellationToken,
BufferContent = false
};
using (var stream = await _httpClient.Get(options))
{
@@ -124,7 +125,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
CancellationToken = cancellationToken,
CacheLength = TimeSpan.FromDays(1),
CacheMode = CacheMode.Unconditional,
TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds)
TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds),
BufferContent = false
}))
{
var response = JsonSerializer.DeserializeFromStream<DiscoverResponse>(stream);
@@ -165,7 +167,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
Url = string.Format("{0}/tuners.html", GetApiUrl(info, false)),
CancellationToken = cancellationToken,
TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds)
TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds),
BufferContent = false
}))
{
var tuners = new List<LiveTvTunerInfo>();
@@ -538,7 +541,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
using (var stream = await _httpClient.Get(new HttpRequestOptions
{
Url = string.Format("{0}/discover.json", GetApiUrl(info, false)),
CancellationToken = CancellationToken.None
CancellationToken = CancellationToken.None,
BufferContent = false
}))
{
var response = JsonSerializer.DeserializeFromStream<DiscoverResponse>(stream);

View File

@@ -12,6 +12,7 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Server.Implementations.LiveTv.EmbyTV;
using System.Collections.Generic;
using System.Linq;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
@@ -139,7 +140,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
}).ConfigureAwait(false);
}
private List<Tuple<Stream, CancellationToken, TaskCompletionSource<bool>>> _additionalStreams = new List<Tuple<Stream, CancellationToken, TaskCompletionSource<bool>>>();
private readonly List<Tuple<Stream, CancellationToken, TaskCompletionSource<bool>>> _additionalStreams = new List<Tuple<Stream, CancellationToken, TaskCompletionSource<bool>>>();
public Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
{
@@ -186,7 +187,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
foreach (var additionalStream in _additionalStreams)
var additionalStreams = _additionalStreams.ToList();
foreach (var additionalStream in additionalStreams)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -196,6 +198,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
}
catch (Exception ex)
{
_logger.ErrorException("Error writing HDHR data to stream", ex);
PopAdditionalStream(additionalStream, ex);
}
}

View File

@@ -81,7 +81,8 @@ namespace MediaBrowser.Server.Implementations.News
{
Url = "http://emby.media/community/index.php?/blog/rss/1-media-browser-developers-blog",
Progress = new Progress<double>(),
UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.42 Safari/537.36"
UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.42 Safari/537.36",
BufferContent = false
};
using (var stream = await _httpClient.Get(requestOptions).ConfigureAwait(false))

View File

@@ -4,6 +4,7 @@ using MediaBrowser.Model.Serialization;
using System;
using System.Data;
using System.IO;
using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Persistence
{
@@ -51,18 +52,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <summary>
/// Gets a stream from a DataReader at a given ordinal
/// </summary>
/// <param name="reader">The reader.</param>
/// <param name="ordinal">The ordinal.</param>
/// <returns>Stream.</returns>
/// <exception cref="System.ArgumentNullException">reader</exception>
public static Stream GetMemoryStream(this IDataReader reader, int ordinal)
public static Stream GetMemoryStream(this IDataReader reader, int ordinal, IMemoryStreamProvider streamProvider)
{
if (reader == null)
{
throw new ArgumentNullException("reader");
}
var memoryStream = new MemoryStream();
var memoryStream = streamProvider.CreateNew();
var num = 0L;
var array = new byte[4096];
long bytes;
@@ -132,18 +131,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <summary>
/// Serializes to bytes.
/// </summary>
/// <param name="json">The json.</param>
/// <param name="obj">The obj.</param>
/// <returns>System.Byte[][].</returns>
/// <exception cref="System.ArgumentNullException">obj</exception>
public static byte[] SerializeToBytes(this IJsonSerializer json, object obj)
public static byte[] SerializeToBytes(this IJsonSerializer json, object obj, IMemoryStreamProvider streamProvider)
{
if (obj == null)
{
throw new ArgumentNullException("obj");
}
using (var stream = new MemoryStream())
using (var stream = streamProvider.CreateNew())
{
json.SerializeToStream(obj, stream);
return stream.ToArray();

View File

@@ -10,6 +10,7 @@ using System.Data;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Persistence
{
@@ -18,10 +19,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary>
public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository
{
public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IDbConnector dbConnector)
private readonly IMemoryStreamProvider _memoryStreamProvider;
public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IDbConnector dbConnector, IMemoryStreamProvider memoryStreamProvider)
: base(logManager, dbConnector)
{
_jsonSerializer = jsonSerializer;
_memoryStreamProvider = memoryStreamProvider;
DbFilePath = Path.Combine(appPaths.DataPath, "displaypreferences.db");
}
@@ -82,7 +86,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
cancellationToken.ThrowIfCancellationRequested();
var serialized = _jsonSerializer.SerializeToBytes(displayPreferences);
var serialized = _jsonSerializer.SerializeToBytes(displayPreferences, _memoryStreamProvider);
using (var connection = await CreateConnection().ConfigureAwait(false))
{
@@ -166,7 +170,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
foreach (var displayPreference in displayPreferences)
{
var serialized = _jsonSerializer.SerializeToBytes(displayPreference);
var serialized = _jsonSerializer.SerializeToBytes(displayPreference, _memoryStreamProvider);
using (var cmd = connection.CreateCommand())
{
@@ -246,7 +250,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
if (reader.Read())
{
using (var stream = reader.GetMemoryStream(0))
using (var stream = reader.GetMemoryStream(0, _memoryStreamProvider))
{
return _jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream);
}
@@ -283,7 +287,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
while (reader.Read())
{
using (var stream = reader.GetMemoryStream(0))
using (var stream = reader.GetMemoryStream(0, _memoryStreamProvider))
{
list.Add(_jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream));
}

View File

@@ -19,6 +19,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Playlists;
@@ -95,11 +96,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _updateInheritedTagsCommand;
public const int LatestSchemaVersion = 109;
private readonly IMemoryStreamProvider _memoryStreamProvider;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
/// </summary>
public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager, IDbConnector connector)
public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager, IDbConnector connector, IMemoryStreamProvider memoryStreamProvider)
: base(logManager, connector)
{
if (config == null)
@@ -113,6 +115,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
_config = config;
_jsonSerializer = jsonSerializer;
_memoryStreamProvider = memoryStreamProvider;
_criticReviewsPath = Path.Combine(_config.ApplicationPaths.DataPath, "critic-reviews");
DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db");
@@ -724,7 +727,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveItemCommand.GetParameter(index++).Value = item.Id;
_saveItemCommand.GetParameter(index++).Value = item.GetType().FullName;
_saveItemCommand.GetParameter(index++).Value = _jsonSerializer.SerializeToBytes(item);
_saveItemCommand.GetParameter(index++).Value = _jsonSerializer.SerializeToBytes(item, _memoryStreamProvider);
_saveItemCommand.GetParameter(index++).Value = item.Path;
@@ -1075,7 +1078,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
BaseItem item = null;
using (var stream = reader.GetMemoryStream(1))
using (var stream = reader.GetMemoryStream(1, _memoryStreamProvider))
{
try
{

View File

@@ -9,6 +9,7 @@ using System.Data;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Persistence
{
@@ -18,10 +19,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
public class SqliteUserRepository : BaseSqliteRepository, IUserRepository
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IMemoryStreamProvider _memoryStreamProvider;
public SqliteUserRepository(ILogManager logManager, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer, IDbConnector dbConnector) : base(logManager, dbConnector)
public SqliteUserRepository(ILogManager logManager, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer, IDbConnector dbConnector, IMemoryStreamProvider memoryStreamProvider) : base(logManager, dbConnector)
{
_jsonSerializer = jsonSerializer;
_memoryStreamProvider = memoryStreamProvider;
DbFilePath = Path.Combine(appPaths.DataPath, "users.db");
}
@@ -75,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
cancellationToken.ThrowIfCancellationRequested();
var serialized = _jsonSerializer.SerializeToBytes(user);
var serialized = _jsonSerializer.SerializeToBytes(user, _memoryStreamProvider);
cancellationToken.ThrowIfCancellationRequested();
@@ -150,7 +153,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var id = reader.GetGuid(0);
using (var stream = reader.GetMemoryStream(1))
using (var stream = reader.GetMemoryStream(1, _memoryStreamProvider))
{
var user = _jsonSerializer.DeserializeFromStream<User>(stream);
user.Id = id;

View File

@@ -17,7 +17,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
public override bool IsVisible(User user)
{
return base.IsVisible(user) && GetChildren(user, false).Any();
return base.IsVisible(user);
}
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)

View File

@@ -13,6 +13,7 @@ using System.Linq;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.ServerManager
{
@@ -72,6 +73,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
private readonly List<IWebSocketListener> _webSocketListeners = new List<IWebSocketListener>();
private bool _disposed;
private readonly IMemoryStreamProvider _memoryStreamProvider;
/// <summary>
/// Initializes a new instance of the <see cref="ServerManager" /> class.
@@ -81,7 +83,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
/// <param name="logger">The logger.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <exception cref="System.ArgumentNullException">applicationHost</exception>
public ServerManager(IServerApplicationHost applicationHost, IJsonSerializer jsonSerializer, ILogger logger, IServerConfigurationManager configurationManager)
public ServerManager(IServerApplicationHost applicationHost, IJsonSerializer jsonSerializer, ILogger logger, IServerConfigurationManager configurationManager, IMemoryStreamProvider memoryStreamProvider)
{
if (applicationHost == null)
{
@@ -100,6 +102,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
_jsonSerializer = jsonSerializer;
_applicationHost = applicationHost;
ConfigurationManager = configurationManager;
_memoryStreamProvider = memoryStreamProvider;
}
/// <summary>
@@ -150,7 +153,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
return;
}
var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, _logger)
var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, _logger, _memoryStreamProvider)
{
OnReceive = ProcessWebSocketMessageReceived,
Url = e.Url,

View File

@@ -9,6 +9,7 @@ using System.Collections.Specialized;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.IO;
using UniversalDetector;
namespace MediaBrowser.Server.Implementations.ServerManager
@@ -78,7 +79,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager
/// </summary>
/// <value>The query string.</value>
public NameValueCollection QueryString { get; set; }
private readonly IMemoryStreamProvider _memoryStreamProvider;
/// <summary>
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
/// </summary>
@@ -87,7 +89,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="logger">The logger.</param>
/// <exception cref="System.ArgumentNullException">socket</exception>
public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger)
public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger, IMemoryStreamProvider memoryStreamProvider)
{
if (socket == null)
{
@@ -113,6 +115,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
_socket.OnReceive = OnReceiveInternal;
RemoteEndPoint = remoteEndPoint;
_logger = logger;
_memoryStreamProvider = memoryStreamProvider;
socket.Closed += socket_Closed;
}
@@ -149,7 +152,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
{
try
{
using (var ms = new MemoryStream(bytes))
using (var ms = _memoryStreamProvider.CreateNew(bytes))
{
var detector = new CharsetDetector();
detector.Feed(ms);

View File

@@ -75,7 +75,8 @@ namespace MediaBrowser.Server.Implementations.Session
await _httpClient.Post(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken
CancellationToken = cancellationToken,
BufferContent = false
}).ConfigureAwait(false);
}

View File

@@ -30,6 +30,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Sync
{
@@ -51,6 +52,7 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly Func<IMediaSourceManager> _mediaSourceManager;
private readonly IJsonSerializer _json;
private readonly ITaskManager _taskManager;
private readonly IMemoryStreamProvider _memoryStreamProvider;
private ISyncProvider[] _providers = { };
@@ -60,7 +62,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemUpdated;
public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemCreated;
public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IServerApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder, IFileSystem fileSystem, Func<ISubtitleEncoder> subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func<IMediaSourceManager> mediaSourceManager, IJsonSerializer json, ITaskManager taskManager)
public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IServerApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder, IFileSystem fileSystem, Func<ISubtitleEncoder> subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func<IMediaSourceManager> mediaSourceManager, IJsonSerializer json, ITaskManager taskManager, IMemoryStreamProvider memoryStreamProvider)
{
_libraryManager = libraryManager;
_repo = repo;
@@ -78,6 +80,7 @@ namespace MediaBrowser.Server.Implementations.Sync
_mediaSourceManager = mediaSourceManager;
_json = json;
_taskManager = taskManager;
_memoryStreamProvider = memoryStreamProvider;
}
public void AddParts(IEnumerable<ISyncProvider> providers)
@@ -95,7 +98,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public ISyncDataProvider GetDataProvider(IServerSyncProvider provider, SyncTarget target)
{
return _dataProviders.GetOrAdd(target.Id, key => new TargetDataProvider(provider, target, _appHost, _logger, _json, _fileSystem, _config.CommonApplicationPaths));
return _dataProviders.GetOrAdd(target.Id, key => new TargetDataProvider(provider, target, _appHost, _logger, _json, _fileSystem, _config.CommonApplicationPaths, _memoryStreamProvider));
}
public async Task<SyncJobCreationResult> CreateJob(SyncJobRequest request)

View File

@@ -12,6 +12,7 @@ using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using Interfaces.IO;
using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Sync
{
@@ -28,8 +29,9 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly IFileSystem _fileSystem;
private readonly IApplicationPaths _appPaths;
private readonly IServerApplicationHost _appHost;
private readonly IMemoryStreamProvider _memoryStreamProvider;
public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, IServerApplicationHost appHost, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths)
public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, IServerApplicationHost appHost, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths, IMemoryStreamProvider memoryStreamProvider)
{
_logger = logger;
_json = json;
@@ -37,6 +39,7 @@ namespace MediaBrowser.Server.Implementations.Sync
_target = target;
_fileSystem = fileSystem;
_appPaths = appPaths;
_memoryStreamProvider = memoryStreamProvider;
_appHost = appHost;
}
@@ -90,7 +93,7 @@ namespace MediaBrowser.Server.Implementations.Sync
private async Task SaveData(List<LocalItem> items, CancellationToken cancellationToken)
{
using (var stream = new MemoryStream())
using (var stream = _memoryStreamProvider.CreateNew())
{
_json.SerializeToStream(items, stream);