Implemented RTSP OPTIONS and RTSP DESCRIBE
This commit is contained in:
parent
05857b9004
commit
2205d50b0a
1
.gitignore
vendored
1
.gitignore
vendored
@ -122,3 +122,4 @@ imgui.ini
|
|||||||
/GUIs/skyscraper8.UI.ImGui.MonoGame/bin/Debug/net8.0
|
/GUIs/skyscraper8.UI.ImGui.MonoGame/bin/Debug/net8.0
|
||||||
/GUIs/skyscraper8.UI.ImGui.MonoGame/obj/Debug/net8.0
|
/GUIs/skyscraper8.UI.ImGui.MonoGame/obj/Debug/net8.0
|
||||||
/GUIs/skyscraper8.UI.ImGui.MonoGame/obj
|
/GUIs/skyscraper8.UI.ImGui.MonoGame/obj
|
||||||
|
/.vs/skyscraper8/CopilotIndices/17.14.995.13737
|
||||||
|
|||||||
@ -26,6 +26,8 @@ using System.Net.NetworkInformation;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
|
using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
|
||||||
|
using skyscraper8.SatIp;
|
||||||
|
using skyscraper8.SatIp.RtspResponses;
|
||||||
|
|
||||||
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]
|
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]
|
||||||
namespace skyscraper5
|
namespace skyscraper5
|
||||||
@ -35,12 +37,11 @@ namespace skyscraper5
|
|||||||
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||||
private static void IntegrationTest()
|
private static void IntegrationTest()
|
||||||
{
|
{
|
||||||
FileStream fileStream = File.OpenRead("C:\\Temp\\ule-iww.ts");
|
RtspClient rtspClient = new RtspClient("172.20.20.121", 554);
|
||||||
TsContext tesContext = new TsContext();
|
RtspOptionsResponse options = rtspClient.GetOptions("/");
|
||||||
SkyscraperContext skyscraperContext = new SkyscraperContext(tesContext, new InMemoryScraperStorage(), new NullObjectStorage());
|
string url = RtspClient.MakeUrl(DiSEqC_Opcode.DISEQC_OPTION_A | DiSEqC_Opcode.DISEQC_POSITION_A | DiSEqC_Opcode.DISEQC_HORIZONTAL, 11954, true, 27500);
|
||||||
skyscraperContext.InitalizeFilterChain();
|
RtspDescribeResponse describe = rtspClient.GetDescribe(url);
|
||||||
tesContext.RegisterPacketProcessor(0x666, new StreamTypeAutodetection(0x666, skyscraperContext));
|
SessionDescriptionProtocol sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol();
|
||||||
skyscraperContext.IngestFromStream(fileStream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
|
|||||||
194
skyscraper8/SatIp/RtspClient.cs
Normal file
194
skyscraper8/SatIp/RtspClient.cs
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using skyscraper5.Skyscraper;
|
||||||
|
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||||
|
using skyscraper8.SatIp.RtspRequests;
|
||||||
|
using skyscraper8.SatIp.RtspResponses;
|
||||||
|
|
||||||
|
namespace skyscraper8.SatIp
|
||||||
|
{
|
||||||
|
internal class RtspClient : Validatable
|
||||||
|
{
|
||||||
|
private uint cseqCounter;
|
||||||
|
private const string USER_AGENT = "sophiaNetRtspClient/1.0";
|
||||||
|
|
||||||
|
public RtspClient(string ip, int port)
|
||||||
|
{
|
||||||
|
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
|
||||||
|
this.TcpClient = new TcpClient();
|
||||||
|
this.TcpClient.Connect(ipEndPoint);
|
||||||
|
this.RootPath = string.Format("rtsp://{0}:{1}", ip, port);
|
||||||
|
this.NetworkStream = TcpClient.GetStream();
|
||||||
|
this.BufferedStream = new BufferedStream(this.NetworkStream);
|
||||||
|
this.StreamReader = new StreamReader(this.BufferedStream);
|
||||||
|
this.StreamWriter = new StreamWriter(this.BufferedStream);
|
||||||
|
this.cseqCounter = 2;
|
||||||
|
this.ListenIp = GetListenIp(this.TcpClient.Client.LocalEndPoint);
|
||||||
|
RtspOptionsResponse rtspOptionsResponse = GetOptions("/");
|
||||||
|
this.Valid = rtspOptionsResponse.Valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPAddress ListenIp { get; set; }
|
||||||
|
|
||||||
|
private IPAddress GetListenIp(EndPoint clientLocalEndPoint)
|
||||||
|
{
|
||||||
|
IPEndPoint ipEndPoint = clientLocalEndPoint as IPEndPoint;
|
||||||
|
if (ipEndPoint == null)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException(clientLocalEndPoint.GetType().Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipEndPoint.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||||
|
{
|
||||||
|
return ipEndPoint.Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipEndPoint.Address.IsIPv4MappedToIPv6)
|
||||||
|
{
|
||||||
|
return ipEndPoint.Address.MapToIPv4();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotImplementedException(String.Format("Don't know whether I can listen on IP {0}", ipEndPoint.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string RootPath { get; set; }
|
||||||
|
|
||||||
|
private TcpClient TcpClient { get; set; }
|
||||||
|
private NetworkStream NetworkStream { get; set; }
|
||||||
|
private BufferedStream BufferedStream { get; set; }
|
||||||
|
private StreamReader StreamReader { get; set; }
|
||||||
|
private StreamWriter StreamWriter { get; set; }
|
||||||
|
|
||||||
|
public RtspOptionsResponse GetOptions(string url)
|
||||||
|
{
|
||||||
|
RtspOptionsRequest request = new RtspOptionsRequest();
|
||||||
|
request.RequestPath = url;
|
||||||
|
request.CSeq = cseqCounter++;
|
||||||
|
request.UserAgent = USER_AGENT;
|
||||||
|
RtspResponseHeader header = GetResponse(request.ListHeaders(RootPath));
|
||||||
|
RtspOptionsResponse result = new RtspOptionsResponse(header);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RtspDescribeResponse GetDescribe(string url)
|
||||||
|
{
|
||||||
|
RtspDescribeRequest request = new RtspDescribeRequest();
|
||||||
|
request.RequestPath = url;
|
||||||
|
request.CSeq = cseqCounter++;
|
||||||
|
request.UserAgent = USER_AGENT;
|
||||||
|
request.Accept = "application/sdp";
|
||||||
|
RtspResponseHeader header = GetResponse(request.ListHeaders(RootPath));
|
||||||
|
RtspDescribeResponse result = new RtspDescribeResponse(header);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RtspResponseHeader GetResponse(string request)
|
||||||
|
{
|
||||||
|
StreamWriter.Write(request);
|
||||||
|
StreamWriter.Flush();
|
||||||
|
|
||||||
|
RtspResponseHeader result = new RtspResponseHeader();
|
||||||
|
|
||||||
|
string response = StreamReader.ReadLine();
|
||||||
|
if (!response.StartsWith("RTSP/"))
|
||||||
|
throw new RtspException("Invalid RTSP response.");
|
||||||
|
|
||||||
|
response = response.Substring(5);
|
||||||
|
|
||||||
|
string versionString = response.Substring(0, 3);
|
||||||
|
result.rtspVersion = Version.Parse(versionString);
|
||||||
|
response = response.Substring(4);
|
||||||
|
|
||||||
|
string statusCodeString = response.Substring(0,3);
|
||||||
|
result.statusCode = ushort.Parse(statusCodeString);
|
||||||
|
|
||||||
|
response = response.Substring(4);
|
||||||
|
result.statusLine = response;
|
||||||
|
|
||||||
|
long contentLength = 0;
|
||||||
|
|
||||||
|
result.kv = new Dictionary<string, string>();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
string lineIn = StreamReader.ReadLine();
|
||||||
|
if (string.IsNullOrEmpty(lineIn))
|
||||||
|
break;
|
||||||
|
|
||||||
|
int indexOf = lineIn.IndexOf(": ");
|
||||||
|
string key = lineIn.Substring(0, indexOf);
|
||||||
|
string value = lineIn.Substring(indexOf + 2);
|
||||||
|
result.kv.Add(key, value);
|
||||||
|
|
||||||
|
if (key.Equals("Content-Length"))
|
||||||
|
{
|
||||||
|
contentLength = long.Parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentLength > 0)
|
||||||
|
{
|
||||||
|
StreamReader.DiscardBufferedData();
|
||||||
|
byte[] buffer = new byte[contentLength];
|
||||||
|
int sucessfullyRead = BufferedStream.Read(buffer, 0, (int)contentLength);
|
||||||
|
if (sucessfullyRead != contentLength)
|
||||||
|
{
|
||||||
|
throw new IOException("incomplete read");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.payload = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string MakeUrl(DiSEqC_Opcode diseqcChannel, int freq, bool isS2, int symbolrate)
|
||||||
|
{
|
||||||
|
byte diseqc;
|
||||||
|
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_A) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_A))
|
||||||
|
{
|
||||||
|
diseqc = 1;
|
||||||
|
}
|
||||||
|
else if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_A) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_B))
|
||||||
|
{
|
||||||
|
diseqc = 2;
|
||||||
|
}
|
||||||
|
else if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_B) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_A))
|
||||||
|
{
|
||||||
|
diseqc = 3;
|
||||||
|
}
|
||||||
|
else if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_B) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_B))
|
||||||
|
{
|
||||||
|
diseqc = 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(diseqcChannel));
|
||||||
|
}
|
||||||
|
|
||||||
|
char pol;
|
||||||
|
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_HORIZONTAL))
|
||||||
|
{
|
||||||
|
pol = 'h';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pol = 'v';
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.AppendFormat("/?src={0}", diseqc);
|
||||||
|
sb.AppendFormat("&freq={0}", freq);
|
||||||
|
sb.AppendFormat("&pol={0}", pol);
|
||||||
|
sb.AppendFormat("&msys={0}", isS2 ? "dvbs2" : "dvbs");
|
||||||
|
sb.AppendFormat("&sr={0}", symbolrate);
|
||||||
|
sb.AppendFormat("&pids=all");
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
skyscraper8/SatIp/RtspException.cs
Normal file
23
skyscraper8/SatIp/RtspException.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace skyscraper8.SatIp
|
||||||
|
{
|
||||||
|
public class RtspException : Exception
|
||||||
|
{
|
||||||
|
public RtspException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public RtspException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public RtspException(string message, Exception inner) : base(message, inner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
skyscraper8/SatIp/RtspRequest.cs
Normal file
34
skyscraper8/SatIp/RtspRequest.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace skyscraper8.SatIp
|
||||||
|
{
|
||||||
|
internal abstract class RtspRequest
|
||||||
|
{
|
||||||
|
protected readonly Dictionary<string, string> args;
|
||||||
|
private string verb;
|
||||||
|
public string RequestPath { get; set; }
|
||||||
|
|
||||||
|
protected RtspRequest(string verb)
|
||||||
|
{
|
||||||
|
this.args = new Dictionary<string, string>();
|
||||||
|
this.verb = verb;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string ListHeaders(string rootpath)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.AppendFormat("{0} {1}{2} RTSP/1.0\r\n", verb, rootpath, RequestPath);
|
||||||
|
foreach (KeyValuePair<string, string> pair in args)
|
||||||
|
{
|
||||||
|
sb.AppendFormat("{0}: {1}\r\n", pair.Key, pair.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendFormat("\r\n");
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
52
skyscraper8/SatIp/RtspRequests/RtspDescribeRequest.cs
Normal file
52
skyscraper8/SatIp/RtspRequests/RtspDescribeRequest.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using skyscraper8.SatIp.RtspResponses;
|
||||||
|
|
||||||
|
namespace skyscraper8.SatIp.RtspRequests
|
||||||
|
{
|
||||||
|
internal class RtspDescribeRequest : RtspRequest
|
||||||
|
{
|
||||||
|
public RtspDescribeRequest() : base("DESCRIBE")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint CSeq
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.args["CSeq"] = Convert.ToString(value);
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return uint.Parse(base.args["CSeq"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string UserAgent
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.args["User-Agent"] = value;
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.args["User-Agent"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Accept
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.args["Accept"] = value;
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.args["Accept"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
skyscraper8/SatIp/RtspRequests/RtspOptionsRequest.cs
Normal file
40
skyscraper8/SatIp/RtspRequests/RtspOptionsRequest.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace skyscraper8.SatIp.RtspRequests
|
||||||
|
{
|
||||||
|
internal class RtspOptionsRequest : RtspRequest
|
||||||
|
{
|
||||||
|
public RtspOptionsRequest()
|
||||||
|
: base("OPTIONS")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint CSeq
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.args["CSeq"] = Convert.ToString(value);
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return uint.Parse(base.args["CSeq"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string UserAgent
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.args["User-Agent"] = value;
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.args["User-Agent"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
skyscraper8/SatIp/RtspResponse.cs
Normal file
31
skyscraper8/SatIp/RtspResponse.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using skyscraper5.Skyscraper;
|
||||||
|
|
||||||
|
namespace skyscraper8.SatIp
|
||||||
|
{
|
||||||
|
internal abstract class RtspResponse : Validatable
|
||||||
|
{
|
||||||
|
private readonly string statusLine;
|
||||||
|
protected readonly Dictionary<string, string> args;
|
||||||
|
protected readonly byte[] payload;
|
||||||
|
|
||||||
|
protected RtspResponse(RtspResponseHeader header)
|
||||||
|
{
|
||||||
|
RtspVersion = header.rtspVersion;
|
||||||
|
RtspStatusCode = header.statusCode;
|
||||||
|
statusLine = header.statusLine;
|
||||||
|
args = header.kv;
|
||||||
|
payload = header.payload;
|
||||||
|
Valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ushort RtspStatusCode { get; private set; }
|
||||||
|
|
||||||
|
public Version RtspVersion { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
17
skyscraper8/SatIp/RtspResponseHeader.cs
Normal file
17
skyscraper8/SatIp/RtspResponseHeader.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace skyscraper8.SatIp
|
||||||
|
{
|
||||||
|
internal struct RtspResponseHeader
|
||||||
|
{
|
||||||
|
public Version rtspVersion;
|
||||||
|
public ushort statusCode;
|
||||||
|
public string statusLine;
|
||||||
|
public Dictionary<string, string> kv;
|
||||||
|
public byte[] payload;
|
||||||
|
}
|
||||||
|
}
|
||||||
54
skyscraper8/SatIp/RtspResponses/RtspDescribeResponse.cs
Normal file
54
skyscraper8/SatIp/RtspResponses/RtspDescribeResponse.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace skyscraper8.SatIp.RtspResponses
|
||||||
|
{
|
||||||
|
internal class RtspDescribeResponse : RtspResponse
|
||||||
|
{
|
||||||
|
public RtspDescribeResponse(RtspResponseHeader header) : base(header)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint CSeq
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return uint.Parse(base.args["CSeq"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ContentType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.args["Content-Type"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long ContentLength
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return long.Parse(base.args["Content-Length"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionDescriptionProtocol GetSessionDescriptionProtocol()
|
||||||
|
{
|
||||||
|
if (!ContentType.Equals("application/sdp"))
|
||||||
|
{
|
||||||
|
throw new RtspException(String.Format("Invalid MIME Type. Expected {0}, got {1}.", "application/sdp", ContentType));
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryStream ms = new MemoryStream(base.payload, false);
|
||||||
|
StreamReader sr = new StreamReader(ms);
|
||||||
|
SessionDescriptionProtocol result = new SessionDescriptionProtocol(sr);
|
||||||
|
ms.Close();
|
||||||
|
sr.Close();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
skyscraper8/SatIp/RtspResponses/RtspOptionsResponse.cs
Normal file
32
skyscraper8/SatIp/RtspResponses/RtspOptionsResponse.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace skyscraper8.SatIp.RtspResponses
|
||||||
|
{
|
||||||
|
internal class RtspOptionsResponse : RtspResponse
|
||||||
|
{
|
||||||
|
public RtspOptionsResponse(RtspResponseHeader header)
|
||||||
|
: base(header)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint CSeq
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return uint.Parse(base.args["CSeq"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Public
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.args["Public"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
149
skyscraper8/SatIp/SessionDescriptionProtocol.cs
Normal file
149
skyscraper8/SatIp/SessionDescriptionProtocol.cs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace skyscraper8.SatIp
|
||||||
|
{
|
||||||
|
internal class SessionDescriptionProtocol
|
||||||
|
{
|
||||||
|
public SessionDescriptionProtocol(StreamReader sr)
|
||||||
|
{
|
||||||
|
while (!sr.EndOfStream)
|
||||||
|
{
|
||||||
|
string line = sr.ReadLine();
|
||||||
|
int indexOf = line.IndexOf('=');
|
||||||
|
string key = line.Substring(0, indexOf);
|
||||||
|
string value = line.Substring(indexOf + 1);
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case "v":
|
||||||
|
SdpVersion = int.Parse(value);
|
||||||
|
break;
|
||||||
|
case "o":
|
||||||
|
string[] oArgs = value.Split(' ');
|
||||||
|
Username = oArgs[0];
|
||||||
|
SessionId = ulong.Parse(oArgs[1]);
|
||||||
|
SessionVersion = uint.Parse(oArgs[2]);
|
||||||
|
OwnerNetworkType = Enum.Parse<OwnerNetworkTypeEnum>(oArgs[3]);
|
||||||
|
OwnerAddressType = Enum.Parse<OwnerAddressTypeEnum>(oArgs[4]);
|
||||||
|
OwnerAddress = IPAddress.Parse(oArgs[5]);
|
||||||
|
break;
|
||||||
|
case "s":
|
||||||
|
SessionName = value;
|
||||||
|
break;
|
||||||
|
case "t":
|
||||||
|
string[] tArgs = value.Split(' ');
|
||||||
|
SessionStartTime = uint.Parse(tArgs[0]);
|
||||||
|
SessionStopType = uint.Parse(tArgs[1]);
|
||||||
|
break;
|
||||||
|
case "m":
|
||||||
|
string[] mArgs = value.Split(' ');
|
||||||
|
MediaType = Enum.Parse<MediaTypeEnum>(mArgs[0], true);
|
||||||
|
MediaPort = uint.Parse(mArgs[1]);
|
||||||
|
MediaProtocol = mArgs[2];
|
||||||
|
MediaFormat = (MediaFormatEnum)int.Parse(mArgs[3]);
|
||||||
|
break;
|
||||||
|
case "c":
|
||||||
|
string[] cArgs = value.Split(' ');
|
||||||
|
ConnectionNetworkType = Enum.Parse<OwnerNetworkTypeEnum>(cArgs[0]);
|
||||||
|
ConnectionAddressType = Enum.Parse<OwnerAddressTypeEnum>(cArgs[1]);
|
||||||
|
ConnectionAddress = IPAddress.Parse(cArgs[2]);
|
||||||
|
break;
|
||||||
|
case "a":
|
||||||
|
int aIndex = value.IndexOf(':');
|
||||||
|
string aKey = value.Substring(0, aIndex);
|
||||||
|
string aValue = value.Substring(aIndex + 1);
|
||||||
|
if (MediaAttribute == null)
|
||||||
|
MediaAttribute = new Dictionary<string, string>();
|
||||||
|
MediaAttribute[aKey] = aValue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, string> MediaAttribute { get; set; }
|
||||||
|
|
||||||
|
public IPAddress ConnectionAddress { get; set; }
|
||||||
|
|
||||||
|
public OwnerAddressTypeEnum ConnectionAddressType { get; set; }
|
||||||
|
|
||||||
|
public OwnerNetworkTypeEnum ConnectionNetworkType { get; set; }
|
||||||
|
|
||||||
|
public MediaFormatEnum MediaFormat { get; set; }
|
||||||
|
|
||||||
|
public string MediaProtocol { get; set; }
|
||||||
|
|
||||||
|
public uint MediaPort { get; set; }
|
||||||
|
|
||||||
|
public MediaTypeEnum MediaType { get; set; }
|
||||||
|
|
||||||
|
public uint SessionStopType { get; set; }
|
||||||
|
|
||||||
|
public uint SessionStartTime { get; set; }
|
||||||
|
|
||||||
|
public string SessionName { get; set; }
|
||||||
|
|
||||||
|
public IPAddress OwnerAddress { get; set; }
|
||||||
|
|
||||||
|
public OwnerAddressTypeEnum OwnerAddressType { get; set; }
|
||||||
|
|
||||||
|
public OwnerNetworkTypeEnum OwnerNetworkType { get; set; }
|
||||||
|
|
||||||
|
public uint SessionVersion { get; set; }
|
||||||
|
|
||||||
|
public ulong SessionId { get; set; }
|
||||||
|
|
||||||
|
public string Username { get; set; }
|
||||||
|
|
||||||
|
public int SdpVersion { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OwnerNetworkTypeEnum
|
||||||
|
{
|
||||||
|
IN
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OwnerAddressTypeEnum
|
||||||
|
{
|
||||||
|
IP4
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MediaTypeEnum
|
||||||
|
{
|
||||||
|
Video,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MediaFormatEnum
|
||||||
|
{
|
||||||
|
PCMU = 0,
|
||||||
|
GSM = 3,
|
||||||
|
G723 = 4,
|
||||||
|
DVI4_32kbit = 5,
|
||||||
|
DVI4_64kbit = 6,
|
||||||
|
LPC = 7,
|
||||||
|
PCMA = 8,
|
||||||
|
G722 = 9,
|
||||||
|
L16Stereo = 10,
|
||||||
|
L16Mono = 11,
|
||||||
|
QCELP = 12,
|
||||||
|
ComfortNoise = 13,
|
||||||
|
MPA = 14,
|
||||||
|
G728 = 15,
|
||||||
|
DVI4_44kbit = 16,
|
||||||
|
DVI4_88kbit = 17,
|
||||||
|
G729 = 18,
|
||||||
|
CellB = 25,
|
||||||
|
Jpeg = 26,
|
||||||
|
NV = 28,
|
||||||
|
H261 = 31,
|
||||||
|
MPV = 32,
|
||||||
|
M2T = 33,
|
||||||
|
H263 = 34
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user