Skip to content

Commit

Permalink
add SkStackPanaSessionEstablishmentException.{PaaAddress|Channel|PanI…
Browse files Browse the repository at this point in the history
…d} to be able to refer the parameters specified for the PANA authentication
  • Loading branch information
smdn committed Jun 27, 2024
1 parent 6121459 commit 7fc24f9
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ namespace Smdn.Net.SkStackIP;
#pragma warning disable IDE0040
partial class SkStackClient {
#pragma warning restore IDE0040
private static SkStackPanaSessionEstablishmentException CreatePanaSessionEstablishmentException(
IPAddress paaAddress,
SkStackEventNumber eventNumber,
IPAddress address
)
=> new(
message: null,
paaAddress: paaAddress,
address: address,
eventNumber: eventNumber
);

/// <summary>
/// <para>Sends a command <c>SKJOIN</c>.</para>
/// </summary>
Expand All @@ -22,18 +34,33 @@ partial class SkStackClient {
public ValueTask<SkStackResponse> SendSKJOINAsync(
IPAddress ipv6address,
CancellationToken cancellationToken = default
)
=> SendSKJOINAsync(
ipv6address: ipv6address,
createPanaSessionEstablishmentException: (eventNumber, address) => CreatePanaSessionEstablishmentException(ipv6address, eventNumber, address),
cancellationToken: cancellationToken
);

internal ValueTask<SkStackResponse> SendSKJOINAsync(
IPAddress ipv6address,
Func<SkStackEventNumber, IPAddress, Exception>? createPanaSessionEstablishmentException,
CancellationToken cancellationToken
)
{
if (ipv6address is null)
throw new ArgumentNullException(nameof(ipv6address));
if (ipv6address.AddressFamily != AddressFamily.InterNetworkV6)
throw new ArgumentException($"`{nameof(ipv6address)}.{nameof(IPAddress.AddressFamily)}` must be {nameof(AddressFamily.InterNetworkV6)}");

return SKJOIN(ipv6address, cancellationToken);
return SKJOIN(ipv6address, createPanaSessionEstablishmentException, cancellationToken);

async ValueTask<SkStackResponse> SKJOIN(IPAddress addr, CancellationToken ct)
async ValueTask<SkStackResponse> SKJOIN(
IPAddress addr,
Func<SkStackEventNumber, IPAddress, Exception>? createException,
CancellationToken ct
)
{
var (response, _) = await SKJOIN_SKREJOIN(SkStackCommandNames.SKJOIN, addr, ct).ConfigureAwait(false);
var (response, _) = await SKJOIN_SKREJOIN(SkStackCommandNames.SKJOIN, addr, createException, ct).ConfigureAwait(false);

return response;
}
Expand All @@ -51,7 +78,12 @@ IPAddress Address
)> SendSKREJOINAsync(
CancellationToken cancellationToken = default
)
=> SKJOIN_SKREJOIN(SkStackCommandNames.SKREJOIN, ipv6address: null, cancellationToken);
=> SKJOIN_SKREJOIN(
SkStackCommandNames.SKREJOIN,
ipv6address: null,
createPanaSessionEstablishmentException: null,
cancellationToken
);

private async ValueTask<(
SkStackResponse Response,
Expand All @@ -60,10 +92,11 @@ IPAddress Address
SKJOIN_SKREJOIN(
ReadOnlyMemory<byte> command,
IPAddress? ipv6address,
Func<SkStackEventNumber, IPAddress, Exception>? createPanaSessionEstablishmentException,
CancellationToken cancellationToken
)
{
var eventHandler = new SKJOINEventHandler();
var eventHandler = new SKJOINEventHandler(createPanaSessionEstablishmentException);
var resp = await SendCommandAsync(
command: command,
writeArguments: writer => {
Expand All @@ -85,16 +118,20 @@ CancellationToken cancellationToken
return (resp, eventHandler.Address!);
}

private class SKJOINEventHandler : SkStackEventHandlerBase {
private sealed class SKJOINEventHandler(Func<SkStackEventNumber, IPAddress, Exception>? createPanaSessionEstablishmentException) : SkStackEventHandlerBase {
public bool HasAddressSet { get; private set; }
public IPAddress? Address { get; private set; }

private readonly Func<SkStackEventNumber, IPAddress, Exception>? createPanaSessionEstablishmentException = createPanaSessionEstablishmentException;
private SkStackEventNumber eventNumber;

private static SkStackPanaSessionEstablishmentException CreatePanaSessionEstablishmentException(SkStackEventNumber eventNumber, IPAddress address)
=> new(null, address, eventNumber);

public void ThrowIfEstablishmentError()
{
if (eventNumber != SkStackEventNumber.PanaSessionEstablishmentCompleted)
throw new SkStackPanaSessionEstablishmentException($"PANA session establishment failed. (0x{eventNumber:X})", Address!, eventNumber);
throw createPanaSessionEstablishmentException?.Invoke(eventNumber, Address!) ?? CreatePanaSessionEstablishmentException(eventNumber, Address!);
}

public override bool TryProcessEvent(SkStackEvent ev)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ private static int ValidatePanIdAndThrowIfInvalid(int panId, string paramName)
/// <seealso cref="SkStackRegister.PanId"/>
/// <seealso cref="PanaSessionPeerAddress"/>
/// <seealso cref="IsPanaSessionAlive"/>
/// <seealso cref="SendSKJOINAsync"/>
/// <seealso cref="SendSKJOINAsync(IPAddress, Func{SkStackEventNumber, IPAddress, Exception}?, CancellationToken)"/>
/// <seealso cref="SendSKSETRBIDAsync(ReadOnlyMemory{byte}, CancellationToken)"/>
/// <seealso cref="SendSKSETPWDAsync(ReadOnlyMemory{byte}, CancellationToken)"/>
private async ValueTask<SkStackPanaSessionInfo> AuthenticateAsPanaClientAsyncCore(
Expand Down Expand Up @@ -344,6 +344,15 @@ await SendSKSREGAsync(
// Then attempt to establish the PANA session.
await SendSKJOINAsync(
ipv6address: paaAddressNotNull,
createPanaSessionEstablishmentException: (eventNumber, address) =>
new SkStackPanaSessionEstablishmentException(
message: null,
paaAddress: paaAddressNotNull,
channel: channelNotNull,
panId: panIdNotNull,
address: address,
eventNumber: eventNumber
),
cancellationToken: cancellationToken
).ConfigureAwait(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,69 @@ namespace Smdn.Net.SkStackIP;
/// <summary>
/// The exception that represents an error on the establishment of a PANA session.
/// </summary>
/// <seealso cref="SkStackClient.SendSKJOINAsync"/>
/// <seealso cref="SkStackClient.SendSKJOINAsync(IPAddress, System.Threading.CancellationToken)"/>
public class SkStackPanaSessionEstablishmentException : SkStackPanaSessionException {
/// <summary>Gets the <see cref="IPAddress"/> of the PANA Authentication Agent(PAA) that attempted PANA authentication.</summary>
public IPAddress? PaaAddress { get; }

/// <summary>Gets the channel number used when attempting to establish a PANA session.</summary>
/// <value>If this exception occurs as a result of the <see cref="SkStackClient.AuthenticateAsPanaClientAsync(ReadOnlyMemory{byte}, ReadOnlyMemory{byte}, IPAddress, SkStackChannel, int, System.Threading.CancellationToken)"/> method, the non-<see langword="null"/> value will be set to this property. Otherwise, it will be <see langword="null"/>.</value>
public SkStackChannel? Channel { get; }

/// <summary>Gets the PAN ID used when attempting to establish a PANA session.</summary>
/// <value>If this exception occurs as a result of the <see cref="SkStackClient.AuthenticateAsPanaClientAsync(ReadOnlyMemory{byte}, ReadOnlyMemory{byte}, IPAddress, SkStackChannel, int, System.Threading.CancellationToken)"/> method, the non-<see langword="null"/> value will be set to this property. Otherwise, it will be <see langword="null"/>.</value>
public int? PanId { get; }

internal SkStackPanaSessionEstablishmentException(
string? message,
IPAddress address,
SkStackEventNumber eventNumber,
Exception? innerException = null
)
: base(
message: message ?? $"PANA session establishment failed. (0x{eventNumber:X})",
address: address,
eventNumber: eventNumber,
innerException: innerException
)
{
}

internal SkStackPanaSessionEstablishmentException(
string? message,
IPAddress paaAddress,
IPAddress address,
SkStackEventNumber eventNumber,
Exception? innerException = null
)
: base(
message: message ?? $"PANA session establishment failed. (0x{eventNumber:X}, PAA={paaAddress})",
address: address,
eventNumber: eventNumber,
innerException: innerException
)
{
PaaAddress = paaAddress;
}

internal SkStackPanaSessionEstablishmentException(
string message,
string? message,
IPAddress paaAddress,
SkStackChannel channel,
int panId,
IPAddress address,
SkStackEventNumber eventNumber,
Exception? innerException = null
)
: base(
message: message,
message: message ?? $"PANA session establishment failed. (0x{eventNumber:X}, PAA={paaAddress}, Channel={channel}, PanID=0x{panId:X4})",
address: address,
eventNumber: eventNumber,
innerException: innerException
)
{
PaaAddress = paaAddress;
Channel = channel;
PanId = panId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ async Task RaisePanaSessionEstablishmentEventsAsync()

Assert.That(ex!.EventNumber, Is.EqualTo(SkStackEventNumber.PanaSessionEstablishmentError));
Assert.That(ex.Address, Is.EqualTo(IPAddress.Parse(SelfIPv6Address)));
Assert.That(ex.PaaAddress, Is.EqualTo(IPAddress.Parse(PaaIPv6Address)));
Assert.That(ex.Channel, Is.Null);
Assert.That(ex.PanId, Is.Null);

Assert.That(raisedEventCount, Is.EqualTo(0), nameof(raisedEventCount));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ async Task RaisePanaSessionEstablishmentEventsAsync()

Assert.That(ex!.EventNumber, Is.EqualTo(SkStackEventNumber.PanaSessionEstablishmentError));
Assert.That(ex.Address, Is.EqualTo(IPAddress.Parse(SelfIPv6Address)));
Assert.That(ex.PaaAddress, Is.Null);
Assert.That(ex.Channel, Is.Null);
Assert.That(ex.PanId, Is.Null);

Assert.That(raisedEventCount, Is.EqualTo(0), nameof(raisedEventCount));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,13 @@ ILogger logger
cancellationToken: cts.Token
),
exceptPanaSessionEstablishmentException
? Throws.TypeOf<SkStackPanaSessionEstablishmentException>()
? Throws
.TypeOf<SkStackPanaSessionEstablishmentException>()
.And.Property(nameof(SkStackPanaSessionEstablishmentException.PaaAddress)).EqualTo(IPAddress.Parse(paaIPv6Address))
.And.Property(nameof(SkStackPanaSessionEstablishmentException.Channel)).EqualTo(SkStackChannel.Channels[paaChannel])
.And.Property(nameof(SkStackPanaSessionEstablishmentException.PanId)).EqualTo(paaPanId)
.And.Property(nameof(SkStackPanaSessionEstablishmentException.EventNumber)).EqualTo(eventNumberOfPanaSessionEstablishment)
.And.Property(nameof(SkStackPanaSessionEstablishmentException.Address)).EqualTo(IPAddress.Parse(selfIPv6Address))
: Throws.Nothing
);

Expand Down

0 comments on commit 7fc24f9

Please sign in to comment.