368 lines
14 KiB
C#
368 lines
14 KiB
C#
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();
|
|
}
|
|
|
|
}
|
|
}
|