hawkeye camera support(not tested)
This commit is contained in:
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user