| 
					
				 | 
			
			
				@@ -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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |