aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs10
-rw-r--r--MediaBrowser.Model/ApiClient/ServerCredentials.cs2
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs27
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs79
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs68
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs59
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs203
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs37
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs68
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs105
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs57
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs65
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs60
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs160
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs116
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs32
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs25
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs90
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj14
-rw-r--r--MediaBrowser.Server.Implementations/Udp/UdpServer.cs26
-rw-r--r--MediaBrowser.ServerApplication/MainStartup.cs8
-rw-r--r--MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj1
-rw-r--r--MediaBrowser.ServerApplication/Native/LoopbackUtil.cs358
-rw-r--r--MediaBrowser.WebDashboard/Api/PackageCreator.cs7
24 files changed, 1624 insertions, 53 deletions
diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
index 6bf414dfa..ce00acb52 100644
--- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
@@ -481,6 +481,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
}
+ if (state.IsVideoRequest)
+ {
+ var encodingOptions = GetEncodingOptions();
+ var videoEncoder = EncodingJobFactory.GetVideoEncoder(MediaEncoder, state, encodingOptions);
+ if (videoEncoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ arg = "-hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device " + encodingOptions.VaapiDevice + " " + arg;
+ }
+ }
+
return arg.Trim();
}
diff --git a/MediaBrowser.Model/ApiClient/ServerCredentials.cs b/MediaBrowser.Model/ApiClient/ServerCredentials.cs
index 19f68445e..ddeb7e546 100644
--- a/MediaBrowser.Model/ApiClient/ServerCredentials.cs
+++ b/MediaBrowser.Model/ApiClient/ServerCredentials.cs
@@ -67,7 +67,7 @@ namespace MediaBrowser.Model.ApiClient
}
if (!string.IsNullOrEmpty(server.ManualAddress))
{
- existing.LocalAddress = server.ManualAddress;
+ existing.ManualAddress = server.ManualAddress;
}
if (!string.IsNullOrEmpty(server.Name))
{
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
index 28b7824c8..8e46f8f03 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -102,14 +102,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer
// new SessionAuthProvider(_containerAdapter.Resolve<ISessionContext>()),
//}));
- PreRequestFilters.Add((httpReq, httpRes) =>
- {
- //Handles Request and closes Responses after emitting global HTTP Headers
- if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase))
- {
- httpRes.EndRequest(); //add a 'using ServiceStack;'
- }
- });
+ //PreRequestFilters.Add((httpReq, httpRes) =>
+ //{
+ // //Handles Request and closes Responses after emitting global HTTP Headers
+ // if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase))
+ // {
+ // httpRes.EndRequest(); //add a 'using ServiceStack;'
+ // }
+ //});
HostContext.GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
}
@@ -403,6 +403,17 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return;
}
+ if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase))
+ {
+ httpRes.StatusCode = 200;
+ httpRes.AddHeader("Access-Control-Allow-Origin", "*");
+ httpRes.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
+ httpRes.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization");
+ httpRes.ContentType = "text/html";
+
+ httpRes.Close();
+ }
+
var operationName = httpReq.OperationName;
var localPath = url.LocalPath;
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs
new file mode 100644
index 000000000..dddd77179
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs
@@ -0,0 +1,79 @@
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
+{
+ public class ReportBlock
+ {
+ /// <summary>
+ /// Get the length of the block.
+ /// </summary>
+ public int BlockLength { get { return (24); } }
+ /// <summary>
+ /// Get the synchronization source.
+ /// </summary>
+ public string SynchronizationSource { get; private set; }
+ /// <summary>
+ /// Get the fraction lost.
+ /// </summary>
+ public int FractionLost { get; private set; }
+ /// <summary>
+ /// Get the cumulative packets lost.
+ /// </summary>
+ public int CumulativePacketsLost { get; private set; }
+ /// <summary>
+ /// Get the highest number received.
+ /// </summary>
+ public int HighestNumberReceived { get; private set; }
+ /// <summary>
+ /// Get the inter arrival jitter.
+ /// </summary>
+ public int InterArrivalJitter { get; private set; }
+ /// <summary>
+ /// Get the timestamp of the last report.
+ /// </summary>
+ public int LastReportTimeStamp { get; private set; }
+ /// <summary>
+ /// Get the delay since the last report.
+ /// </summary>
+ public int DelaySinceLastReport { get; private set; }
+
+ /// <summary>
+ /// Initialize a new instance of the ReportBlock class.
+ /// </summary>
+ public ReportBlock() { }
+
+ /// <summary>
+ /// Unpack the data in a packet.
+ /// </summary>
+ /// <param name="buffer">The buffer containing the packet.</param>
+ /// <param name="offset">The offset to the first byte of the packet within the buffer.</param>
+ /// <returns>An ErrorSpec instance if an error occurs; null otherwise.</returns>
+ public void Process(byte[] buffer, int offset)
+ {
+ SynchronizationSource = Utils.ConvertBytesToString(buffer, offset, 4);
+ FractionLost = buffer[offset + 4];
+ CumulativePacketsLost = Utils.Convert3BytesToInt(buffer, offset + 5);
+ HighestNumberReceived = Utils.Convert4BytesToInt(buffer, offset + 8);
+ InterArrivalJitter = Utils.Convert4BytesToInt(buffer, offset + 12);
+ LastReportTimeStamp = Utils.Convert4BytesToInt(buffer, offset + 16);
+ DelaySinceLastReport = Utils.Convert4BytesToInt(buffer, offset + 20);
+
+
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs
new file mode 100644
index 000000000..990b6dd94
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
+{
+ class RtcpAppPacket : RtcpPacket
+ {
+ /// <summary>
+ /// Get the synchronization source.
+ /// </summary>
+ public int SynchronizationSource { get; private set; }
+ /// <summary>
+ /// Get the name.
+ /// </summary>
+ public string Name { get; private set; }
+ /// <summary>
+ /// Get the identity.
+ /// </summary>
+ public int Identity { get; private set; }
+ /// <summary>
+ /// Get the variable data portion.
+ /// </summary>
+ public string Data { get; private set; }
+
+ public override void Parse(byte[] buffer, int offset)
+ {
+ base.Parse(buffer, offset);
+ SynchronizationSource = Utils.Convert4BytesToInt(buffer, offset + 4);
+ Name = Utils.ConvertBytesToString(buffer, offset + 8, 4);
+ Identity = Utils.Convert2BytesToInt(buffer, offset + 12);
+
+ int dataLength = Utils.Convert2BytesToInt(buffer, offset + 14);
+ if (dataLength != 0)
+ Data = Utils.ConvertBytesToString(buffer, offset + 16, dataLength);
+ }
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("Application Specific.\n");
+ sb.AppendFormat("Version : {0} .\n", Version);
+ sb.AppendFormat("Padding : {0} .\n", Padding);
+ sb.AppendFormat("Report Count : {0} .\n", ReportCount);
+ sb.AppendFormat("PacketType: {0} .\n", Type);
+ sb.AppendFormat("Length : {0} .\n", Length);
+ sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource);
+ sb.AppendFormat("Name : {0} .\n", Name);
+ sb.AppendFormat("Identity : {0} .\n", Identity);
+ sb.AppendFormat("Data : {0} .\n", Data);
+ sb.AppendFormat(".\n");
+ return sb.ToString();
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs
new file mode 100644
index 000000000..c79ea31a8
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs
@@ -0,0 +1,59 @@
+using System.Collections.ObjectModel;
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
+{
+ public class RtcpByePacket :RtcpPacket
+ {
+ public Collection<string> SynchronizationSources { get; private set; }
+ public string ReasonForLeaving { get; private set; }
+ public override void Parse(byte[] buffer, int offset)
+ {
+ base.Parse(buffer, offset);
+ SynchronizationSources = new Collection<string>();
+ int index = 4;
+
+ while (SynchronizationSources.Count < ReportCount)
+ {
+ SynchronizationSources.Add(Utils.ConvertBytesToString(buffer, offset + index, 4));
+ index += 4;
+ }
+
+ if (index < Length)
+ {
+ int reasonLength = buffer[offset + index];
+ ReasonForLeaving = Utils.ConvertBytesToString(buffer, offset + index + 1, reasonLength);
+ }
+ }
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("ByeBye .\n");
+ sb.AppendFormat("Version : {0} .\n", Version);
+ sb.AppendFormat("Padding : {0} .\n", Padding);
+ sb.AppendFormat("Report Count : {0} .\n", ReportCount);
+ sb.AppendFormat("PacketType: {0} .\n", Type);
+ sb.AppendFormat("Length : {0} .\n", Length);
+ sb.AppendFormat("SynchronizationSources : {0} .\n", SynchronizationSources);
+ sb.AppendFormat("ReasonForLeaving : {0} .\n", ReasonForLeaving);
+ sb.AppendFormat(".\n");
+ return sb.ToString();
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs
new file mode 100644
index 000000000..2c54f0665
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs
@@ -0,0 +1,203 @@
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using MediaBrowser.Model.Logging;
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
+{
+ public class RtcpListener
+ {
+ private readonly ILogger _logger;
+ private Thread _rtcpListenerThread;
+ private AutoResetEvent _rtcpListenerThreadStopEvent = null;
+ private UdpClient _udpClient;
+ private IPEndPoint _multicastEndPoint;
+ private IPEndPoint _serverEndPoint;
+ private TransmissionMode _transmissionMode;
+
+ public RtcpListener(String address, int port, TransmissionMode mode,ILogger logger)
+ {
+ _logger = logger;
+ _transmissionMode = mode;
+ switch (mode)
+ {
+ case TransmissionMode.Unicast:
+ _udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(address), port));
+ _serverEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ break;
+ case TransmissionMode.Multicast:
+ _multicastEndPoint = new IPEndPoint(IPAddress.Parse(address), port);
+ _serverEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ _udpClient = new UdpClient();
+ _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
+ _udpClient.ExclusiveAddressUse = false;
+ _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port));
+ _udpClient.JoinMulticastGroup(_multicastEndPoint.Address);
+ break;
+ }
+ //StartRtcpListenerThread();
+ }
+
+ public void StartRtcpListenerThread()
+ {
+ // Kill the existing thread if it is in "zombie" state.
+ if (_rtcpListenerThread != null && !_rtcpListenerThread.IsAlive)
+ {
+ StopRtcpListenerThread();
+ }
+
+ if (_rtcpListenerThread == null)
+ {
+ _logger.Info("SAT>IP : starting new RTCP listener thread");
+ _rtcpListenerThreadStopEvent = new AutoResetEvent(false);
+ _rtcpListenerThread = new Thread(new ThreadStart(RtcpListenerThread));
+ _rtcpListenerThread.Name = string.Format("SAT>IP tuner RTCP listener");
+ _rtcpListenerThread.IsBackground = true;
+ _rtcpListenerThread.Priority = ThreadPriority.Lowest;
+ _rtcpListenerThread.Start();
+ }
+ }
+
+ public void StopRtcpListenerThread()
+ {
+ if (_rtcpListenerThread != null)
+ {
+ if (!_rtcpListenerThread.IsAlive)
+ {
+ _logger.Info("SAT>IP : aborting old RTCP listener thread");
+ _rtcpListenerThread.Abort();
+ }
+ else
+ {
+ _rtcpListenerThreadStopEvent.Set();
+ if (!_rtcpListenerThread.Join(400 * 2))
+ {
+ _logger.Info("SAT>IP : failed to join RTCP listener thread, aborting thread");
+ _rtcpListenerThread.Abort();
+ }
+ }
+ _rtcpListenerThread = null;
+ if (_rtcpListenerThreadStopEvent != null)
+ {
+ _rtcpListenerThreadStopEvent.Close();
+ _rtcpListenerThreadStopEvent = null;
+ }
+ }
+ }
+
+ private void RtcpListenerThread()
+ {
+ try
+ {
+ bool receivedGoodBye = false;
+ try
+ {
+ _udpClient.Client.ReceiveTimeout = 400;
+ IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ while (!receivedGoodBye && !_rtcpListenerThreadStopEvent.WaitOne(1))
+ {
+ byte[] packets = _udpClient.Receive(ref serverEndPoint);
+ if (packets == null)
+ {
+ continue;
+ }
+
+ int offset = 0;
+ while (offset < packets.Length)
+ {
+ switch (packets[offset + 1])
+ {
+ case 200: //sr
+ var sr = new RtcpSenderReportPacket();
+ sr.Parse(packets, offset);
+ offset += sr.Length;
+ break;
+ case 201: //rr
+ var rr = new RtcpReceiverReportPacket();
+ rr.Parse(packets, offset);
+ offset += rr.Length;
+ break;
+ case 202: //sd
+ var sd = new RtcpSourceDescriptionPacket();
+ sd.Parse(packets, offset);
+ offset += sd.Length;
+ break;
+ case 203: // bye
+ var bye = new RtcpByePacket();
+ bye.Parse(packets, offset);
+ receivedGoodBye = true;
+ OnPacketReceived(new RtcpPacketReceivedArgs(bye));
+ offset += bye.Length;
+ break;
+ case 204: // app
+ var app = new RtcpAppPacket();
+ app.Parse(packets, offset);
+ OnPacketReceived(new RtcpPacketReceivedArgs(app));
+ offset += app.Length;
+ break;
+ }
+ }
+
+ }
+ }
+ finally
+ {
+ switch (_transmissionMode)
+ {
+ case TransmissionMode.Multicast:
+ _udpClient.DropMulticastGroup(_multicastEndPoint.Address);
+ _udpClient.Close();
+ break;
+ case TransmissionMode.Unicast:
+ _udpClient.Close();
+ break;
+ }
+ }
+ }
+ catch (ThreadAbortException)
+ {
+ }
+ catch (Exception ex)
+ {
+ _logger.Info(string.Format("SAT>IP : RTCP listener thread exception"), ex);
+ return;
+ }
+ _logger.Info("SAT>IP : RTCP listener thread stopping");
+ }
+ public delegate void PacketReceivedHandler(object sender, RtcpPacketReceivedArgs e);
+ public event PacketReceivedHandler PacketReceived;
+ public class RtcpPacketReceivedArgs : EventArgs
+ {
+ public Object Packet { get; private set; }
+
+ public RtcpPacketReceivedArgs(Object packet)
+ {
+ Packet = packet;
+ }
+ }
+ protected void OnPacketReceived(RtcpPacketReceivedArgs args)
+ {
+ if (PacketReceived != null)
+ {
+ PacketReceived(this, args);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs
new file mode 100644
index 000000000..0a949eb7e
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
+{
+ public abstract class RtcpPacket
+ {
+ public int Version { get; private set; }
+ public bool Padding { get; private set; }
+ public int ReportCount { get; private set; }
+ public int Type { get; private set; }
+ public int Length { get; private set; }
+
+ public virtual void Parse(byte[] buffer, int offset)
+ {
+ Version = buffer[offset] >> 6;
+ Padding = (buffer[offset] & 0x20) != 0;
+ ReportCount = buffer[offset] & 0x1f;
+ Type = buffer[offset + 1];
+ Length = (Utils.Convert2BytesToInt(buffer, offset + 2) * 4) + 4;
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs
new file mode 100644
index 000000000..abb863652
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs
@@ -0,0 +1,68 @@
+using System.Collections.ObjectModel;
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
+{
+ public class RtcpReceiverReportPacket :RtcpPacket
+ {
+ public string SynchronizationSource { get; private set; }
+ public Collection<ReportBlock> ReportBlocks { get; private set; }
+ public byte[] ProfileExtension { get; private set; }
+ public override void Parse(byte[] buffer, int offset)
+ {
+ base.Parse(buffer, offset);
+ SynchronizationSource = Utils.ConvertBytesToString(buffer, offset + 4, 4);
+
+ ReportBlocks = new Collection<ReportBlock>();
+ int index = 8;
+
+ while (ReportBlocks.Count < ReportCount)
+ {
+ ReportBlock reportBlock = new ReportBlock();
+ reportBlock.Process(buffer, offset + index);
+ ReportBlocks.Add(reportBlock);
+ index += reportBlock.BlockLength;
+ }
+
+ if (index < Length)
+ {
+ ProfileExtension = new byte[Length - index];
+
+ for (int extensionIndex = 0; index < Length; index++)
+ {
+ ProfileExtension[extensionIndex] = buffer[offset + index];
+ extensionIndex++;
+ }
+ }
+ }
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("Receiver Report.\n");
+ sb.AppendFormat("Version : {0} .\n", Version);
+ sb.AppendFormat("Padding : {0} .\n", Padding);
+ sb.AppendFormat("Report Count : {0} .\n", ReportCount);
+ sb.AppendFormat("PacketType: {0} .\n", Type);
+ sb.AppendFormat("Length : {0} .\n", Length);
+ sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource);
+ sb.AppendFormat(".\n");
+ return sb.ToString();
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs
new file mode 100644
index 000000000..dda5d6a03
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs
@@ -0,0 +1,105 @@
+using System.Collections.ObjectModel;
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
+{
+ public class RtcpSenderReportPacket : RtcpPacket
+ {
+ #region Properties
+ /// <summary>
+ /// Get the synchronization source.
+ /// </summary>
+ public int SynchronizationSource { get; private set; }
+ /// <summary>
+ /// Get the NPT timestamp.
+ /// </summary>
+ public long NPTTimeStamp { get; private set; }
+ /// <summary>
+ /// Get the RTP timestamp.
+ /// </summary>
+ public int RTPTimeStamp { get; private set; }
+ /// <summary>
+ /// Get the packet count.
+ /// </summary>
+ public int SenderPacketCount { get; private set; }
+ /// <summary>
+ /// Get the octet count.
+ /// </summary>
+ public int SenderOctetCount { get; private set; }
+ /// <summary>
+ /// Get the list of report blocks.
+ /// </summary>
+ public Collection<ReportBlock> ReportBlocks { get; private set; }
+ /// <summary>
+ /// Get the profile extension data.
+ /// </summary>
+ public byte[] ProfileExtension { get; private set; }
+ #endregion
+
+ public override void Parse(byte[] buffer, int offset)
+ {
+ base.Parse(buffer, offset);
+ SynchronizationSource = Utils.Convert4BytesToInt(buffer, offset + 4);
+ NPTTimeStamp = Utils.Convert8BytesToLong(buffer, offset + 8);
+ RTPTimeStamp = Utils.Convert4BytesToInt(buffer, offset + 16);
+ SenderPacketCount = Utils.Convert4BytesToInt(buffer, offset + 20);
+ SenderOctetCount = Utils.Convert4BytesToInt(buffer, offset + 24);
+
+ ReportBlocks = new Collection<ReportBlock>();
+ int index = 28;
+
+ while (ReportBlocks.Count < ReportCount)
+ {
+ ReportBlock reportBlock = new ReportBlock();
+ reportBlock.Process(buffer, offset + index);
+ ReportBlocks.Add(reportBlock);
+ index += reportBlock.BlockLength;
+ }
+
+ if (index < Length)
+ {
+ ProfileExtension = new byte[Length - index];
+
+ for (int extensionIndex = 0; index < Length; index++)
+ {
+ ProfileExtension[extensionIndex] = buffer[offset + index];
+ extensionIndex++;
+ }
+ }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("Sender Report.\n");
+ sb.AppendFormat("Version : {0} .\n", Version);
+ sb.AppendFormat("Padding : {0} .\n", Padding);
+ sb.AppendFormat("Report Count : {0} .\n", ReportCount);
+ sb.AppendFormat("PacketType: {0} .\n", Type);
+ sb.AppendFormat("Length : {0} .\n", Length);
+ sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource);
+ sb.AppendFormat("NTP Timestamp : {0} .\n", Utils.NptTimestampToDateTime(NPTTimeStamp));
+ sb.AppendFormat("RTP Timestamp : {0} .\n", RTPTimeStamp);
+ sb.AppendFormat("Sender PacketCount : {0} .\n", SenderPacketCount);
+ sb.AppendFormat("Sender Octet Count : {0} .\n", SenderOctetCount);
+ sb.AppendFormat(".\n");
+ return sb.ToString();
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs
new file mode 100644
index 000000000..0a95a4413
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs
@@ -0,0 +1,57 @@
+using System.Collections.ObjectModel;
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
+{
+ class RtcpSourceDescriptionPacket :RtcpPacket
+ { /// <summary>
+ /// Get the list of source descriptions.
+ /// </summary>
+ public Collection<SourceDescriptionBlock> Descriptions;
+ public override void Parse(byte[] buffer, int offset)
+ {
+ base.Parse(buffer, offset);
+ Descriptions = new Collection<SourceDescriptionBlock>();
+
+ int index = 4;
+
+ while (Descriptions.Count < ReportCount)
+ {
+ SourceDescriptionBlock descriptionBlock = new SourceDescriptionBlock();
+ descriptionBlock.Process(buffer, offset + index);
+ Descriptions.Add(descriptionBlock);
+ index += descriptionBlock.BlockLength;
+ }
+ }
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("Source Description.\n");
+ sb.AppendFormat("Version : {0} .\n", Version);
+ sb.AppendFormat("Padding : {0} .\n", Padding);
+ sb.AppendFormat("Report Count : {0} .\n", ReportCount);
+ sb.AppendFormat("PacketType: {0} .\n", Type);
+ sb.AppendFormat("Length : {0} .\n", Length);
+ sb.AppendFormat("Descriptions : {0} .\n", Descriptions);
+
+ sb.AppendFormat(".\n");
+ return sb.ToString();
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs
new file mode 100644
index 000000000..bf56087cd
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs
@@ -0,0 +1,65 @@
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+using System.Collections.ObjectModel;
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
+{
+ class SourceDescriptionBlock
+ {
+ /// <summary>
+ /// Get the length of the block.
+ /// </summary>
+ public int BlockLength { get { return (blockLength + (blockLength % 4)); } }
+
+ /// <summary>
+ /// Get the synchronization source.
+ /// </summary>
+ public string SynchronizationSource { get; private set; }
+ /// <summary>
+ /// Get the list of source descriptioni items.
+ /// </summary>
+ public Collection<SourceDescriptionItem> Items;
+
+ private int blockLength;
+
+ public void Process(byte[] buffer, int offset)
+ {
+ SynchronizationSource = Utils.ConvertBytesToString(buffer, offset, 4);
+ Items = new Collection<SourceDescriptionItem>();
+ int index = 4;
+ bool done = false;
+ do
+ {
+ SourceDescriptionItem item = new SourceDescriptionItem();
+ item.Process(buffer, offset + index);
+
+ if (item.Type != 0)
+ {
+ Items.Add(item);
+ index += item.ItemLength;
+ blockLength += item.ItemLength;
+ }
+ else
+ {
+ blockLength++;
+ done = true;
+ }
+ }
+ while (!done);
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs
new file mode 100644
index 000000000..5dd033642
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
+{
+ /// <summary>
+ /// The class that describes a source description item.
+ /// </summary>
+ public class SourceDescriptionItem
+ {
+ /// <summary>
+ /// Get the type.
+ /// </summary>
+ public int Type { get; private set; }
+ /// <summary>
+ /// Get the text.
+ /// </summary>
+ public string Text { get; private set; }
+
+ /// <summary>
+ /// Get the length of the item.
+ /// </summary>
+ public int ItemLength { get { return (Text.Length + 2); } }
+
+ /// <summary>
+ /// Initialize a new instance of the SourceDescriptionItem class.
+ /// </summary>
+ public SourceDescriptionItem() { }
+
+ /// <summary>
+ /// Unpack the data in a packet.
+ /// </summary>
+ /// <param name="buffer">The buffer containing the packet.</param>
+ /// <param name="offset">The offset to the first byte of the packet within the buffer.</param>
+ /// <returns>An ErrorSpec instance if an error occurs; null otherwise.</returns>
+ public void Process(byte[] buffer, int offset)
+ {
+ Type = buffer[offset];
+ if (Type != 0)
+ {
+ int length = buffer[offset + 1];
+ Text = Utils.ConvertBytesToString(buffer, offset + 2, length);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs
new file mode 100644
index 000000000..ea6a9ba6a
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs
@@ -0,0 +1,160 @@
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using MediaBrowser.Model.Logging;
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtp
+{
+ public class RtpListener
+ {
+ private readonly ILogger _logger;
+ private AutoResetEvent _rtpListenerThreadStopEvent;
+ private Thread _rtpListenerThread;
+ private UdpClient _udpClient;
+ private IPEndPoint _multicastEndPoint;
+ private IPEndPoint _serverEndPoint;
+ private TransmissionMode _transmissionMode;
+ public RtpListener(String address, int port,TransmissionMode mode,ILogger logger)
+ {
+ _logger = logger;
+ _transmissionMode = mode;
+ switch (mode)
+ {
+ case TransmissionMode.Unicast:
+ _udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(address), port));
+ _serverEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ break;
+ case TransmissionMode.Multicast:
+ _multicastEndPoint = new IPEndPoint(IPAddress.Parse(address), port);
+ _serverEndPoint = null;
+ _udpClient = new UdpClient();
+ _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
+ _udpClient.ExclusiveAddressUse = false;
+ _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, _multicastEndPoint.Port));
+ _udpClient.JoinMulticastGroup(_multicastEndPoint.Address);
+ break;
+ }
+ //StartRtpListenerThread();
+ }
+ public void StartRtpListenerThread()
+ {
+ // Kill the existing thread if it is in "zombie" state.
+ if (_rtpListenerThread != null && !_rtpListenerThread.IsAlive)
+ {
+ StopRtpListenerThread();
+ }
+
+ if (_rtpListenerThread == null)
+ {
+ _logger.Info("SAT>IP : starting new RTP listener thread");
+ _rtpListenerThreadStopEvent = new AutoResetEvent(false);
+ _rtpListenerThread = new Thread(new ThreadStart(RtpListenerThread));
+ _rtpListenerThread.Name = string.Format("SAT>IP tuner RTP listener");
+ _rtpListenerThread.IsBackground = true;
+ _rtpListenerThread.Priority = ThreadPriority.Lowest;
+ _rtpListenerThread.Start();
+ }
+ }
+
+ public void StopRtpListenerThread()
+ {
+ if (_rtpListenerThread != null)
+ {
+ if (!_rtpListenerThread.IsAlive)
+ {
+ _logger.Info("SAT>IP : aborting old RTP listener thread");
+ _rtpListenerThread.Abort();
+ }
+ else
+ {
+ _rtpListenerThreadStopEvent.Set();
+ if (!_rtpListenerThread.Join(400 * 2))
+ {
+ _logger.Info("SAT>IP : failed to join RTP listener thread, aborting thread");
+ _rtpListenerThread.Abort();
+ }
+ }
+ _rtpListenerThread = null;
+ if (_rtpListenerThreadStopEvent != null)
+ {
+ _rtpListenerThreadStopEvent.Close();
+ _rtpListenerThreadStopEvent = null;
+ }
+ }
+ }
+
+ private void RtpListenerThread()
+ {
+ try
+ {
+ try
+ {
+
+ while (!_rtpListenerThreadStopEvent.WaitOne(1))
+ {
+ byte[] receivedbytes = _udpClient.Receive(ref _serverEndPoint);
+ RtpPacket packet = RtpPacket.Decode(receivedbytes);
+ OnPacketReceived(new RtpPacketReceivedArgs(packet));
+ }
+ }
+ finally
+ {
+ switch (_transmissionMode)
+ {
+ case TransmissionMode.Multicast:
+ _udpClient.DropMulticastGroup(_multicastEndPoint.Address);
+ _udpClient.Close();
+ break;
+ case TransmissionMode.Unicast:
+ _udpClient.Close();
+ break;
+ }
+ }
+ }
+ catch (ThreadAbortException)
+ {
+ }
+ catch (Exception ex)
+ {
+ _logger.Info(string.Format("SAT>IP : RTP listener thread exception"), ex);
+ return;
+ }
+ _logger.Info("SAT>IP : RTP listener thread stopping");
+ }
+ public delegate void PacketReceivedHandler(object sender, RtpPacketReceivedArgs e);
+ public event PacketReceivedHandler PacketReceived;
+ public class RtpPacketReceivedArgs : EventArgs
+ {
+ public RtpPacket Packet { get; private set; }
+
+ public RtpPacketReceivedArgs(RtpPacket packet)
+ {
+ Packet = packet;
+ }
+ }
+ protected void OnPacketReceived(RtpPacketReceivedArgs args)
+ {
+ if (PacketReceived != null)
+ {
+ PacketReceived(this, args);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs
new file mode 100644
index 000000000..489d7f087
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs
@@ -0,0 +1,116 @@
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using System;
+using System.Collections.ObjectModel;
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtp
+{
+ public class RtpPacket
+ {
+ private static int MinHeaderLength = 12;
+ public int HeaderSize = MinHeaderLength;
+ public int Version { get; set; }
+ public Boolean Padding { get; set; }
+ public Boolean Extension { get; set; }
+ public int ContributingSourceCount { get; set; }
+ public Boolean Marker { get; set; }
+ public int PayloadType { get; set; }
+ public int SequenceNumber { get; set; }
+ public long TimeStamp { get; set; }
+ public long SynchronizationSource { get; set; }
+ public Collection<string> ContributingSources { get; private set; }
+ public int ExtensionHeaderId = 0;
+ public int ExtensionHeaderLength = 0;
+ public bool HasPayload { get; set; }
+ public byte[] Payload { get; set; }
+ public RtpPacket()
+ {
+
+ }
+ public static RtpPacket Decode(byte[] buffer)
+ {
+ var packet = new RtpPacket();
+ packet.Version = buffer[0] >> 6;
+ packet.Padding = (buffer[0] & 0x20) != 0;
+ packet.Extension = (buffer[0] & 0x10) != 0;
+ packet.ContributingSourceCount = buffer[0] & 0x0f;
+
+ packet.Marker = (buffer[1] & 0x80) != 0;
+ packet.PayloadType = buffer[1] & 0x7f;
+
+ packet.SequenceNumber = Utils.Convert2BytesToInt(buffer, 2);
+ packet.TimeStamp = Utils.Convert4BytesToLong(buffer, 4);
+ packet.SynchronizationSource = Utils.Convert4BytesToLong(buffer, 8);
+
+ int index = 12;
+
+ if (packet.ContributingSourceCount != 0)
+ {
+ packet.ContributingSources = new Collection<string>();
+
+ while (packet.ContributingSources.Count < packet.ContributingSourceCount)
+ {
+ packet.ContributingSources.Add(Utils.ConvertBytesToString(buffer, index, 4));
+ index += 4;
+ }
+ }
+ var dataoffset = 0;
+ if (!packet.Extension)
+ dataoffset = index;
+ else
+ {
+ packet.ExtensionHeaderId = Utils.Convert2BytesToInt(buffer, index);
+ packet.ExtensionHeaderLength = Utils.Convert2BytesToInt(buffer, index + 2);
+ dataoffset = index + packet.ExtensionHeaderLength + 4;
+ }
+
+ var dataLength = buffer.Length - dataoffset;
+ if (dataLength > dataoffset)
+ {
+ packet.HasPayload = true;
+ packet.Payload = new byte[dataLength];
+ Array.Copy(buffer, dataoffset, packet.Payload, 0, dataLength);
+ }
+ else
+ {
+ packet.HasPayload = false;
+ }
+ return packet;
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("RTP Packet");
+ sb.AppendFormat("Version: {0} \n", Version);
+ sb.AppendFormat("Padding: {0} \n", Padding);
+ sb.AppendFormat("Extension: {0} \n", Extension);
+ sb.AppendFormat("Contributing Source Identifiers Count: {0} \n", ContributingSourceCount);
+ sb.AppendFormat("Marker: {0} \n", Marker);
+ sb.AppendFormat("Payload Type: {0} \n", PayloadType);
+ sb.AppendFormat("Sequence Number: {0} \n", SequenceNumber);
+ sb.AppendFormat("Timestamp: {0} .\n", TimeStamp);
+ sb.AppendFormat("Synchronization Source Identifier: {0} \n", SynchronizationSource);
+ sb.AppendFormat("\n");
+ return sb.ToString();
+ }
+
+ }
+
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs
index ba5c604ed..cb0e573da 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs
@@ -237,7 +237,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
string modelurl = "";
string serialnumber = "";
string presentationurl = "";
- string capabilities = "";
+ //string capabilities = "";
string m3u = "";
var document = XDocument.Load(locationUri.AbsoluteUri);
var xnm = new XmlNamespaceManager(new NameTable());
@@ -284,22 +284,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
var capabilitiesElement = deviceElement.Element(n1 + "X_SATIPCAP");
if (capabilitiesElement != null)
{
- //_capabilities = capabilitiesElement.Value;
- //if (capabilitiesElement.Value.Contains(','))
- //{
- // string[] capabilities = capabilitiesElement.Value.Split(',');
- // foreach (var capability in capabilities)
- // {
- // ReadCapability(capability);
- // }
- //}
- //else
- //{
- // ReadCapability(capabilitiesElement.Value);
- //}
+ //_capabilities = capabilitiesElement.Value;
+ if (capabilitiesElement.Value.Contains(','))
+ {
+ string[] capabilities = capabilitiesElement.Value.Split(',');
+ foreach (var capability in capabilities)
+ {
+ ReadCapability(capability);
+ }
}
else
{
+ ReadCapability(capabilitiesElement.Value);
+ }
+ }
+ else
+ {
_supportsDVBS = true;
_tunerCountDVBS =1;
}
@@ -314,8 +314,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
Id = uniquedevicename,
IsEnabled = true,
Type = SatIpHost.DeviceType,
- Tuners = 1,
- TunersAvailable = 1,
+ Tuners = _tunerCountDVBS,
+ TunersAvailable = _tunerCountDVBS,
M3UUrl = m3u
};
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs
new file mode 100644
index 000000000..71d7656d9
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs
@@ -0,0 +1,25 @@
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
+{
+ public enum TransmissionMode
+ {
+ Unicast,
+ Multicast
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs
new file mode 100644
index 000000000..3595e4b0a
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) <2007-2016> <Kay Diefenthal>
+
+ SatIp.RtspSample is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SatIp.RtspSample is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
+*/
+using System;
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
+{
+ public class Utils
+ {
+ public static int Convert2BytesToInt(byte[] buffer, int offset)
+ {
+ int temp = (int)buffer[offset];
+ temp = (temp * 256) + buffer[offset + 1];
+
+ return (temp);
+ }
+ public static int Convert3BytesToInt(byte[] buffer, int offset)
+ {
+ int temp = (int)buffer[offset];
+ temp = (temp * 256) + buffer[offset + 1];
+ temp = (temp * 256) + buffer[offset + 2];
+
+ return (temp);
+ }
+ public static int Convert4BytesToInt(byte[] buffer, int offset)
+ {
+ int temp =(int)buffer[offset];
+ temp = (temp * 256) + buffer[offset + 1];
+ temp = (temp * 256) + buffer[offset + 2];
+ temp = (temp * 256) + buffer[offset + 3];
+
+ return (temp);
+ }
+ public static long Convert4BytesToLong(byte[] buffer, int offset)
+ {
+ long temp = 0;
+
+ for (int index = 0; index < 4; index++)
+ temp = (temp * 256) + buffer[offset + index];
+
+ return (temp);
+ }
+ public static long Convert8BytesToLong(byte[] buffer, int offset)
+ {
+ long temp = 0;
+
+ for (int index = 0; index < 8; index++)
+ temp = (temp * 256) + buffer[offset + index];
+
+ return (temp);
+ }
+ public static string ConvertBytesToString(byte[] buffer, int offset, int length)
+ {
+ StringBuilder reply = new StringBuilder(4);
+ for (int index = 0; index < length; index++)
+ reply.Append((char)buffer[offset + index]);
+ return (reply.ToString());
+ }
+ public static DateTime NptTimestampToDateTime(long nptTimestamp) { return NptTimestampToDateTime((uint)((nptTimestamp >> 32) & 0xFFFFFFFF), (uint)(nptTimestamp & 0xFFFFFFFF),null); }
+
+ public static DateTime NptTimestampToDateTime(uint seconds, uint fractions, DateTime? epoch )
+ {
+ ulong ticks =(ulong)((seconds * TimeSpan.TicksPerSecond) + ((fractions * TimeSpan.TicksPerSecond) / 0x100000000L));
+ if (epoch.HasValue) return epoch.Value + TimeSpan.FromTicks((Int64)ticks);
+ return (seconds & 0x80000000L) == 0 ? UtcEpoch2036 + TimeSpan.FromTicks((Int64)ticks) : UtcEpoch1900 + TimeSpan.FromTicks((Int64)ticks);
+ }
+
+ //When the First Epoch will wrap (The real Y2k)
+ public static DateTime UtcEpoch2036 = new DateTime(2036, 2, 7, 6, 28, 16, DateTimeKind.Utc);
+
+ public static DateTime UtcEpoch1900 = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
+ public static DateTime UtcEpoch1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 6879c3f40..9a92cf896 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -251,6 +251,18 @@
<Compile Include="LiveTv\RecordingImageProvider.cs" />
<Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\ChannelScan.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\ReportBlock.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpAppPacket.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpByePacket.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpListener.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpPacket.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpReceiverReportPacket.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpSenderReportPacket.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpSourceDescriptionPacket.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\SourceDescriptionBlock.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\SourceDescriptionItem.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtp\RtpListener.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Rtp\RtpPacket.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspMethod.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspRequest.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspResponse.cs" />
@@ -258,6 +270,8 @@
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspStatusCode.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\SatIpHost.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\SatIpDiscovery.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\TransmissionMode.cs" />
+ <Compile Include="LiveTv\TunerHosts\SatIp\Utils.cs" />
<Compile Include="Localization\LocalizationManager.cs" />
<Compile Include="Logging\PatternsLogger.cs" />
<Compile Include="MediaEncoder\EncodingManager.cs" />
diff --git a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs
index 32992b9b2..9d60dcd40 100644
--- a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs
+++ b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs
@@ -51,7 +51,6 @@ namespace MediaBrowser.Server.Implementations.Udp
AddMessageResponder("who is EmbyServer?", RespondToV2Message);
AddMessageResponder("who is MediaBrowserServer_v2?", RespondToV2Message);
- AddMessageResponder("who is MediaBrowserServer?", RespondToV1Message);
}
private void AddMessageResponder(string message, Action<string, Encoding> responder)
@@ -94,31 +93,6 @@ namespace MediaBrowser.Server.Implementations.Udp
}
}
- private async void RespondToV1Message(string endpoint, Encoding encoding)
- {
- var localUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false);
-
- if (!string.IsNullOrEmpty(localUrl))
- {
- // This is how we did the old v1 search, so need to strip off the protocol
- var index = localUrl.IndexOf("://", StringComparison.OrdinalIgnoreCase);
-
- if (index != -1)
- {
- localUrl = localUrl.Substring(index + 3);
- }
-
- // Send a response back with our ip address and port
- var response = String.Format("MediaBrowserServer|{0}", localUrl);
-
- await SendAsync(Encoding.UTF8.GetBytes(response), endpoint);
- }
- else
- {
- _logger.Warn("Unable to respond to udp request because the local ip address could not be determined.");
- }
- }
-
private async void RespondToV2Message(string endpoint, Encoding encoding)
{
var localUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false);
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index 8f153f33f..67b2a3b47 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -292,6 +292,14 @@ namespace MediaBrowser.ServerApplication
ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX);
}
+ try
+ {
+ LoopUtil.Run();
+ }
+ catch (Exception ex)
+ {
+ logManager.GetLogger("LoopUtil").ErrorException("Error in LoopUtil", ex);
+ }
var task = _appHost.Init(initProgress);
Task.WaitAll(task);
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index 9c5470358..a32312493 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -119,6 +119,7 @@
<Compile Include="MainStartup.cs" />
<Compile Include="Native\LnkShortcutHandler.cs" />
<Compile Include="Native\DbConnector.cs" />
+ <Compile Include="Native\LoopbackUtil.cs" />
<Compile Include="Native\Standby.cs" />
<Compile Include="Native\ServerAuthorization.cs" />
<Compile Include="Native\WindowsApp.cs" />
diff --git a/MediaBrowser.ServerApplication/Native/LoopbackUtil.cs b/MediaBrowser.ServerApplication/Native/LoopbackUtil.cs
new file mode 100644
index 000000000..dea77d375
--- /dev/null
+++ b/MediaBrowser.ServerApplication/Native/LoopbackUtil.cs
@@ -0,0 +1,358 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.ServerApplication.Native
+{
+ /// <summary>
+ /// http://blogs.msdn.com/b/fiddler/archive/2011/12/10/fiddler-windows-8-apps-enable-LoopUtil-network-isolation-exemption.aspx
+ /// </summary>
+ public class LoopUtil
+ {
+ //http://msdn.microsoft.com/en-us/library/windows/desktop/aa379595(v=vs.85).aspx
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SID_AND_ATTRIBUTES
+ {
+ public IntPtr Sid;
+ public uint Attributes;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct INET_FIREWALL_AC_CAPABILITIES
+ {
+ public uint count;
+ public IntPtr capabilities; //SID_AND_ATTRIBUTES
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct INET_FIREWALL_AC_BINARIES
+ {
+ public uint count;
+ public IntPtr binaries;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct INET_FIREWALL_APP_CONTAINER
+ {
+ internal IntPtr appContainerSid;
+ internal IntPtr userSid;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string appContainerName;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string displayName;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string description;
+ internal INET_FIREWALL_AC_CAPABILITIES capabilities;
+ internal INET_FIREWALL_AC_BINARIES binaries;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string workingDirectory;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string packageFullName;
+ }
+
+
+ // Call this API to free the memory returned by the Enumeration API
+ [DllImport("FirewallAPI.dll")]
+ internal static extern void NetworkIsolationFreeAppContainers(IntPtr pACs);
+
+ // Call this API to load the current list of LoopUtil-enabled AppContainers
+ [DllImport("FirewallAPI.dll")]
+ internal static extern uint NetworkIsolationGetAppContainerConfig(out uint pdwCntACs, out IntPtr appContainerSids);
+
+ // Call this API to set the LoopUtil-exemption list
+ [DllImport("FirewallAPI.dll")]
+ private static extern uint NetworkIsolationSetAppContainerConfig(uint pdwCntACs, SID_AND_ATTRIBUTES[] appContainerSids);
+
+
+ // Use this API to convert a string SID into an actual SID
+ [DllImport("advapi32.dll", SetLastError = true)]
+ internal static extern bool ConvertStringSidToSid(string strSid, out IntPtr pSid);
+
+ [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
+ static extern bool ConvertSidToStringSid(
+ [MarshalAs(UnmanagedType.LPArray)] byte[] pSID,
+ out IntPtr ptrSid);
+
+ [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
+ static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid);
+
+ // Use this API to convert a string reference (e.g. "@{blah.pri?ms-resource://whatever}") into a plain string
+ [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
+ internal static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf);
+
+ // Call this API to enumerate all of the AppContainers on the system
+ [DllImport("FirewallAPI.dll")]
+ internal static extern uint NetworkIsolationEnumAppContainers(uint Flags, out uint pdwCntPublicACs, out IntPtr ppACs);
+ // DWORD NetworkIsolationEnumAppContainers(
+ // _In_ DWORD Flags,
+ // _Out_ DWORD *pdwNumPublicAppCs,
+ // _Out_ PINET_FIREWALL_APP_CONTAINER *ppPublicAppCs
+ //);
+
+ //http://msdn.microsoft.com/en-gb/library/windows/desktop/hh968116.aspx
+ enum NETISO_FLAG
+ {
+ NETISO_FLAG_FORCE_COMPUTE_BINARIES = 0x1,
+ NETISO_FLAG_MAX = 0x2
+ }
+
+
+ public class AppContainer
+ {
+ public String appContainerName { get; set; }
+ public String displayName { get; set; }
+ public String workingDirectory { get; set; }
+ public String StringSid { get; set; }
+ public List<uint> capabilities { get; set; }
+ public bool LoopUtil { get; set; }
+
+ public AppContainer(String _appContainerName, String _displayName, String _workingDirectory, IntPtr _sid)
+ {
+ this.appContainerName = _appContainerName;
+ this.displayName = _displayName;
+ this.workingDirectory = _workingDirectory;
+ String tempSid;
+ ConvertSidToStringSid(_sid, out tempSid);
+ this.StringSid = tempSid;
+ }
+ }
+
+ internal List<LoopUtil.INET_FIREWALL_APP_CONTAINER> _AppList;
+ internal List<LoopUtil.SID_AND_ATTRIBUTES> _AppListConfig;
+ public List<AppContainer> Apps = new List<AppContainer>();
+ internal IntPtr _pACs;
+
+ public LoopUtil()
+ {
+ LoadApps();
+ }
+
+ public void LoadApps()
+ {
+ Apps.Clear();
+ _pACs = IntPtr.Zero;
+ //Full List of Apps
+ _AppList = PI_NetworkIsolationEnumAppContainers();
+ //List of Apps that have LoopUtil enabled.
+ _AppListConfig = PI_NetworkIsolationGetAppContainerConfig();
+ foreach (var PI_app in _AppList)
+ {
+ AppContainer app = new AppContainer(PI_app.appContainerName, PI_app.displayName, PI_app.workingDirectory, PI_app.appContainerSid);
+
+ var app_capabilities = LoopUtil.getCapabilites(PI_app.capabilities);
+ if (app_capabilities.Count > 0)
+ {
+ //var sid = new SecurityIdentifier(app_capabilities[0], 0);
+
+ IntPtr arrayValue = IntPtr.Zero;
+ //var b = LoopUtil.ConvertStringSidToSid(app_capabilities[0].Sid, out arrayValue);
+ //string mysid;
+ //var b = LoopUtil.ConvertSidToStringSid(app_capabilities[0].Sid, out mysid);
+ }
+ app.LoopUtil = CheckLoopback(PI_app.appContainerSid);
+ Apps.Add(app);
+ }
+ }
+ private bool CheckLoopback(IntPtr intPtr)
+ {
+ foreach (SID_AND_ATTRIBUTES item in _AppListConfig)
+ {
+ string left, right;
+ ConvertSidToStringSid(item.Sid, out left);
+ ConvertSidToStringSid(intPtr, out right);
+
+ if (left == right)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool CreateExcemptions(string appName)
+ {
+ var hasChanges = false;
+
+ foreach (var app in Apps)
+ {
+ if ((app.appContainerName ?? string.Empty).IndexOf(appName, StringComparison.OrdinalIgnoreCase) != -1 ||
+ (app.displayName ?? string.Empty).IndexOf(appName, StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ if (!app.LoopUtil)
+ {
+ app.LoopUtil = true;
+ hasChanges = true;
+ }
+ }
+ }
+
+ return hasChanges;
+ }
+
+ public static void Run()
+ {
+ var util = new LoopUtil();
+ util.LoadApps();
+
+ var hasChanges = util.CreateExcemptions("Emby");
+
+ if (hasChanges)
+ {
+ util.SaveLoopbackState();
+ }
+ util.SaveLoopbackState();
+ }
+
+ private static List<SID_AND_ATTRIBUTES> getCapabilites(INET_FIREWALL_AC_CAPABILITIES cap)
+ {
+ List<SID_AND_ATTRIBUTES> mycap = new List<SID_AND_ATTRIBUTES>();
+
+ IntPtr arrayValue = cap.capabilities;
+
+ var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
+ for (var i = 0; i < cap.count; i++)
+ {
+ var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES));
+ mycap.Add(cur);
+ arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize));
+ }
+
+ return mycap;
+
+ }
+
+ private static List<SID_AND_ATTRIBUTES> getContainerSID(INET_FIREWALL_AC_CAPABILITIES cap)
+ {
+ List<SID_AND_ATTRIBUTES> mycap = new List<SID_AND_ATTRIBUTES>();
+
+ IntPtr arrayValue = cap.capabilities;
+
+ var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
+ for (var i = 0; i < cap.count; i++)
+ {
+ var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES));
+ mycap.Add(cur);
+ arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize));
+ }
+
+ return mycap;
+
+ }
+
+ private static List<SID_AND_ATTRIBUTES> PI_NetworkIsolationGetAppContainerConfig()
+ {
+
+ IntPtr arrayValue = IntPtr.Zero;
+ uint size = 0;
+ var list = new List<SID_AND_ATTRIBUTES>();
+
+ // Pin down variables
+ GCHandle handle_pdwCntPublicACs = GCHandle.Alloc(size, GCHandleType.Pinned);
+ GCHandle handle_ppACs = GCHandle.Alloc(arrayValue, GCHandleType.Pinned);
+
+ uint retval = NetworkIsolationGetAppContainerConfig(out size, out arrayValue);
+
+ var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
+ for (var i = 0; i < size; i++)
+ {
+ var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES));
+ list.Add(cur);
+ arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize));
+ }
+
+ //release pinned variables.
+ handle_pdwCntPublicACs.Free();
+ handle_ppACs.Free();
+
+ return list;
+
+
+ }
+
+ private List<INET_FIREWALL_APP_CONTAINER> PI_NetworkIsolationEnumAppContainers()
+ {
+
+ IntPtr arrayValue = IntPtr.Zero;
+ uint size = 0;
+ var list = new List<INET_FIREWALL_APP_CONTAINER>();
+
+ // Pin down variables
+ GCHandle handle_pdwCntPublicACs = GCHandle.Alloc(size, GCHandleType.Pinned);
+ GCHandle handle_ppACs = GCHandle.Alloc(arrayValue, GCHandleType.Pinned);
+
+ //uint retval2 = NetworkIsolationGetAppContainerConfig( out size, out arrayValue);
+
+ uint retval = NetworkIsolationEnumAppContainers((Int32)NETISO_FLAG.NETISO_FLAG_MAX, out size, out arrayValue);
+ _pACs = arrayValue; //store the pointer so it can be freed when we close the form
+
+ var structSize = Marshal.SizeOf(typeof(INET_FIREWALL_APP_CONTAINER));
+ for (var i = 0; i < size; i++)
+ {
+ var cur = (INET_FIREWALL_APP_CONTAINER)Marshal.PtrToStructure(arrayValue, typeof(INET_FIREWALL_APP_CONTAINER));
+ list.Add(cur);
+ arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize));
+ }
+
+ //release pinned variables.
+ handle_pdwCntPublicACs.Free();
+ handle_ppACs.Free();
+
+ return list;
+
+
+ }
+
+ public bool SaveLoopbackState()
+ {
+ var countEnabled = CountEnabledLoopUtil();
+ SID_AND_ATTRIBUTES[] arr = new SID_AND_ATTRIBUTES[countEnabled];
+ int count = 0;
+
+ for (int i = 0; i < Apps.Count; i++)
+ {
+ if (Apps[i].LoopUtil)
+ {
+ arr[count].Attributes = 0;
+ //TO DO:
+ IntPtr ptr;
+ ConvertStringSidToSid(Apps[i].StringSid, out ptr);
+ arr[count].Sid = ptr;
+ count++;
+ }
+
+ }
+
+
+ if (NetworkIsolationSetAppContainerConfig((uint)countEnabled, arr) == 0)
+ {
+ return true;
+ }
+ else
+ { return false; }
+
+ }
+
+ private int CountEnabledLoopUtil()
+ {
+ var count = 0;
+ for (int i = 0; i < Apps.Count; i++)
+ {
+ if (Apps[i].LoopUtil)
+ {
+ count++;
+ }
+
+ }
+ return count;
+ }
+
+ public void FreeResources()
+ {
+ NetworkIsolationFreeAppContainers(_pACs);
+ }
+
+ }
+}
diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
index 65e7fa5d3..e7247a11f 100644
--- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs
+++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
@@ -346,11 +346,14 @@ namespace MediaBrowser.WebDashboard.Api
if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
{
- sb.Append("<meta http-equiv=\"Content-Security-Policy\" content=\"default-src * 'unsafe-inline' 'unsafe-eval' data: filesystem:;\">");
+ sb.Append("<meta http-equiv=\"Content-Security-Policy\" content=\"default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap: file: filesystem:; connect-src ws: *\">");
+ }
+ else
+ {
+ sb.Append("<meta http-equiv=\"X-UA-Compatibility\" content=\"IE=Edge\">");
}
sb.Append("<link rel=\"manifest\" href=\"manifest.json\">");
- sb.Append("<meta http-equiv=\"X-UA-Compatibility\" content=\"IE=Edge\">");
sb.Append("<meta name=\"format-detection\" content=\"telephone=no\">");
sb.Append("<meta name=\"msapplication-tap-highlight\" content=\"no\">");
sb.Append("<meta name=\"viewport\" content=\"user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width\">");