Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rtsp over Http #97

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions RTSP.Tests/RTSPListenerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public void ReceiveData()

Assert.AreEqual(11, dataMessage.Channel);
Assert.AreSame(testedListener, dataMessage.SourcePort);
Assert.AreEqual(data, dataMessage.Data);
Assert.AreEqual(data, dataMessage.Data[..dataMessage.DataLength]);
}

[Test]
Expand Down Expand Up @@ -294,7 +294,8 @@ public void SendDataAsync()
var data = new RtspData
{
Channel = 12,
Data = Enumerable.Range(0, dataLenght).Select(x => (byte)x).ToArray()
Data = Enumerable.Range(0, dataLenght).Select(x => (byte)x).ToArray(),
DataLength = dataLenght,
};

// Run
Expand Down
1 change: 1 addition & 0 deletions RTSP.Tests/RTSPUtilsTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NUnit.Framework;
using Rtsp.Utils;
using System;

namespace Rtsp.Tests
Expand Down
18 changes: 0 additions & 18 deletions RTSP/ArrayUtils.cs

This file was deleted.

130 changes: 115 additions & 15 deletions RTSP/Authentication.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,132 @@
using Rtsp.Messages;
using System;
using System.Security.Cryptography;
using System.Text;
using System.Collections.Generic;
using System.Net;

namespace Rtsp
{

// WWW-Authentication and Authorization Headers
public abstract class Authentication
{
protected readonly string username;
protected readonly string password;
protected readonly string realm;
public NetworkCredential Credentials { get; }

// Constructor
public Authentication(string username, string password, string realm)
protected Authentication(NetworkCredential credentials)
{
this.username = username;
this.password = password;
this.realm = realm;
Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials));
}

public abstract string GetHeader();
public abstract string GetResponse(uint nonceCounter, string uri, string method, byte[] entityBodyBytes);

Check warning on line 18 in RTSP/Authentication.cs

View workflow job for this annotation

GitHub Actions / build

Argument type 'uint' is not CLS-compliant
public abstract bool IsValid(RtspMessage message);

public static Authentication Create(NetworkCredential credential, string authenticateHeader)
{
authenticateHeader = authenticateHeader ??
throw new ArgumentNullException(nameof(authenticateHeader));

if (authenticateHeader.StartsWith("Basic", StringComparison.OrdinalIgnoreCase))
return new AuthenticationBasic(credential);

if (authenticateHeader.StartsWith("Digest", StringComparison.OrdinalIgnoreCase))
{
int spaceIndex = authenticateHeader.IndexOf(' ');

if (spaceIndex != -1)
{
string parameters = authenticateHeader.Substring(++spaceIndex);

Dictionary<string, string> parameterNameToValueMap = ParseParameters(parameters);

if (!parameterNameToValueMap.TryGetValue("REALM", out string realm))
throw new ArgumentException("\"realm\" parameter is not found");
if (!parameterNameToValueMap.TryGetValue("NONCE", out string nonce))
throw new ArgumentException("\"nonce\" parameter is not found");

parameterNameToValueMap.TryGetValue("QOP", out string qop);
return new AuthenticationDigest(credential, realm, nonce, qop);
}
}

throw new ArgumentOutOfRangeException(authenticateHeader,
$"Invalid authenticate header: {authenticateHeader}");
}

private static Dictionary<string, string> ParseParameters(string parameters)
{
var parameterNameToValueMap = new Dictionary<string, string>();

int parameterStartOffset = 0;
while (parameterStartOffset < parameters.Length)
{
int equalsSignIndex = parameters.IndexOf('=', parameterStartOffset);

if (equalsSignIndex == -1)
break;

int parameterNameLength = equalsSignIndex - parameterStartOffset;
string parameterName = parameters.Substring(parameterStartOffset, parameterNameLength).Trim()
.ToUpperInvariant();

public abstract bool IsValid(RtspMessage received_message);
++equalsSignIndex;


int nonSpaceIndex = equalsSignIndex;

if (nonSpaceIndex == parameters.Length)
break;

while (parameters[nonSpaceIndex] == ' ')
if (++nonSpaceIndex == parameters.Length)
break;

int parameterValueStartPos;
int parameterValueEndPos;
int commaIndex;

if (parameters[nonSpaceIndex] == '\"')
{
parameterValueStartPos = parameters.IndexOf('\"', equalsSignIndex);

if (parameterValueStartPos == -1)
break;

++parameterValueStartPos;

parameterValueEndPos = parameters.IndexOf('\"', parameterValueStartPos);

if (parameterValueEndPos == -1)
break;

commaIndex = parameters.IndexOf(',', parameterValueEndPos + 1);

if (commaIndex != -1)
parameterStartOffset = ++commaIndex;
else
parameterStartOffset = parameters.Length;
}
else
{
parameterValueStartPos = nonSpaceIndex;

commaIndex = parameters.IndexOf(',', ++nonSpaceIndex);

if (commaIndex != -1)
{
parameterValueEndPos = commaIndex;
parameterStartOffset = ++commaIndex;
}
else
{
parameterValueEndPos = parameters.Length;
parameterStartOffset = parameterValueEndPos;
}
}

int parameterValueLength = parameterValueEndPos - parameterValueStartPos;
string parameterValue = parameters.Substring(parameterValueStartPos, parameterValueLength);

parameterNameToValueMap[parameterName] = parameterValue;
}

return parameterNameToValueMap;
}
}
}
}
42 changes: 9 additions & 33 deletions RTSP/AuthenticationBasic.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,22 @@
using Rtsp.Messages;
using System;
using System.Security.Cryptography;
using System.Net;
using System.Text;

namespace Rtsp
{

// WWW-Authentication and Authorization Headers
public class AuthenticationBasic : Authentication
public class AuthenticationBasic(NetworkCredential credentials) : Authentication(credentials)
{
private const char quote = '\"';

// Constructor
public AuthenticationBasic(string username, string password, string realm)
: base(username, password, realm)
{
}

public override string GetHeader()
public override string GetResponse(uint nonceCounter, string uri, string method, byte[] entityBodyBytes)

Check warning on line 12 in RTSP/AuthenticationBasic.cs

View workflow job for this annotation

GitHub Actions / build

Argument type 'uint' is not CLS-compliant
{
return $"Basic realm=\"{realm}\"";
string usernamePasswordHash = $"{Credentials.UserName}:{Credentials.Password}";
return $"Bassic {Convert.ToBase64String(Encoding.UTF8.GetBytes(usernamePasswordHash))}";
}


public override bool IsValid(RtspMessage received_message)
public override bool IsValid(RtspMessage message)
{

string? authorization = received_message.Headers["Authorization"];
string? authorization = message.Headers["Authorization"];


// Check Username and Password
Expand All @@ -39,7 +29,7 @@
string decoded_username = decoded.Substring(0, split_position);
string decoded_password = decoded.Substring(split_position + 1);

if ((decoded_username == username) && (decoded_password == password))
if ((decoded_username == Credentials.UserName) && (decoded_password == Credentials.Password))
{
// _logger.Debug("Basic Authorization passed");
return true;
Expand All @@ -54,21 +44,7 @@
return false;
}

public override string ToString() => $"Authentication Basic";


// Generate Basic or Digest Authorization
public static string? GenerateAuthorization(string username, string password,
string realm, string nonce, string url, string command)
{

if (username == null || username.Length == 0) return null;
if (password == null || password.Length == 0) return null;
if (realm == null || realm.Length == 0) return null;

byte[] credentials = Encoding.UTF8.GetBytes(username + ":" + password);
string credentials_base64 = Convert.ToBase64String(credentials);
string basic_authorization = "Basic " + credentials_base64;
return basic_authorization;
}
}
}
Loading
Loading