hawkeye camera support(not tested)
This commit is contained in:
103
framework/Inspectron.HawkEye/RTSP/Messages/PortCouple.cs
Normal file
103
framework/Inspectron.HawkEye/RTSP/Messages/PortCouple.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Describe a couple of port used to transfer video and command.
|
||||
/// </summary>
|
||||
public class PortCouple
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the first port number.
|
||||
/// </summary>
|
||||
/// <value>The first port.</value>
|
||||
public int First { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the second port number.
|
||||
/// </summary>
|
||||
/// <remarks>If not present the value is 0</remarks>
|
||||
/// <value>The second port.</value>
|
||||
public int Second { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PortCouple"/> class.
|
||||
/// </summary>
|
||||
public PortCouple()
|
||||
{ }
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PortCouple"/> class.
|
||||
/// </summary>
|
||||
/// <param name="first">The first port.</param>
|
||||
public PortCouple(int first)
|
||||
{
|
||||
First = first;
|
||||
Second = 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PortCouple"/> class.
|
||||
/// </summary>
|
||||
/// <param name="first">The first port.</param>
|
||||
/// <param name="second">The second port.</param>
|
||||
public PortCouple(int first, int second)
|
||||
{
|
||||
First = first;
|
||||
Second = second;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance has second port.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance has second port; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsSecondPortPresent
|
||||
{
|
||||
get { return Second != 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the int values of port.
|
||||
/// </summary>
|
||||
/// <param name="stringValue">A string value.</param>
|
||||
/// <returns>The port couple</returns>
|
||||
public static PortCouple Parse(string stringValue)
|
||||
{
|
||||
if (stringValue == null)
|
||||
throw new ArgumentNullException("stringValue");
|
||||
Contract.Requires(!string.IsNullOrEmpty(stringValue));
|
||||
|
||||
string[] values = stringValue.Split('-');
|
||||
|
||||
int tempValue;
|
||||
|
||||
int.TryParse(values[0], out tempValue);
|
||||
PortCouple result = new PortCouple(tempValue);
|
||||
|
||||
tempValue = 0;
|
||||
if (values.Length > 1)
|
||||
int.TryParse(values[1], out tempValue);
|
||||
|
||||
result.Second = tempValue;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String"/> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (IsSecondPortPresent)
|
||||
return First.ToString(CultureInfo.InvariantCulture) + "-" + Second.ToString(CultureInfo.InvariantCulture);
|
||||
else
|
||||
return First.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
49
framework/Inspectron.HawkEye/RTSP/Messages/RTSPChunk.cs
Normal file
49
framework/Inspectron.HawkEye/RTSP/Messages/RTSPChunk.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Class wich represent each message echanged on Rtsp socket.
|
||||
/// </summary>
|
||||
public abstract class RtspChunk : ICloneable
|
||||
{
|
||||
/// <summary>
|
||||
/// Logs the message to debug.
|
||||
/// </summary>
|
||||
public void LogMessage()
|
||||
{
|
||||
LogMessage(NLog.LogLevel.Debug);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs the message.
|
||||
/// </summary>
|
||||
/// <param name="alevel">The log level.</param>
|
||||
public abstract void LogMessage(NLog.LogLevel aLevel);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data associate with the message.
|
||||
/// </summary>
|
||||
/// <value>Array of byte transmit with the message.</value>
|
||||
public byte[] Data
|
||||
{ get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source port wich receive the message.
|
||||
/// </summary>
|
||||
/// <value>The source port.</value>
|
||||
public RtspListener SourcePort { get; set; }
|
||||
|
||||
#region ICloneable Membres
|
||||
|
||||
/// <summary>
|
||||
/// Crée un nouvel objet qui est une copie de l'instance en cours.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Nouvel objet qui est une copie de cette instance.
|
||||
/// </returns>
|
||||
public abstract object Clone();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
45
framework/Inspectron.HawkEye/RTSP/Messages/RTSPData.cs
Normal file
45
framework/Inspectron.HawkEye/RTSP/Messages/RTSPData.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Message wich represent data. ($ limited message)
|
||||
/// </summary>
|
||||
public class RtspData : RtspChunk
|
||||
{
|
||||
private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
/// <summary>
|
||||
/// Logs the message to debug.
|
||||
/// </summary>
|
||||
public override void LogMessage(NLog.LogLevel aLevel)
|
||||
{
|
||||
// Default value to debug
|
||||
if (aLevel == null)
|
||||
aLevel = NLog.LogLevel.Debug;
|
||||
// if the level is not logged directly return
|
||||
if (!_logger.IsEnabled(aLevel))
|
||||
return;
|
||||
_logger.Log(aLevel, "Data message");
|
||||
if (Data == null)
|
||||
_logger.Log(aLevel, "Data : null");
|
||||
else
|
||||
_logger.Log(aLevel, "Data length :-{0}-", Data.Length);
|
||||
}
|
||||
|
||||
public int Channel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Clones this instance.
|
||||
/// <remarks>Listner is not cloned</remarks>
|
||||
/// </summary>
|
||||
/// <returns>a clone of this instance</returns>
|
||||
public override object Clone()
|
||||
{
|
||||
RtspData result = new RtspData();
|
||||
result.Channel = this.Channel;
|
||||
if (this.Data != null)
|
||||
result.Data = this.Data.Clone() as byte[];
|
||||
result.SourcePort = this.SourcePort;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// Class containing helper constant for general use headers.
|
||||
/// </summary>
|
||||
public static class RtspHeaderNames
|
||||
{
|
||||
public const string ContentBase = "Content-Base";
|
||||
public const string ContentEncoding = "Content-Encoding";
|
||||
public const string ContentType = "Content-Type";
|
||||
|
||||
public const string Public = "Public";
|
||||
public const string Session = "Session";
|
||||
public const string Transport = "Transport";
|
||||
|
||||
public const string WWWAuthenticate = "WWW-Authenticate";
|
||||
public const string Authorization = "Authorization";
|
||||
}
|
||||
}
|
||||
309
framework/Inspectron.HawkEye/RTSP/Messages/RTSPMessage.cs
Normal file
309
framework/Inspectron.HawkEye/RTSP/Messages/RTSPMessage.cs
Normal file
@@ -0,0 +1,309 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspMessage : RtspChunk
|
||||
{
|
||||
private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
/// <summary>
|
||||
/// The regex to validate the Rtsp message.
|
||||
/// </summary>
|
||||
private static readonly Regex _rtspVersionTest = new Regex(@"^RTSP/\d\.\d", RegexOptions.Compiled);
|
||||
/// <summary>
|
||||
/// Create the good type of Rtsp Message from the header.
|
||||
/// </summary>
|
||||
/// <param name="aRequestLine">A request line.</param>
|
||||
/// <returns>An Rtsp message</returns>
|
||||
public static RtspMessage GetRtspMessage(string aRequestLine)
|
||||
{
|
||||
// We can't determine the message
|
||||
if (string.IsNullOrEmpty(aRequestLine))
|
||||
return new RtspMessage();
|
||||
string[] requestParts = aRequestLine.Split(new char[] { ' ' }, 3);
|
||||
RtspMessage returnValue;
|
||||
if (requestParts.Length == 3)
|
||||
{
|
||||
// A request is : Method SP Request-URI SP RTSP-Version
|
||||
// A response is : RTSP-Version SP Status-Code SP Reason-Phrase
|
||||
// RTSP-Version = "RTSP" "/" 1*DIGIT "." 1*DIGIT
|
||||
if (_rtspVersionTest.IsMatch(requestParts[2]))
|
||||
returnValue = RtspRequest.GetRtspRequest(requestParts);
|
||||
else if (_rtspVersionTest.IsMatch(requestParts[0]))
|
||||
returnValue = new RtspResponse();
|
||||
else
|
||||
{
|
||||
_logger.Warn(CultureInfo.InvariantCulture, "Got a strange message {0}", aRequestLine);
|
||||
returnValue = new RtspMessage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn(CultureInfo.InvariantCulture, "Got a strange message {0}", aRequestLine);
|
||||
returnValue = new RtspMessage();
|
||||
}
|
||||
returnValue.Command = aRequestLine;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RtspMessage"/> class.
|
||||
/// </summary>
|
||||
public RtspMessage()
|
||||
{
|
||||
Data = new byte[0];
|
||||
Creation = DateTime.Now;
|
||||
}
|
||||
|
||||
private Dictionary<string, string> _headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
internal protected string[] commandArray;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the creation time.
|
||||
/// </summary>
|
||||
/// <value>The creation time.</value>
|
||||
public DateTime Creation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the command of the message (first line).
|
||||
/// </summary>
|
||||
/// <value>The command.</value>
|
||||
public string Command
|
||||
{
|
||||
get
|
||||
{
|
||||
if (commandArray == null)
|
||||
return string.Empty;
|
||||
return string.Join(" ", commandArray);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
commandArray = new string[] { String.Empty };
|
||||
else
|
||||
commandArray = value.Split(new char[] {' '}, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Method of the message (eg OPTIONS, DESCRIBE, SETUP, PLAY).
|
||||
/// </summary>
|
||||
/// <value>The Method</value>
|
||||
public string Method
|
||||
{
|
||||
get
|
||||
{
|
||||
if (commandArray == null)
|
||||
return string.Empty;
|
||||
return commandArray[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the headers of the message.
|
||||
/// </summary>
|
||||
/// <value>The headers.</value>
|
||||
public Dictionary<string, string> Headers
|
||||
{
|
||||
get
|
||||
{
|
||||
return _headers;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds one header from a string.
|
||||
/// </summary>
|
||||
/// <param name="line">The string containing header of format Header: Value.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="line"/> is null</exception>
|
||||
public void AddHeader(string line)
|
||||
{
|
||||
if (line == (string)null)
|
||||
throw new ArgumentNullException("line");
|
||||
|
||||
//spliter
|
||||
string[] elements = line.Split(new char[] { ':' }, 2);
|
||||
if (elements.Length == 2)
|
||||
{
|
||||
_headers[elements[0].Trim()] = elements[1].TrimStart();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn(CultureInfo.InvariantCulture, "Invalid Header received : -{0}-", line);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Ccommande Seqquence number.
|
||||
/// <remarks>If the header is not define or not a valid number it return 0</remarks>
|
||||
/// </summary>
|
||||
/// <value>The sequence number.</value>
|
||||
public int CSeq
|
||||
{
|
||||
get
|
||||
{
|
||||
string returnStringValue;
|
||||
int returnValue;
|
||||
if (!(_headers.TryGetValue("CSeq", out returnStringValue) &&
|
||||
int.TryParse(returnStringValue, out returnValue)))
|
||||
returnValue = 0;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
set
|
||||
{
|
||||
_headers["CSeq"] = value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the session ID.
|
||||
/// </summary>
|
||||
/// <value>The session ID.</value>
|
||||
public virtual string Session
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_headers.ContainsKey("Session"))
|
||||
return null;
|
||||
|
||||
return _headers["Session"];
|
||||
}
|
||||
set
|
||||
{
|
||||
_headers["Session"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialises the length of the data byte array from content lenth header.
|
||||
/// </summary>
|
||||
public void InitialiseDataFromContentLength()
|
||||
{
|
||||
int dataLength;
|
||||
if (!(_headers.ContainsKey("Content-Length")
|
||||
&& int.TryParse(_headers["Content-Length"], out dataLength)))
|
||||
{
|
||||
dataLength = 0;
|
||||
}
|
||||
this.Data = new byte[dataLength];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the content length header.
|
||||
/// </summary>
|
||||
public void AdjustContentLength()
|
||||
{
|
||||
if (Data.Length > 0)
|
||||
{
|
||||
_headers["Content-Length"] = Data.Length.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
_headers.Remove("Content-Length");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends to the message to a stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="stream"/> is empty</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="stream"/> can't be written.</exception>
|
||||
public void SendTo(Stream stream)
|
||||
{
|
||||
// <pex>
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException("stream");
|
||||
if (!stream.CanWrite)
|
||||
throw
|
||||
new ArgumentException("Stream CanWrite == false, can't send message to it", "stream");
|
||||
// </pex>
|
||||
Contract.EndContractBlock();
|
||||
|
||||
Encoding encoder = ASCIIEncoding.UTF8;
|
||||
StringBuilder outputString = new StringBuilder();
|
||||
|
||||
AdjustContentLength();
|
||||
|
||||
// output header
|
||||
outputString.Append(Command);
|
||||
outputString.Append("\r\n");
|
||||
foreach (KeyValuePair<string, string> item in _headers)
|
||||
{
|
||||
outputString.AppendFormat("{0}: {1}\r\n", item.Key, item.Value);
|
||||
}
|
||||
outputString.Append("\r\n");
|
||||
byte[] buffer = encoder.GetBytes(outputString.ToString());
|
||||
lock(stream) {
|
||||
stream.Write(buffer, 0, buffer.Length);
|
||||
|
||||
// Output data
|
||||
if (Data.Length > 0)
|
||||
stream.Write(Data, 0, Data.Length);
|
||||
|
||||
}
|
||||
stream.Flush();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Logs the message.
|
||||
/// </summary>
|
||||
/// <param name="aLevel">A log level.</param>
|
||||
public override void LogMessage(NLog.LogLevel aLevel)
|
||||
{
|
||||
// Default value to debug
|
||||
if (aLevel == null)
|
||||
aLevel = NLog.LogLevel.Debug;
|
||||
// if the level is not logged directly return
|
||||
if (!_logger.IsEnabled(aLevel))
|
||||
return;
|
||||
|
||||
_logger.Log(aLevel, "Commande : {0}", Command);
|
||||
foreach (KeyValuePair<string, string> item in _headers)
|
||||
{
|
||||
_logger.Log(aLevel, "Header : {0}: {1}", item.Key, item.Value);
|
||||
}
|
||||
|
||||
if (Data.Length > 0)
|
||||
{
|
||||
_logger.Log(aLevel, "Data :-{0}-", ASCIIEncoding.ASCII.GetString(Data));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Crée un nouvel objet qui est une copie de l'instance en cours.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Nouvel objet qui est une copie de cette instance.
|
||||
/// </returns>
|
||||
public override object Clone()
|
||||
{
|
||||
RtspMessage returnValue = GetRtspMessage(this.Command);
|
||||
|
||||
foreach (var item in this.Headers)
|
||||
{
|
||||
if (item.Value == null)
|
||||
returnValue.Headers.Add(item.Key.Clone() as string, null);
|
||||
else
|
||||
returnValue.Headers.Add(item.Key.Clone() as string, item.Value.Clone() as string);
|
||||
}
|
||||
returnValue.Data = this.Data.Clone() as byte[];
|
||||
returnValue.SourcePort = this.SourcePort;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
191
framework/Inspectron.HawkEye/RTSP/Messages/RTSPRequest.cs
Normal file
191
framework/Inspectron.HawkEye/RTSP/Messages/RTSPRequest.cs
Normal file
@@ -0,0 +1,191 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// An Rtsp Request
|
||||
/// </summary>
|
||||
public class RtspRequest : RtspMessage
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Request type.
|
||||
/// </summary>
|
||||
public enum RequestType
|
||||
{
|
||||
UNKNOWN,
|
||||
DESCRIBE,
|
||||
ANNOUNCE,
|
||||
GET_PARAMETER,
|
||||
OPTIONS,
|
||||
PAUSE,
|
||||
PLAY,
|
||||
RECORD,
|
||||
REDIRECT,
|
||||
SETUP,
|
||||
SET_PARAMETER,
|
||||
TEARDOWN,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the request command.
|
||||
/// </summary>
|
||||
/// <param name="aStringRequest">A string request command.</param>
|
||||
/// <returns>The typed request.</returns>
|
||||
internal static RequestType ParseRequest(string aStringRequest)
|
||||
{
|
||||
RequestType returnValue;
|
||||
if (!Enum.TryParse<RequestType>(aStringRequest, true, out returnValue))
|
||||
returnValue = RequestType.UNKNOWN;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Rtsp request.
|
||||
/// </summary>
|
||||
/// <param name="aRequestParts">A request parts.</param>
|
||||
/// <returns>the parsed request</returns>
|
||||
internal static RtspMessage GetRtspRequest(string[] aRequestParts)
|
||||
{
|
||||
// <pex>
|
||||
Debug.Assert(aRequestParts != (string[])null, "aRequestParts");
|
||||
Debug.Assert(aRequestParts.Length != 0, "aRequestParts.Length == 0");
|
||||
// </pex>
|
||||
// we already know this is a Request
|
||||
RtspRequest returnValue;
|
||||
switch (ParseRequest(aRequestParts[0]))
|
||||
{
|
||||
case RequestType.OPTIONS:
|
||||
returnValue = new RtspRequestOptions();
|
||||
break;
|
||||
case RequestType.DESCRIBE:
|
||||
returnValue = new RtspRequestDescribe();
|
||||
break;
|
||||
case RequestType.SETUP:
|
||||
returnValue = new RtspRequestSetup();
|
||||
break;
|
||||
case RequestType.PLAY:
|
||||
returnValue = new RtspRequestPlay();
|
||||
break;
|
||||
case RequestType.PAUSE:
|
||||
returnValue = new RtspRequestPause();
|
||||
break;
|
||||
case RequestType.TEARDOWN:
|
||||
returnValue = new RtspRequestTeardown();
|
||||
break;
|
||||
case RequestType.GET_PARAMETER:
|
||||
returnValue = new RtspRequestGetParameter();
|
||||
break;
|
||||
case RequestType.ANNOUNCE:
|
||||
returnValue = new RtspRequestAnnounce();
|
||||
break;
|
||||
case RequestType.RECORD:
|
||||
returnValue = new RtspRequestRecord();
|
||||
break;
|
||||
/*
|
||||
case RequestType.REDIRECT:
|
||||
break;
|
||||
|
||||
case RequestType.SET_PARAMETER:
|
||||
break;
|
||||
*/
|
||||
case RequestType.UNKNOWN:
|
||||
default:
|
||||
returnValue = new RtspRequest();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RtspRequest"/> class.
|
||||
/// </summary>
|
||||
public RtspRequest()
|
||||
{
|
||||
Command = "OPTIONS * RTSP/1.0";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the request.
|
||||
/// </summary>
|
||||
/// <value>The request in string format.</value>
|
||||
public string Request
|
||||
{
|
||||
get
|
||||
{
|
||||
return commandArray[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the request.
|
||||
/// <remarks>The return value is typed with <see cref="Rtsp.RequestType"/> if the value is not
|
||||
/// reconise the value is sent. The string value can be get by <see cref="Request"/></remarks>
|
||||
/// </summary>
|
||||
/// <value>The request.</value>
|
||||
public RequestType RequestTyped
|
||||
{
|
||||
get
|
||||
{
|
||||
return ParseRequest(commandArray[0]);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Enum.IsDefined(typeof(RequestType), value))
|
||||
commandArray[0] = value.ToString();
|
||||
else
|
||||
commandArray[0] = RequestType.UNKNOWN.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private Uri _RtspUri;
|
||||
/// <summary>
|
||||
/// Gets or sets the Rtsp asked URI.
|
||||
/// </summary>
|
||||
/// <value>The Rtsp asked URI.</value>
|
||||
/// <remarks>The request with uri * is return with null URI</remarks>
|
||||
public Uri RtspUri
|
||||
{
|
||||
get
|
||||
{
|
||||
if (commandArray.Length < 2 || commandArray[1]=="*")
|
||||
return null;
|
||||
if (_RtspUri == null)
|
||||
Uri.TryCreate(commandArray[1], UriKind.Absolute, out _RtspUri);
|
||||
return _RtspUri;
|
||||
}
|
||||
set
|
||||
{
|
||||
_RtspUri = value;
|
||||
if (commandArray.Length < 2)
|
||||
{
|
||||
Array.Resize(ref commandArray, 3);
|
||||
}
|
||||
commandArray[1] = (value != null ? value.ToString().TrimEnd('/') : "*");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assiociate OK response with the request.
|
||||
/// </summary>
|
||||
/// <returns>an Rtsp response correcponding to request.</returns>
|
||||
public virtual RtspResponse CreateResponse()
|
||||
{
|
||||
RtspResponse returnValue = new RtspResponse();
|
||||
returnValue.ReturnCode = 200;
|
||||
returnValue.CSeq = this.CSeq;
|
||||
if (this.Headers.ContainsKey(RtspHeaderNames.Session))
|
||||
{
|
||||
returnValue.Headers[RtspHeaderNames.Session] = this.Headers[RtspHeaderNames.Session];
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public Object ContextData { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspRequestAnnounce : RtspRequest
|
||||
{
|
||||
// constructor
|
||||
|
||||
public RtspRequestAnnounce()
|
||||
{
|
||||
Command = "ANNOUNCE * RTSP/1.0";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspRequestDescribe : RtspRequest
|
||||
{
|
||||
|
||||
// constructor
|
||||
|
||||
public RtspRequestDescribe()
|
||||
{
|
||||
Command = "DESCRIBE * RTSP/1.0";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspRequestGetParameter : RtspRequest
|
||||
{
|
||||
|
||||
// Constructor
|
||||
public RtspRequestGetParameter()
|
||||
{
|
||||
Command = "GET_PARAMETER * RTSP/1.0";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspRequestOptions : RtspRequest
|
||||
{
|
||||
|
||||
// Constructor
|
||||
public RtspRequestOptions()
|
||||
{
|
||||
Command = "OPTIONS * RTSP/1.0";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assiociate OK response with the request.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// an Rtsp response corresponding to request.
|
||||
/// </returns>
|
||||
public override RtspResponse CreateResponse()
|
||||
{
|
||||
RtspResponse response = base.CreateResponse();
|
||||
// Add genric suported operations.
|
||||
response.Headers.Add(RtspHeaderNames.Public, "OPTIONS,DESCRIBE,ANNOUNCE,SETUP,PLAY,PAUSE,TEARDOWN,GET_PARAMETER,SET_PARAMETER,REDIRECT");
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspRequestPause : RtspRequest
|
||||
{
|
||||
|
||||
// Constructor
|
||||
public RtspRequestPause()
|
||||
{
|
||||
Command = "PAUSE * RTSP/1.0";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspRequestPlay : RtspRequest
|
||||
{
|
||||
|
||||
// Constructor
|
||||
public RtspRequestPlay()
|
||||
{
|
||||
Command = "PLAY * RTSP/1.0";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspRequestRecord : RtspRequest
|
||||
{
|
||||
public RtspRequestRecord()
|
||||
{
|
||||
Command = "RECORD * RTSP/1.0";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspRequestSetup : RtspRequest
|
||||
{
|
||||
|
||||
// Constructor
|
||||
public RtspRequestSetup()
|
||||
{
|
||||
Command = "SETUP * RTSP/1.0";
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the transports associate with the request.
|
||||
/// </summary>
|
||||
/// <value>The transport.</value>
|
||||
public RtspTransport[] GetTransports()
|
||||
{
|
||||
|
||||
if (!Headers.ContainsKey(RtspHeaderNames.Transport))
|
||||
return new RtspTransport[] { new RtspTransport() };
|
||||
|
||||
string[] items = Headers[RtspHeaderNames.Transport].Split(',');
|
||||
return Array.ConvertAll<string, RtspTransport>(items,
|
||||
new Converter<string, RtspTransport>(RtspTransport.Parse));
|
||||
|
||||
}
|
||||
|
||||
public void AddTransport(RtspTransport newTransport)
|
||||
{
|
||||
string actualTransport = string.Empty;
|
||||
if(Headers.ContainsKey(RtspHeaderNames.Transport))
|
||||
actualTransport = Headers[RtspHeaderNames.Transport] + ",";
|
||||
Headers[RtspHeaderNames.Transport] = actualTransport + newTransport.ToString();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspRequestTeardown : RtspRequest
|
||||
{
|
||||
|
||||
// Constructor
|
||||
public RtspRequestTeardown()
|
||||
{
|
||||
Command = "TEARDOWN * RTSP/1.0";
|
||||
}
|
||||
}
|
||||
}
|
||||
228
framework/Inspectron.HawkEye/RTSP/Messages/RTSPResponse.cs
Normal file
228
framework/Inspectron.HawkEye/RTSP/Messages/RTSPResponse.cs
Normal file
@@ -0,0 +1,228 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspResponse : RtspMessage
|
||||
{
|
||||
public const int DEFAULT_TIMEOUT = 60;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default error message for an error code.
|
||||
/// </summary>
|
||||
/// <param name="aErrorCode">An error code.</param>
|
||||
/// <returns>The default error message associate</returns>
|
||||
private static string GetDefaultError(int aErrorCode)
|
||||
{
|
||||
switch (aErrorCode)
|
||||
{
|
||||
|
||||
case 100: return "Continue";
|
||||
|
||||
case 200: return "OK";
|
||||
case 201: return "Created";
|
||||
case 250: return "Low on Storage Space";
|
||||
|
||||
case 300: return "Multiple Choices";
|
||||
case 301: return "Moved Permanently";
|
||||
case 302: return "Moved Temporarily";
|
||||
case 303: return "See Other";
|
||||
case 305: return "Use Proxy";
|
||||
|
||||
case 400: return "Bad Request";
|
||||
case 401: return "Unauthorized";
|
||||
case 402: return "Payment Required";
|
||||
case 403: return "Forbidden";
|
||||
case 404: return "Not Found";
|
||||
case 405: return "Method Not Allowed";
|
||||
case 406: return "Not Acceptable";
|
||||
case 407: return "Proxy Authentication Required";
|
||||
case 408: return "Request Timeout";
|
||||
case 410: return "Gone";
|
||||
case 411: return "Length Required";
|
||||
case 412: return "Precondition Failed";
|
||||
case 413: return "Request Entity Too Large";
|
||||
case 414: return "Request-URI Too Long";
|
||||
case 415: return "Unsupported Media Type";
|
||||
case 451: return "Invalid parameter";
|
||||
case 452: return "Illegal Conference Identifier";
|
||||
case 453: return "Not Enough Bandwidth";
|
||||
case 454: return "Session Not Found";
|
||||
case 455: return "Method Not Valid In This State";
|
||||
case 456: return "Header Field Not Valid";
|
||||
case 457: return "Invalid Range";
|
||||
case 458: return "Parameter Is Read-Only";
|
||||
case 459: return "Aggregate Operation Not Allowed";
|
||||
case 460: return "Only Aggregate Operation Allowed";
|
||||
case 461: return "Unsupported Transport";
|
||||
case 462: return "Destination Unreachable";
|
||||
|
||||
case 500: return "Internal Server Error";
|
||||
case 501: return "Not Implemented";
|
||||
case 502: return "Bad Gateway";
|
||||
case 503: return "Service Unavailable";
|
||||
case 504: return "Gateway Timeout";
|
||||
case 505: return "RTSP Version Not Supported";
|
||||
case 551: return "Option not support";
|
||||
default:
|
||||
return "Return: " + aErrorCode.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RtspResponse"/> class.
|
||||
/// </summary>
|
||||
public RtspResponse()
|
||||
: base()
|
||||
{
|
||||
// Initialise with a default result code.
|
||||
Command = "RTSP/1.0 200 OK";
|
||||
}
|
||||
|
||||
private int _returnCode;
|
||||
/// <summary>
|
||||
/// Gets or sets the return code of the response.
|
||||
/// </summary>
|
||||
/// <value>The return code.</value>
|
||||
/// <remarks>On change the error message is set to the default one associate with the code</remarks>
|
||||
public int ReturnCode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_returnCode == 0 && commandArray.Length >= 2)
|
||||
{
|
||||
int.TryParse(commandArray[1], out _returnCode);
|
||||
}
|
||||
|
||||
return _returnCode;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (ReturnCode != value)
|
||||
{
|
||||
_returnCode = value;
|
||||
// make sure we have the room
|
||||
if (commandArray.Length < 3)
|
||||
{
|
||||
Array.Resize(ref commandArray, 3);
|
||||
}
|
||||
commandArray[1] = value.ToString(CultureInfo.InvariantCulture);
|
||||
commandArray[2] = GetDefaultError(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the error/return message.
|
||||
/// </summary>
|
||||
/// <value>The return message.</value>
|
||||
public string ReturnMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (commandArray.Length < 3)
|
||||
return String.Empty;
|
||||
return commandArray[2];
|
||||
}
|
||||
set
|
||||
{
|
||||
// Make sure we have the room
|
||||
if (commandArray.Length < 3)
|
||||
{
|
||||
Array.Resize(ref commandArray, 3);
|
||||
}
|
||||
commandArray[2] = value;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance correspond to an OK response.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is OK; otherwise, <c>false</c>.</value>
|
||||
public bool IsOk
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ReturnCode > 0 && ReturnCode < 400)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the timeout in second.
|
||||
/// <remarks>The default timeout is 60.</remarks>
|
||||
/// </summary>
|
||||
/// <value>The timeout.</value>
|
||||
public int Timeout
|
||||
{
|
||||
get
|
||||
{
|
||||
int returnValue = DEFAULT_TIMEOUT;
|
||||
if (Headers.ContainsKey(RtspHeaderNames.Session))
|
||||
{
|
||||
string[] parts = Headers[RtspHeaderNames.Session].Split(';');
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
string[] subParts = parts[1].Split('=');
|
||||
if (subParts.Length > 1 &&
|
||||
subParts[0].ToUpperInvariant() == "TIMEOUT")
|
||||
if (!int.TryParse(subParts[1], out returnValue))
|
||||
returnValue = DEFAULT_TIMEOUT;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
set
|
||||
{
|
||||
if(Headers.ContainsKey(RtspHeaderNames.Session))
|
||||
if (value != DEFAULT_TIMEOUT)
|
||||
{
|
||||
|
||||
Headers[RtspHeaderNames.Session] = Headers[RtspHeaderNames.Session].Split(';').First()
|
||||
+ ";timeout=" + value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
//remove timeout part
|
||||
Headers[RtspHeaderNames.Session] = Headers[RtspHeaderNames.Session].Split(';').First();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the session ID.
|
||||
/// </summary>
|
||||
/// <value>The session ID.</value>
|
||||
public override string Session
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Headers.ContainsKey(RtspHeaderNames.Session))
|
||||
return null;
|
||||
|
||||
return Headers[RtspHeaderNames.Session].Split(';')[0];
|
||||
}
|
||||
set
|
||||
{
|
||||
if(Timeout != DEFAULT_TIMEOUT)
|
||||
{
|
||||
Headers[RtspHeaderNames.Session] = value + ";timeout=" + Timeout.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
Headers[RtspHeaderNames.Session] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the original request associate with the response.
|
||||
/// </summary>
|
||||
/// <value>The original request.</value>
|
||||
public RtspRequest OriginalRequest
|
||||
{ get; set; }
|
||||
}
|
||||
}
|
||||
367
framework/Inspectron.HawkEye/RTSP/Messages/RTSPTransport.cs
Normal file
367
framework/Inspectron.HawkEye/RTSP/Messages/RTSPTransport.cs
Normal file
@@ -0,0 +1,367 @@
|
||||
using System;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Text;
|
||||
|
||||
namespace Inspectron.HawkEye.RTSP.Messages
|
||||
{
|
||||
public class RtspTransport
|
||||
{
|
||||
public RtspTransport()
|
||||
{
|
||||
// Default value is true in RFC
|
||||
IsMulticast = true;
|
||||
LowerTransport = LowerTransportType.UDP;
|
||||
Mode = "PLAY";
|
||||
}
|
||||
/*
|
||||
RFC
|
||||
Transport = "Transport" ":"
|
||||
1\#transport-spec
|
||||
transport-spec = transport-protocol/profile[/lower-transport]
|
||||
*parameter
|
||||
transport-protocol = "RTP"
|
||||
profile = "AVP"
|
||||
lower-transport = "TCP" | "UDP"
|
||||
parameter = ( "unicast" | "multicast" )
|
||||
| ";" "destination" [ "=" address ]
|
||||
| ";" "interleaved" "=" channel [ "-" channel ]
|
||||
| ";" "append"
|
||||
| ";" "ttl" "=" ttl
|
||||
| ";" "layers" "=" 1*DIGIT
|
||||
| ";" "port" "=" port [ "-" port ]
|
||||
| ";" "client_port" "=" port [ "-" port ]
|
||||
| ";" "server_port" "=" port [ "-" port ]
|
||||
| ";" "ssrc" "=" ssrc
|
||||
| ";" "mode" = <"> 1\#mode <">
|
||||
ttl = 1*3(DIGIT)
|
||||
port = 1*5(DIGIT)
|
||||
ssrc = 8*8(HEX)
|
||||
channel = 1*3(DIGIT)
|
||||
address = host
|
||||
mode = <"> *Method <"> | Method
|
||||
|
||||
*/
|
||||
/// <summary>
|
||||
/// List of transport
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public enum TransportType
|
||||
{
|
||||
/// <summary>
|
||||
/// RTP for now
|
||||
/// </summary>
|
||||
RTP,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Profile type
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public enum ProfileType
|
||||
{
|
||||
/// <summary>
|
||||
/// RTP/AVP of now
|
||||
/// </summary>
|
||||
AVP,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transport type.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public enum LowerTransportType
|
||||
{
|
||||
/// <summary>
|
||||
/// UDP transport.
|
||||
/// </summary>
|
||||
UDP,
|
||||
/// <summary>
|
||||
/// TCP transport.
|
||||
/// </summary>
|
||||
TCP,
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the transport.
|
||||
/// </summary>
|
||||
/// <value>The transport.</value>
|
||||
public TransportType Transport { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the profile.
|
||||
/// </summary>
|
||||
/// <value>The profile.</value>
|
||||
public ProfileType Profile { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the lower transport.
|
||||
/// </summary>
|
||||
/// <value>The lower transport.</value>
|
||||
public LowerTransportType LowerTransport { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is multicast.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is multicast; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsMulticast { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the destination.
|
||||
/// </summary>
|
||||
/// <value>The destination.</value>
|
||||
public string Destination { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the source.
|
||||
/// </summary>
|
||||
/// <value>The source.</value>
|
||||
public string Source { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the interleaved.
|
||||
/// </summary>
|
||||
/// <value>The interleaved.</value>
|
||||
public PortCouple Interleaved { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is append.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is append; otherwise, <c>false</c>.</value>
|
||||
public bool IsAppend { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the TTL.
|
||||
/// </summary>
|
||||
/// <value>The TTL.</value>
|
||||
public int TTL { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the layers.
|
||||
/// </summary>
|
||||
/// <value>The layers.</value>
|
||||
public int Layers { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the port.
|
||||
/// </summary>
|
||||
/// <value>The port.</value>
|
||||
public PortCouple Port { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the client port.
|
||||
/// </summary>
|
||||
/// <value>The client port.</value>
|
||||
public PortCouple ClientPort { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the server port.
|
||||
/// </summary>
|
||||
/// <value>The server port.</value>
|
||||
public PortCouple ServerPort { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the S SRC.
|
||||
/// </summary>
|
||||
/// <value>The S SRC.</value>
|
||||
public string SSrc { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the mode.
|
||||
/// </summary>
|
||||
/// <value>The mode.</value>
|
||||
public string Mode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parses the specified transport string.
|
||||
/// </summary>
|
||||
/// <param name="aTransportString">A transport string.</param>
|
||||
/// <returns>The transport class.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="aTransportString"/> is null.</exception>
|
||||
public static RtspTransport Parse(string aTransportString)
|
||||
{
|
||||
if (aTransportString == null)
|
||||
throw new ArgumentNullException("aTransportString");
|
||||
Contract.EndContractBlock();
|
||||
|
||||
RtspTransport returnValue = new RtspTransport();
|
||||
|
||||
string[] transportPart = aTransportString.Split(';');
|
||||
string[] transportProtocolPart = transportPart[0].Split('/');
|
||||
|
||||
ReadTransport(returnValue, transportProtocolPart);
|
||||
ReadProfile(returnValue, transportProtocolPart);
|
||||
ReadLowerTransport(returnValue, transportProtocolPart);
|
||||
|
||||
foreach (string part in transportPart)
|
||||
{
|
||||
string[] subPart = part.Split('=');
|
||||
|
||||
switch (subPart[0].ToUpperInvariant())
|
||||
{
|
||||
case "UNICAST":
|
||||
returnValue.IsMulticast = false;
|
||||
break;
|
||||
case "MULTICAST":
|
||||
returnValue.IsMulticast = true;
|
||||
break;
|
||||
case "DESTINATION":
|
||||
if (subPart.Length == 2)
|
||||
returnValue.Destination = subPart[1];
|
||||
break;
|
||||
case "SOURCE":
|
||||
if (subPart.Length == 2)
|
||||
returnValue.Source = subPart[1];
|
||||
break;
|
||||
case "INTERLEAVED":
|
||||
returnValue.IsMulticast = false;
|
||||
if (subPart.Length < 2)
|
||||
throw new ArgumentException("interleaved value invalid", "aTransportString");
|
||||
|
||||
returnValue.Interleaved = PortCouple.Parse(subPart[1]);
|
||||
break;
|
||||
case "APPEND":
|
||||
returnValue.IsAppend = true;
|
||||
break;
|
||||
case "TTL":
|
||||
int ttl = 0;
|
||||
if (subPart.Length < 2 || !int.TryParse(subPart[1], out ttl))
|
||||
throw new ArgumentException("TTL value invalid", "aTransportString");
|
||||
returnValue.TTL = ttl;
|
||||
break;
|
||||
case "LAYERS":
|
||||
int layers = 0;
|
||||
if (subPart.Length < 2 || !int.TryParse(subPart[1], out layers))
|
||||
throw new ArgumentException("Layers value invalid", "aTransportString");
|
||||
returnValue.TTL = layers;
|
||||
break;
|
||||
case "PORT":
|
||||
if (subPart.Length < 2)
|
||||
throw new ArgumentException("Port value invalid", "aTransportString");
|
||||
returnValue.Port = PortCouple.Parse(subPart[1]);
|
||||
break;
|
||||
case "CLIENT_PORT":
|
||||
if (subPart.Length < 2)
|
||||
throw new ArgumentException("client_port value invalid", "aTransportString");
|
||||
returnValue.ClientPort = PortCouple.Parse(subPart[1]);
|
||||
break;
|
||||
case "SERVER_PORT":
|
||||
if (subPart.Length < 2)
|
||||
throw new ArgumentException("server_port value invalid", "aTransportString");
|
||||
returnValue.ServerPort = PortCouple.Parse(subPart[1]);
|
||||
break;
|
||||
case "SSRC":
|
||||
if (subPart.Length < 2)
|
||||
throw new ArgumentException("ssrc value invalid", "aTransportString");
|
||||
returnValue.SSrc = subPart[1];
|
||||
break;
|
||||
case "MODE":
|
||||
if (subPart.Length < 2)
|
||||
throw new ArgumentException("mode value invalid", "aTransportString");
|
||||
returnValue.Mode = subPart[1];
|
||||
break;
|
||||
default:
|
||||
// TODO log invalid part
|
||||
break;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private static void ReadLowerTransport(RtspTransport returnValue, string[] transportProtocolPart)
|
||||
{
|
||||
if (transportProtocolPart.Length == 3)
|
||||
{
|
||||
LowerTransportType lowerTransport;
|
||||
if (!Enum.TryParse<LowerTransportType>(transportProtocolPart[2], out lowerTransport))
|
||||
throw new ArgumentException("Lower transport type invalid", "aTransportString");
|
||||
returnValue.LowerTransport = lowerTransport;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReadProfile(RtspTransport returnValue, string[] transportProtocolPart)
|
||||
{
|
||||
ProfileType profile;
|
||||
if (transportProtocolPart.Length < 2 || !Enum.TryParse<ProfileType>(transportProtocolPart[1], out profile))
|
||||
throw new ArgumentException("Transport profile type invalid", "aTransportString");
|
||||
returnValue.Profile = profile;
|
||||
}
|
||||
|
||||
private static void ReadTransport(RtspTransport returnValue, string[] transportProtocolPart)
|
||||
{
|
||||
TransportType transport;
|
||||
if (!Enum.TryParse<TransportType>(transportProtocolPart[0], out transport))
|
||||
throw new ArgumentException("Transport type invalid", "aTransportString");
|
||||
returnValue.Transport = transport;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String"/> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder transportString = new StringBuilder();
|
||||
transportString.Append(Transport.ToString());
|
||||
transportString.Append('/');
|
||||
transportString.Append(Profile.ToString());
|
||||
transportString.Append('/');
|
||||
transportString.Append(LowerTransport.ToString());
|
||||
if (LowerTransport == LowerTransportType.TCP)
|
||||
{
|
||||
transportString.Append(";unicast");
|
||||
}
|
||||
if (LowerTransport == LowerTransportType.UDP)
|
||||
{
|
||||
transportString.Append(';');
|
||||
transportString.Append(IsMulticast ? "multicast" : "unicast");
|
||||
}
|
||||
if (Destination != null)
|
||||
{
|
||||
transportString.Append(";destination=");
|
||||
transportString.Append(Destination);
|
||||
}
|
||||
if (Source != null)
|
||||
{
|
||||
transportString.Append(";source=");
|
||||
transportString.Append(Source);
|
||||
}
|
||||
if (Interleaved != null)
|
||||
{
|
||||
transportString.Append(";interleaved=");
|
||||
transportString.Append(Interleaved.ToString());
|
||||
}
|
||||
if (IsAppend)
|
||||
{
|
||||
transportString.Append(";append");
|
||||
}
|
||||
if (TTL > 0)
|
||||
{
|
||||
transportString.Append(";ttl=");
|
||||
transportString.Append(TTL);
|
||||
}
|
||||
if (Layers > 0)
|
||||
{
|
||||
transportString.Append(";layers=");
|
||||
transportString.Append(Layers);
|
||||
}
|
||||
if (Port != null)
|
||||
{
|
||||
transportString.Append(";port=");
|
||||
transportString.Append(Port.ToString());
|
||||
}
|
||||
if (ClientPort != null)
|
||||
{
|
||||
transportString.Append(";client_port=");
|
||||
transportString.Append(ClientPort.ToString());
|
||||
}
|
||||
if (ServerPort != null)
|
||||
{
|
||||
transportString.Append(";server_port=");
|
||||
transportString.Append(ServerPort.ToString());
|
||||
}
|
||||
if (SSrc != null)
|
||||
{
|
||||
transportString.Append(";ssrc=");
|
||||
transportString.Append(SSrc);
|
||||
}
|
||||
if (Mode != null && Mode != "PLAY")
|
||||
{
|
||||
transportString.Append(";mode=");
|
||||
transportString.Append(Mode);
|
||||
}
|
||||
return transportString.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user