Skip to content

Commit

Permalink
X_AVM-DE_GetConfigFile
Browse files Browse the repository at this point in the history
  • Loading branch information
Rans4ckeR committed May 19, 2024
1 parent 86fd1ad commit 558dc73
Show file tree
Hide file tree
Showing 18 changed files with 124 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ static async Task StopCaptureAsync(InternetGatewayDevice device, CaptureInterfac
* ❌ FactoryReset
* ❌ Reboot
* ✅ X_GenerateUUID
* X_AVM-DE_GetConfigFile
* X_AVM-DE_GetConfigFile
* ❌ X_AVM-DE_SetConfigFile
* ✅ X_AVM-DE_CreateUrlSID
* ✅ X_AVM-DE_GetSupportDataInfo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ public static Task<DeviceConfigCreateUrlSidResponse> DeviceConfigCreateUrlSidAsy
public static Task<DeviceConfigGetSupportDataInfoResponse> DeviceConfigGetSupportDataInfoAsync(this InternetGatewayDevice internetGatewayDevice)
=> internetGatewayDevice.ExecuteAsync((h, d) => h.DeviceConfigGetSupportDataInfoAsync(d));

public static Task<DeviceConfigGetConfigFileResponse> DeviceConfigGetConfigFileAsync(this InternetGatewayDevice internetGatewayDevice, DeviceConfigGetConfigFileRequest deviceConfigGetConfigFileRequest)
=> internetGatewayDevice.ExecuteAsync((h, d) => h.DeviceConfigGetConfigFileAsync(d, deviceConfigGetConfigFileRequest));

private static Func<IFritzServiceOperationHandler, InternetGatewayDevice, Task<T>> GetWlanOperation<T>(
int interfaceNumber,
Func<IFritzServiceOperationHandler, InternetGatewayDevice, Task<T>> interface1Operation,
Expand Down
28 changes: 13 additions & 15 deletions RS.Fritz.Manager.API/Infrastructure/ExceptionMessageBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace RS.Fritz.Manager.API;

using System.Text;
using System.Xml.Linq;

public static class ExceptionMessageBuilder
{
Expand Down Expand Up @@ -41,22 +42,16 @@ private static void GetExceptionDetails(this StringBuilder sb, Exception ex)
.AppendLine(FormattableString.Invariant($"{nameof(FaultException)}.{nameof(FaultException.Reason)}: {faultException.Reason}"))
.GetFaultCode(faultException.Code);

#pragma warning disable IDE0045 // Convert to conditional expression
if (ex is FaultException<UPnPFault> upnpFaultFaultException)
_ = ex switch
{
_ = sb.AppendLine(FormattableString.Invariant($"{nameof(UPnPFault)}.{nameof(UPnPFault.ErrorCode)}: {upnpFaultFaultException.Detail.ErrorCode}"))
.AppendLine(FormattableString.Invariant($"{nameof(UPnPFault)}.{nameof(UPnPFault.ErrorDescription)}: {upnpFaultFaultException.Detail.ErrorDescription}"));
}
else if (ex is FaultException<AvmUPnPFault> avmUpnpFaultFaultException)
{
_ = sb.AppendLine(FormattableString.Invariant($"{nameof(AvmUPnPFault)}.{nameof(AvmUPnPFault.ErrorCode)}: {avmUpnpFaultFaultException.Detail.ErrorCode}"))
.AppendLine(FormattableString.Invariant($"{nameof(AvmUPnPFault)}.{nameof(AvmUPnPFault.ErrorDescription)}: {avmUpnpFaultFaultException.Detail.ErrorDescription}"));
}
else
{
throw new NotSupportedException(FormattableString.Invariant($"Encountered unexpected {nameof(FaultException)}."));
}
#pragma warning restore IDE0045 // Convert to conditional expression
FaultException<UPnPFault> upnpFaultFaultException => sb
.AppendLine(FormattableString.Invariant($"{nameof(UPnPFault)}.{nameof(UPnPFault.ErrorCode)}: {upnpFaultFaultException.Detail.ErrorCode}"))
.AppendLine(FormattableString.Invariant($"{nameof(UPnPFault)}.{nameof(UPnPFault.ErrorDescription)}: {upnpFaultFaultException.Detail.ErrorDescription}")),
FaultException<AvmUPnPFault> avmUpnpFaultFaultException => sb
.AppendLine(FormattableString.Invariant($"{nameof(AvmUPnPFault)}.{nameof(AvmUPnPFault.ErrorCode)}: {avmUpnpFaultFaultException.Detail.ErrorCode}"))
.AppendLine(FormattableString.Invariant($"{nameof(AvmUPnPFault)}.{nameof(AvmUPnPFault.ErrorDescription)}: {avmUpnpFaultFaultException.Detail.ErrorDescription}")),
_ => sb.AppendLine(GetFaultReasonContent(faultException))
};
}

_ = sb.AppendLine(FormattableString.Invariant($"{nameof(Exception)}.{nameof(Exception.StackTrace)}: {ex.StackTrace}"));
Expand All @@ -76,4 +71,7 @@ private static void GetFaultCode(this StringBuilder sb, FaultCode faultCode)
.GetFaultCode(faultCode.SubCode);
}
}

private static string GetFaultReasonContent(FaultException ex)
=> FormattableString.Invariant($"{nameof(FaultException)}.{nameof(FaultException.Reason)}.Content: {XElement.Parse(ex.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml())}");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace RS.Fritz.Manager.API;

[MessageContract(WrapperName = "GetConfigFile")]
public readonly record struct DeviceConfigGetConfigFileRequest(
[property: MessageBodyMember(Name = "NewX_AVM-DE_Password")] string Password);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace RS.Fritz.Manager.API;

[MessageContract(WrapperName = "GetConfigFileResponse")]
public readonly record struct DeviceConfigGetConfigFileResponse(
[property: MessageBodyMember(Name = "NewX_AVM-DE_ConfigFileUrl")] string ConfigFileUrl);
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ public Task<DeviceConfigCreateUrlSidResponse> CreateUrlSidAsync(DeviceConfigCrea

public Task<DeviceConfigGetSupportDataInfoResponse> GetSupportDataInfoAsync(DeviceConfigGetSupportDataInfoRequest deviceConfigGetSupportDataInfoRequest)
=> Channel.GetSupportDataInfoAsync(deviceConfigGetSupportDataInfoRequest);

public Task<DeviceConfigGetConfigFileResponse> GetConfigFileAsync(DeviceConfigGetConfigFileRequest deviceConfigGetConfigFileRequest)
=> Channel.GetConfigFileAsync(deviceConfigGetConfigFileRequest);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ internal interface IFritzDeviceConfigService : IAsyncDisposable
[FaultContract(typeof(UPnPFault))]
[FaultContract(typeof(AvmUPnPFault))]
Task<DeviceConfigGetSupportDataInfoResponse> GetSupportDataInfoAsync(DeviceConfigGetSupportDataInfoRequest deviceConfigGetSupportDataInfoRequest);

[OperationContract(Action = $"{UPnPConstants.AvmServiceNamespace}:DeviceConfig:1#X_AVM-DE_GetConfigFile")]
[FaultContract(typeof(UPnPFault))]
[FaultContract(typeof(AvmUPnPFault))]
Task<DeviceConfigGetConfigFileResponse> GetConfigFileAsync(DeviceConfigGetConfigFileRequest deviceConfigGetConfigFileRequest);
}
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,9 @@ public Task<DeviceConfigCreateUrlSidResponse> DeviceConfigCreateUrlSidAsync(Inte
public Task<DeviceConfigGetSupportDataInfoResponse> DeviceConfigGetSupportDataInfoAsync(InternetGatewayDevice internetGatewayDevice)
=> ExecuteAsync(GetFritzServiceClient(internetGatewayDevice, fritzDeviceConfigServiceClientFactory, (q, r, t) => new FritzDeviceConfigService(q, r, t!), FritzDeviceConfigService.ControlUrl), q => q.GetSupportDataInfoAsync(default));

public Task<DeviceConfigGetConfigFileResponse> DeviceConfigGetConfigFileAsync(InternetGatewayDevice internetGatewayDevice, DeviceConfigGetConfigFileRequest deviceConfigGetConfigFileRequest)
=> ExecuteAsync(GetFritzServiceClient(internetGatewayDevice, fritzDeviceConfigServiceClientFactory, (q, r, t) => new FritzDeviceConfigService(q, r, t!), FritzDeviceConfigService.ControlUrl), q => q.GetConfigFileAsync(deviceConfigGetConfigFileRequest));

private static T GetFritzServiceClient<T>(InternetGatewayDevice internetGatewayDevice, IClientFactory<T> clientFactory, Func<FritzServiceEndpointConfiguration, EndpointAddress, NetworkCredential?, T> createService, string controlUrl, bool secure = true)
=> clientFactory.Build(createService, internetGatewayDevice.PreferredLocation!, secure, controlUrl, secure ? internetGatewayDevice.SecurityPort : null, internetGatewayDevice.NetworkCredential);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,4 +321,6 @@ public interface IFritzServiceOperationHandler
Task<DeviceConfigCreateUrlSidResponse> DeviceConfigCreateUrlSidAsync(InternetGatewayDevice internetGatewayDevice);

Task<DeviceConfigGetSupportDataInfoResponse> DeviceConfigGetSupportDataInfoAsync(InternetGatewayDevice internetGatewayDevice);

Task<DeviceConfigGetConfigFileResponse> DeviceConfigGetConfigFileAsync(InternetGatewayDevice internetGatewayDevice, DeviceConfigGetConfigFileRequest deviceConfigGetConfigFileRequest);
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ internal static class ServiceCollectionExtensions
.AddSingleton<UserInterfaceSetConfigViewModel>()
.AddSingleton<DeviceConfigViewModel>()
.AddSingleton<DeviceConfigGenerateUuIdViewModel>()
.AddSingleton<DeviceConfigCreateUrlSidViewModel>();
.AddSingleton<DeviceConfigCreateUrlSidViewModel>()
.AddSingleton<DeviceConfigGetConfigFileViewModel>();
}
3 changes: 3 additions & 0 deletions RS.Fritz.Manager.UI/RS.Fritz.Manager.UI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
</Page>
<Page Update="UserControls\DeviceConfig\DeviceConfigGetConfigFileView.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
<Page Update="UserControls\Hosts\HostsHostsCheckUpdateView.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,17 @@
<TextBlock x:Name="SupportDataStatus" Grid.Row="3" Grid.Column="1" Text="{Binding SupportDataStatus}"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type api:DeviceConfigGetConfigFileResponse}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Target="{Binding ElementName=ConfigFileUrl}" Content="_ConfigFileUrl" ToolTip="Encrypted config file URL, valid for less than 30 seconds."/>
<ContentControl x:Name="ConfigFileUrl" Grid.Row="0" Grid.Column="1" ContentTemplate="{StaticResource UrlDataTemplate}" Content="{Binding ConfigFileUrl}"/>
</Grid>
</DataTemplate>
</ResourceDictionary>
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,7 @@
<DataTemplate DataType="{x:Type ui:DeviceConfigCreateUrlSidViewModel}">
<ui:DeviceConfigCreateUrlSidView/>
</DataTemplate>
<DataTemplate DataType="{x:Type ui:DeviceConfigGetConfigFileViewModel}">
<ui:DeviceConfigGetConfigFileView/>
</DataTemplate>
</ResourceDictionary>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<UserControl x:Class="RS.Fritz.Manager.UI.DeviceConfigGetConfigFileView"
x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ui="clr-namespace:RS.Fritz.Manager.UI"
d:DataContext="{d:DesignInstance Type=ui:DeviceConfigGetConfigFileViewModel}"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Border Style="{StaticResource BorderStyle}">
<Expander Header="{Binding Title}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Target="{Binding ElementName=Password}" Content="_Password" ToolTip="Password used to encrypt the file."/>
<TextBox x:Name="Password" Grid.Row="0" Grid.Column="1" MinWidth="50" Text="{Binding Password, UpdateSourceTrigger=PropertyChanged}"/>
<Button Grid.Row="1" Grid.Column="0" Content="{Binding ButtonText}" Command="{Binding DefaultCommand}" CommandParameter="{StaticResource False}"/>
<ContentControl Grid.Row="0" Grid.Column="2" Grid.RowSpan="2" Content="{Binding Response.Value}"/>
</Grid>
</Expander>
</Border>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace RS.Fritz.Manager.UI;

internal sealed partial class DeviceConfigGetConfigFileView
{
public DeviceConfigGetConfigFileView() => InitializeComponent();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace RS.Fritz.Manager.UI;

internal sealed class
DeviceConfigGetConfigFileViewModel(DeviceLoginInfo deviceLoginInfo, ILogger logger)
: ManualOperationViewModel<DeviceConfigGetConfigFileRequest, DeviceConfigGetConfigFileResponse>(deviceLoginInfo, logger, "GetConfigFile", "Get Config File URL", (d, r) => d.DeviceConfigGetConfigFileAsync(r))
{
private string? password;

public string? Password
{
get => password;
set
{
if (SetProperty(ref password, value))
UpdateAndNotifyCanExecuteDefaultCommand();
}
}

protected override DeviceConfigGetConfigFileRequest BuildRequest()
=> new(Password!);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
Expand Down Expand Up @@ -48,5 +49,6 @@
</Grid>
</Expander>
</Border>
<ContentControl Grid.Row="4" Grid.Column="0" Content="{Binding DeviceConfigGetConfigFileViewModel}"/>
</Grid>
</UserControl>
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ internal sealed class DeviceConfigViewModel(
DeviceLoginInfo deviceLoginInfo,
ILogger logger,
DeviceConfigGenerateUuIdViewModel deviceConfigGenerateUuIdViewModel,
DeviceConfigCreateUrlSidViewModel deviceConfigCreateUrlSidViewModel)
DeviceConfigCreateUrlSidViewModel deviceConfigCreateUrlSidViewModel,
DeviceConfigGetConfigFileViewModel deviceConfigGetConfigFileViewModel)
: FritzServiceViewModel(deviceLoginInfo, logger, "DeviceConfig")
{
private KeyValuePair<DeviceConfigGetPersistentDataResponse?, UPnPFault?>? deviceConfigGetPersistentDataResponse;
Expand All @@ -26,6 +27,8 @@ internal sealed class DeviceConfigViewModel(

public DeviceConfigCreateUrlSidViewModel DeviceConfigCreateUrlSidViewModel { get; } = deviceConfigCreateUrlSidViewModel;

public DeviceConfigGetConfigFileViewModel DeviceConfigGetConfigFileViewModel { get; } = deviceConfigGetConfigFileViewModel;

protected override ValueTask DoExecuteDefaultCommandAsync(CancellationToken cancellationToken)
=> API.TaskExtensions.WhenAllSafe([GetDeviceConfigGetPersistentDataAsync(), GetDeviceConfigGetSupportDataInfoResponseAsync()], true);

Expand Down

0 comments on commit 558dc73

Please sign in to comment.