diff --git a/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.SKJOIN_SKREJOIN.cs b/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.SKJOIN_SKREJOIN.cs
index b9fea30..4c843e4 100644
--- a/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.SKJOIN_SKREJOIN.cs
+++ b/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.SKJOIN_SKREJOIN.cs
@@ -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
+ );
+
///
/// Sends a command SKJOIN.
///
@@ -22,6 +34,17 @@ partial class SkStackClient {
public ValueTask SendSKJOINAsync(
IPAddress ipv6address,
CancellationToken cancellationToken = default
+ )
+ => SendSKJOINAsync(
+ ipv6address: ipv6address,
+ createPanaSessionEstablishmentException: (eventNumber, address) => CreatePanaSessionEstablishmentException(ipv6address, eventNumber, address),
+ cancellationToken: cancellationToken
+ );
+
+ internal ValueTask SendSKJOINAsync(
+ IPAddress ipv6address,
+ Func? createPanaSessionEstablishmentException,
+ CancellationToken cancellationToken
)
{
if (ipv6address is null)
@@ -29,11 +52,15 @@ public ValueTask SendSKJOINAsync(
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 SKJOIN(IPAddress addr, CancellationToken ct)
+ async ValueTask SKJOIN(
+ IPAddress addr,
+ Func? 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;
}
@@ -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,
@@ -60,10 +92,11 @@ IPAddress Address
SKJOIN_SKREJOIN(
ReadOnlyMemory command,
IPAddress? ipv6address,
+ Func? createPanaSessionEstablishmentException,
CancellationToken cancellationToken
)
{
- var eventHandler = new SKJOINEventHandler();
+ var eventHandler = new SKJOINEventHandler(createPanaSessionEstablishmentException);
var resp = await SendCommandAsync(
command: command,
writeArguments: writer => {
@@ -85,16 +118,20 @@ CancellationToken cancellationToken
return (resp, eventHandler.Address!);
}
- private class SKJOINEventHandler : SkStackEventHandlerBase {
+ private sealed class SKJOINEventHandler(Func? createPanaSessionEstablishmentException) : SkStackEventHandlerBase {
public bool HasAddressSet { get; private set; }
public IPAddress? Address { get; private set; }
+ private readonly Func? 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)
diff --git a/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Functions.PANA.AuthenticateAsPaC.cs b/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Functions.PANA.AuthenticateAsPaC.cs
index 523cc2f..9499355 100644
--- a/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Functions.PANA.AuthenticateAsPaC.cs
+++ b/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Functions.PANA.AuthenticateAsPaC.cs
@@ -201,7 +201,7 @@ private static int ValidatePanIdAndThrowIfInvalid(int panId, string paramName)
///
///
///
- ///
+ ///
///
///
private async ValueTask AuthenticateAsPanaClientAsyncCore(
@@ -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);
diff --git a/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackPanaSessionEstablishmentException.cs b/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackPanaSessionEstablishmentException.cs
index 30a95f0..efd5bba 100644
--- a/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackPanaSessionEstablishmentException.cs
+++ b/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackPanaSessionEstablishmentException.cs
@@ -10,20 +10,69 @@ namespace Smdn.Net.SkStackIP;
///
/// The exception that represents an error on the establishment of a PANA session.
///
-///
+///
public class SkStackPanaSessionEstablishmentException : SkStackPanaSessionException {
+ /// Gets the of the PANA Authentication Agent(PAA) that attempted PANA authentication.
+ public IPAddress? PaaAddress { get; }
+
+ /// Gets the channel number used when attempting to establish a PANA session.
+ /// If this exception occurs as a result of the method, the non- value will be set to this property. Otherwise, it will be .
+ public SkStackChannel? Channel { get; }
+
+ /// Gets the PAN ID used when attempting to establish a PANA session.
+ /// If this exception occurs as a result of the method, the non- value will be set to this property. Otherwise, it will be .
+ 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;
}
}
diff --git a/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.3.4.SKJOIN.cs b/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.3.4.SKJOIN.cs
index e446ef8..9459fed 100644
--- a/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.3.4.SKJOIN.cs
+++ b/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.3.4.SKJOIN.cs
@@ -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));
diff --git a/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.3.5.SKREJOIN.cs b/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.3.5.SKREJOIN.cs
index efa445e..9886fac 100644
--- a/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.3.5.SKREJOIN.cs
+++ b/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Commands.3.5.SKREJOIN.cs
@@ -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));
diff --git a/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Functions.PANA.AuthenticateAsPaC.cs b/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Functions.PANA.AuthenticateAsPaC.cs
index a6e0251..551ee68 100644
--- a/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Functions.PANA.AuthenticateAsPaC.cs
+++ b/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackClient.Functions.PANA.AuthenticateAsPaC.cs
@@ -96,7 +96,13 @@ ILogger logger
cancellationToken: cts.Token
),
exceptPanaSessionEstablishmentException
- ? Throws.TypeOf()
+ ? Throws
+ .TypeOf()
+ .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
);