Skip to content

Commit

Permalink
Use SharedStream for LiveTV more restrictively (jellyfin#11805)
Browse files Browse the repository at this point in the history
  • Loading branch information
gnattu committed May 25, 2024
1 parent 5e75142 commit ef98589
Showing 1 changed file with 23 additions and 34 deletions.
57 changes: 23 additions & 34 deletions src/Jellyfin.LiveTv/TunerHosts/M3UTunerHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,8 @@ namespace Jellyfin.LiveTv.TunerHosts
{
public class M3UTunerHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost
{
private static readonly string[] _disallowedMimeTypes =
{
"text/plain",
"text/html",
"video/x-matroska",
"video/mp4",
"application/vnd.apple.mpegurl",
"application/mpegurl",
"application/x-mpegurl",
"video/vnd.mpeg.dash.mpd"
};

private static readonly string[] _disallowedSharedStreamExtensions =
{
".mkv",
".mp4",
".m3u8",
".mpd"
};
private static readonly string[] _mimeTypesCanShareHttpStream = ["video/MP2T"];
private static readonly string[] _extensionsCanShareHttpStream = [".ts", ".tsv", ".m2t"];

private readonly IHttpClientFactory _httpClientFactory;
private readonly IServerApplicationHost _appHost;
Expand Down Expand Up @@ -113,28 +96,34 @@ protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo tunerH

if (mediaSource.Protocol == MediaProtocol.Http && !mediaSource.RequiresLooping)
{
using var message = new HttpRequestMessage(HttpMethod.Head, mediaSource.Path);
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
.SendAsync(message, cancellationToken)
.ConfigureAwait(false);
var extension = Path.GetExtension(new UriBuilder(mediaSource.Path).Path);

if (response.IsSuccessStatusCode)
if (string.IsNullOrEmpty(extension))
{
if (!_disallowedMimeTypes.Contains(response.Content.Headers.ContentType?.MediaType, StringComparison.OrdinalIgnoreCase))
try
{
return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper);
using var message = new HttpRequestMessage(HttpMethod.Head, mediaSource.Path);
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
.SendAsync(message, cancellationToken)
.ConfigureAwait(false);

if (response.IsSuccessStatusCode)
{
if (_mimeTypesCanShareHttpStream.Contains(response.Content.Headers.ContentType?.MediaType, StringComparison.OrdinalIgnoreCase))
{
return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper);
}
}
}
}
else
{
// Fallback to check path extension when the server does not support HEAD method
// Use UriBuilder to remove all query string as GetExtension will include them when used directly
var extension = Path.GetExtension(new UriBuilder(mediaSource.Path).Path);
if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
catch (Exception)
{
return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper);
Logger.LogWarning("HEAD request to check MIME type failed, shared stream disabled");
}
}
else if (_extensionsCanShareHttpStream.Contains(extension, StringComparison.OrdinalIgnoreCase))
{
return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper);
}
}

return new LiveStream(mediaSource, tunerHost, FileSystem, Logger, Config, _streamHelper);
Expand Down

0 comments on commit ef98589

Please sign in to comment.