/Source/NETworkManager/ViewModels/NetworkInterfaceViewModel.cs

https://github.com/BornToBeRoot/NETworkManager · C# · 1153 lines · 899 code · 231 blank · 23 comment · 133 complexity · 2a52eccf3bd88572f2abba4863d6dac9 MD5 · raw file

  1. using System.Collections.Generic;
  2. using System.Windows.Input;
  3. using System.Net.NetworkInformation;
  4. using System;
  5. using System.Linq;
  6. using MahApps.Metro.Controls.Dialogs;
  7. using NETworkManager.Settings;
  8. using NETworkManager.Models.Network;
  9. using System.Threading.Tasks;
  10. using System.Windows.Data;
  11. using System.ComponentModel;
  12. using System.Diagnostics;
  13. using NETworkManager.Views;
  14. using NETworkManager.Utilities;
  15. using System.Windows;
  16. using LiveCharts;
  17. using LiveCharts.Configurations;
  18. using LiveCharts.Wpf;
  19. using MahApps.Metro.Controls;
  20. using NETworkManager.Profiles;
  21. using System.Windows.Threading;
  22. namespace NETworkManager.ViewModels
  23. {
  24. public class NetworkInterfaceViewModel : ViewModelBase, IProfileManager
  25. {
  26. #region Variables
  27. private readonly IDialogCoordinator _dialogCoordinator;
  28. private readonly DispatcherTimer _searchDispatcherTimer = new DispatcherTimer();
  29. private BandwidthMeter _bandwidthMeter;
  30. private readonly bool _isLoading;
  31. private bool _isNetworkInteraceLoading;
  32. public bool IsNetworkInterfaceLoading
  33. {
  34. get => _isNetworkInteraceLoading;
  35. set
  36. {
  37. if (value == _isNetworkInteraceLoading)
  38. return;
  39. _isNetworkInteraceLoading = value;
  40. OnPropertyChanged();
  41. }
  42. }
  43. private bool _canConfigure;
  44. public bool CanConfigure
  45. {
  46. get => _canConfigure;
  47. set
  48. {
  49. if (value == _canConfigure)
  50. return;
  51. _canConfigure = value;
  52. OnPropertyChanged();
  53. }
  54. }
  55. private bool _isConfigurationRunning;
  56. public bool IsConfigurationRunning
  57. {
  58. get => _isConfigurationRunning;
  59. set
  60. {
  61. if (value == _isConfigurationRunning)
  62. return;
  63. _isConfigurationRunning = value;
  64. OnPropertyChanged();
  65. }
  66. }
  67. private bool _displayStatusMessage;
  68. public bool DisplayStatusMessage
  69. {
  70. get => _displayStatusMessage;
  71. set
  72. {
  73. if (value == _displayStatusMessage)
  74. return;
  75. _displayStatusMessage = value;
  76. OnPropertyChanged();
  77. }
  78. }
  79. private string _statusMessage;
  80. public string StatusMessage
  81. {
  82. get => _statusMessage;
  83. set
  84. {
  85. if (value == _statusMessage)
  86. return;
  87. _statusMessage = value;
  88. OnPropertyChanged();
  89. }
  90. }
  91. #region NetworkInterfaces, SelectedNetworkInterface
  92. private List<NetworkInterfaceInfo> _networkInterfaces;
  93. public List<NetworkInterfaceInfo> NetworkInterfaces
  94. {
  95. get => _networkInterfaces;
  96. set
  97. {
  98. if (value == _networkInterfaces)
  99. return;
  100. _networkInterfaces = value;
  101. OnPropertyChanged();
  102. }
  103. }
  104. private NetworkInterfaceInfo _selectedNetworkInterface;
  105. public NetworkInterfaceInfo SelectedNetworkInterface
  106. {
  107. get => _selectedNetworkInterface;
  108. set
  109. {
  110. if (value == _selectedNetworkInterface)
  111. return;
  112. if (value != null)
  113. {
  114. if (!_isLoading)
  115. SettingsManager.Current.NetworkInterface_InterfaceId = value.Id;
  116. // Bandwidth
  117. StopBandwidthMeter();
  118. StartBandwidthMeter(value.Id);
  119. // Configuration
  120. SetConfigurationDefaults(value);
  121. CanConfigure = value.IsOperational;
  122. }
  123. _selectedNetworkInterface = value;
  124. OnPropertyChanged();
  125. }
  126. }
  127. #endregion
  128. #region Bandwidth
  129. private long _bandwidthTotalBytesSentTemp;
  130. private long _bandwidthTotalBytesSent;
  131. public long BandwidthTotalBytesSent
  132. {
  133. get => _bandwidthTotalBytesSent;
  134. set
  135. {
  136. if (value == _bandwidthTotalBytesSent)
  137. return;
  138. _bandwidthTotalBytesSent = value;
  139. OnPropertyChanged();
  140. }
  141. }
  142. private long _bandwidthTotalBytesReceivedTemp;
  143. private long _bandwidthTotalBytesReceived;
  144. public long BandwidthTotalBytesReceived
  145. {
  146. get => _bandwidthTotalBytesReceived;
  147. set
  148. {
  149. if (value == _bandwidthTotalBytesReceived)
  150. return;
  151. _bandwidthTotalBytesReceived = value;
  152. OnPropertyChanged();
  153. }
  154. }
  155. private long _bandwidthDiffBytesSent;
  156. public long BandwidthDiffBytesSent
  157. {
  158. get => _bandwidthDiffBytesSent;
  159. set
  160. {
  161. if (value == _bandwidthDiffBytesSent)
  162. return;
  163. _bandwidthDiffBytesSent = value;
  164. OnPropertyChanged();
  165. }
  166. }
  167. private long _bandwidthDiffBytesReceived;
  168. public long BandwidthDiffBytesReceived
  169. {
  170. get => _bandwidthDiffBytesReceived;
  171. set
  172. {
  173. if (value == _bandwidthDiffBytesReceived)
  174. return;
  175. _bandwidthDiffBytesReceived = value;
  176. OnPropertyChanged();
  177. }
  178. }
  179. private long _bandwithBytesReceivedSpeed;
  180. public long BandwidthBytesReceivedSpeed
  181. {
  182. get => _bandwithBytesReceivedSpeed;
  183. set
  184. {
  185. if (value == _bandwithBytesReceivedSpeed)
  186. return;
  187. _bandwithBytesReceivedSpeed = value;
  188. OnPropertyChanged();
  189. }
  190. }
  191. private long _bandwidthBytesSentSpeed;
  192. public long BandwidthBytesSentSpeed
  193. {
  194. get => _bandwidthBytesSentSpeed;
  195. set
  196. {
  197. if (value == _bandwidthBytesSentSpeed)
  198. return;
  199. _bandwidthBytesSentSpeed = value;
  200. OnPropertyChanged();
  201. }
  202. }
  203. private DateTime _bandwidthStartTime;
  204. public DateTime BandwidthStartTime
  205. {
  206. get => _bandwidthStartTime;
  207. set
  208. {
  209. if (value == _bandwidthStartTime)
  210. return;
  211. _bandwidthStartTime = value;
  212. OnPropertyChanged();
  213. }
  214. }
  215. private TimeSpan _bandwidthMeasuredTime;
  216. public TimeSpan BandwidthMeasuredTime
  217. {
  218. get => _bandwidthMeasuredTime;
  219. set
  220. {
  221. if (value == _bandwidthMeasuredTime)
  222. return;
  223. _bandwidthMeasuredTime = value;
  224. OnPropertyChanged();
  225. }
  226. }
  227. #endregion
  228. #region Config
  229. private bool _configEnableDynamicIPAddress = true;
  230. public bool ConfigEnableDynamicIPAddress
  231. {
  232. get => _configEnableDynamicIPAddress;
  233. set
  234. {
  235. if (value == _configEnableDynamicIPAddress)
  236. return;
  237. _configEnableDynamicIPAddress = value;
  238. OnPropertyChanged();
  239. }
  240. }
  241. private bool _configEnableStaticIPAddress;
  242. public bool ConfigEnableStaticIPAddress
  243. {
  244. get => _configEnableStaticIPAddress;
  245. set
  246. {
  247. if (value == _configEnableStaticIPAddress)
  248. return;
  249. ConfigEnableStaticDNS = true;
  250. _configEnableStaticIPAddress = value;
  251. OnPropertyChanged();
  252. }
  253. }
  254. private string _configIPAddress;
  255. public string ConfigIPAddress
  256. {
  257. get => _configIPAddress;
  258. set
  259. {
  260. if (value == _configIPAddress)
  261. return;
  262. _configIPAddress = value;
  263. OnPropertyChanged();
  264. }
  265. }
  266. private string _configSubnetmaskOrCidr;
  267. public string ConfigSubnetmaskOrCidr
  268. {
  269. get => _configSubnetmaskOrCidr;
  270. set
  271. {
  272. if (value == _configSubnetmaskOrCidr)
  273. return;
  274. _configSubnetmaskOrCidr = value;
  275. OnPropertyChanged();
  276. }
  277. }
  278. private string _configGateway;
  279. public string ConfigGateway
  280. {
  281. get => _configGateway;
  282. set
  283. {
  284. if (value == _configGateway)
  285. return;
  286. _configGateway = value;
  287. OnPropertyChanged();
  288. }
  289. }
  290. private bool _configEnableDynamicDNS = true;
  291. public bool ConfigEnableDynamicDNS
  292. {
  293. get => _configEnableDynamicDNS;
  294. set
  295. {
  296. if (value == _configEnableDynamicDNS)
  297. return;
  298. _configEnableDynamicDNS = value;
  299. OnPropertyChanged();
  300. }
  301. }
  302. private bool _configEnableStaticDNS;
  303. public bool ConfigEnableStaticDNS
  304. {
  305. get => _configEnableStaticDNS;
  306. set
  307. {
  308. if (value == _configEnableStaticDNS)
  309. return;
  310. _configEnableStaticDNS = value;
  311. OnPropertyChanged();
  312. }
  313. }
  314. private string _configPrimaryDNSServer;
  315. public string ConfigPrimaryDNSServer
  316. {
  317. get => _configPrimaryDNSServer;
  318. set
  319. {
  320. if (value == _configPrimaryDNSServer)
  321. return;
  322. _configPrimaryDNSServer = value;
  323. OnPropertyChanged();
  324. }
  325. }
  326. private string _configSecondaryDNSServer;
  327. public string ConfigSecondaryDNSServer
  328. {
  329. get => _configSecondaryDNSServer;
  330. set
  331. {
  332. if (value == _configSecondaryDNSServer)
  333. return;
  334. _configSecondaryDNSServer = value;
  335. OnPropertyChanged();
  336. }
  337. }
  338. #endregion
  339. #region Profiles
  340. public ICollectionView Profiles { get; }
  341. private ProfileInfo _selectedProfile = new ProfileInfo();
  342. public ProfileInfo SelectedProfile
  343. {
  344. get => _selectedProfile;
  345. set
  346. {
  347. if (value == _selectedProfile)
  348. return;
  349. if (value != null)
  350. {
  351. ConfigEnableDynamicIPAddress = !value.NetworkInterface_EnableStaticIPAddress;
  352. ConfigEnableStaticIPAddress = value.NetworkInterface_EnableStaticIPAddress;
  353. ConfigIPAddress = value.NetworkInterface_IPAddress;
  354. ConfigGateway = value.NetworkInterface_Gateway;
  355. ConfigSubnetmaskOrCidr = value.NetworkInterface_SubnetmaskOrCidr;
  356. ConfigEnableDynamicDNS = !value.NetworkInterface_EnableStaticDNS;
  357. ConfigEnableStaticDNS = value.NetworkInterface_EnableStaticDNS;
  358. ConfigPrimaryDNSServer = value.NetworkInterface_PrimaryDNSServer;
  359. ConfigSecondaryDNSServer = value.NetworkInterface_SecondaryDNSServer;
  360. }
  361. _selectedProfile = value;
  362. OnPropertyChanged();
  363. }
  364. }
  365. private string _search;
  366. public string Search
  367. {
  368. get => _search;
  369. set
  370. {
  371. if (value == _search)
  372. return;
  373. _search = value;
  374. StartDelayedSearch();
  375. OnPropertyChanged();
  376. }
  377. }
  378. private bool _isSearching;
  379. public bool IsSearching
  380. {
  381. get => _isSearching;
  382. set
  383. {
  384. if (value == _isSearching)
  385. return;
  386. _isSearching = value;
  387. OnPropertyChanged();
  388. }
  389. }
  390. private bool _canProfileWidthChange = true;
  391. private double _tempProfileWidth;
  392. private bool _expandProfileView;
  393. public bool ExpandProfileView
  394. {
  395. get => _expandProfileView;
  396. set
  397. {
  398. if (value == _expandProfileView)
  399. return;
  400. if (!_isLoading)
  401. SettingsManager.Current.NetworkInterface_ExpandProfileView = value;
  402. _expandProfileView = value;
  403. if (_canProfileWidthChange)
  404. ResizeProfile(false);
  405. OnPropertyChanged();
  406. }
  407. }
  408. private GridLength _profileWidth;
  409. public GridLength ProfileWidth
  410. {
  411. get => _profileWidth;
  412. set
  413. {
  414. if (value == _profileWidth)
  415. return;
  416. if (!_isLoading && Math.Abs(value.Value - GlobalStaticConfiguration.Profile_WidthCollapsed) > GlobalStaticConfiguration.FloatPointFix) // Do not save the size when collapsed
  417. SettingsManager.Current.NetworkInterface_ProfileWidth = value.Value;
  418. _profileWidth = value;
  419. if (_canProfileWidthChange)
  420. ResizeProfile(dueToChangedSize: true);
  421. OnPropertyChanged();
  422. }
  423. }
  424. #endregion
  425. #endregion
  426. #region Constructor, LoadSettings, OnShutdown
  427. public NetworkInterfaceViewModel(IDialogCoordinator instance)
  428. {
  429. _isLoading = true;
  430. _dialogCoordinator = instance;
  431. LoadNetworkInterfaces();
  432. InitialBandwidthChart();
  433. Profiles = new CollectionViewSource { Source = ProfileManager.Profiles }.View;
  434. Profiles.GroupDescriptions.Add(new PropertyGroupDescription(nameof(ProfileInfo.Group)));
  435. Profiles.SortDescriptions.Add(new SortDescription(nameof(ProfileInfo.Group), ListSortDirection.Ascending));
  436. Profiles.SortDescriptions.Add(new SortDescription(nameof(ProfileInfo.Name), ListSortDirection.Ascending));
  437. Profiles.Filter = o =>
  438. {
  439. if (!(o is ProfileInfo info))
  440. return false;
  441. if (string.IsNullOrEmpty(Search))
  442. return info.NetworkInterface_Enabled;
  443. var search = Search.Trim();
  444. // Search by: Tag=xxx (exact match, ignore case)
  445. if (search.StartsWith(ProfileManager.TagIdentifier, StringComparison.OrdinalIgnoreCase))
  446. return !string.IsNullOrEmpty(info.Tags) && info.NetworkInterface_Enabled && info.Tags.Replace(" ", "").Split(';').Any(str => search.Substring(ProfileManager.TagIdentifier.Length, search.Length - ProfileManager.TagIdentifier.Length).Equals(str, StringComparison.OrdinalIgnoreCase));
  447. // Search by: Name, IPScanner_IPRange
  448. return info.NetworkInterface_Enabled && (info.Name.IndexOf(search, StringComparison.OrdinalIgnoreCase) > -1);
  449. };
  450. // This will select the first entry as selected item...
  451. SelectedProfile = Profiles.SourceCollection.Cast<ProfileInfo>().Where(x => x.NetworkInterface_Enabled).OrderBy(x => x.Group).ThenBy(x => x.Name).FirstOrDefault();
  452. _searchDispatcherTimer.Interval = GlobalStaticConfiguration.SearchDispatcherTimerTimeSpan;
  453. _searchDispatcherTimer.Tick += SearchDispatcherTimer_Tick;
  454. // Detect if network address or status changed...
  455. NetworkChange.NetworkAvailabilityChanged += (sender, args) => ReloadNetworkInterfacesAction();
  456. NetworkChange.NetworkAddressChanged += (sender, args) => ReloadNetworkInterfacesAction();
  457. LoadSettings();
  458. SettingsManager.Current.PropertyChanged += SettingsManager_PropertyChanged;
  459. _isLoading = false;
  460. }
  461. private void InitialBandwidthChart()
  462. {
  463. var dayConfig = Mappers.Xy<LvlChartsDefaultInfo>()
  464. .X(dayModel => (double)dayModel.DateTime.Ticks / TimeSpan.FromHours(1).Ticks)
  465. .Y(dayModel => dayModel.Value);
  466. Series = new SeriesCollection(dayConfig)
  467. {
  468. new LineSeries
  469. {
  470. Title = "Download",
  471. Values = new ChartValues<LvlChartsDefaultInfo>(),
  472. PointGeometry = null
  473. },
  474. new LineSeries
  475. {
  476. Title = "Upload",
  477. Values = new ChartValues<LvlChartsDefaultInfo>(),
  478. PointGeometry = null
  479. }
  480. };
  481. FormatterDate = value => new DateTime((long)(value * TimeSpan.FromHours(1).Ticks)).ToString("hh:mm:ss");
  482. FormatterSpeed = value => $"{FileSizeConverter.GetBytesReadable((long)value * 8)}it/s";
  483. }
  484. public Func<double, string> FormatterDate { get; set; }
  485. public Func<double, string> FormatterSpeed { get; set; }
  486. public SeriesCollection Series { get; set; }
  487. private async void LoadNetworkInterfaces()
  488. {
  489. IsNetworkInterfaceLoading = true;
  490. NetworkInterfaces = await Models.Network.NetworkInterface.GetNetworkInterfacesAsync();
  491. // Get the last selected interface, if it is still available on this machine...
  492. if (NetworkInterfaces.Count > 0)
  493. {
  494. var info = NetworkInterfaces.FirstOrDefault(s => s.Id == SettingsManager.Current.NetworkInterface_InterfaceId);
  495. SelectedNetworkInterface = info ?? NetworkInterfaces[0];
  496. }
  497. IsNetworkInterfaceLoading = false;
  498. }
  499. private void LoadSettings()
  500. {
  501. ExpandProfileView = SettingsManager.Current.NetworkInterface_ExpandProfileView;
  502. ProfileWidth = ExpandProfileView ? new GridLength(SettingsManager.Current.NetworkInterface_ProfileWidth) : new GridLength(GlobalStaticConfiguration.Profile_WidthCollapsed);
  503. _tempProfileWidth = SettingsManager.Current.NetworkInterface_ProfileWidth;
  504. }
  505. #endregion
  506. #region ICommands & Actions
  507. public ICommand ReloadNetworkInterfacesCommand => new RelayCommand(p => ReloadNetworkInterfacesAction(), ReloadNetworkInterfaces_CanExecute);
  508. private bool ReloadNetworkInterfaces_CanExecute(object obj) => !IsNetworkInterfaceLoading && Application.Current.MainWindow != null && !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen;
  509. private async void ReloadNetworkInterfacesAction()
  510. {
  511. IsNetworkInterfaceLoading = true;
  512. await Task.Delay(2000); // Make the user happy, let him see a reload animation (and he cannot spam the reload command)
  513. var id = string.Empty;
  514. if (SelectedNetworkInterface != null)
  515. id = SelectedNetworkInterface.Id;
  516. NetworkInterfaces = await Models.Network.NetworkInterface.GetNetworkInterfacesAsync();
  517. // Change interface...
  518. SelectedNetworkInterface = string.IsNullOrEmpty(id) ? NetworkInterfaces.FirstOrDefault() : NetworkInterfaces.FirstOrDefault(x => x.Id == id);
  519. IsNetworkInterfaceLoading = false;
  520. }
  521. public ICommand OpenNetworkConnectionsCommand => new RelayCommand(p => OpenNetworkConnectionsAction(), OpenNetworkConnections_CanExecute);
  522. private bool OpenNetworkConnections_CanExecute(object paramter) => Application.Current.MainWindow != null && !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen;
  523. public async void OpenNetworkConnectionsAction()
  524. {
  525. try
  526. {
  527. Process.Start("NCPA.cpl");
  528. }
  529. catch (Exception ex)
  530. {
  531. await _dialogCoordinator.ShowMessageAsync(this, Localization.Resources.Strings.Error, ex.Message, MessageDialogStyle.Affirmative, AppearanceManager.MetroDialog);
  532. }
  533. }
  534. public ICommand ApplyConfigurationCommand => new RelayCommand(p => ApplyConfigurationAction(), ApplyConfiguration_CanExecute);
  535. private bool ApplyConfiguration_CanExecute(object paramter) => Application.Current.MainWindow != null && !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen;
  536. public void ApplyConfigurationAction()
  537. {
  538. ApplyConfiguration();
  539. }
  540. public ICommand ApplyProfileConfigCommand => new RelayCommand(p => ApplyProfileProfileAction());
  541. private void ApplyProfileProfileAction()
  542. {
  543. ApplyProfileConfig();
  544. }
  545. public ICommand AddProfileCommand => new RelayCommand(p => AddProfileAction());
  546. private void AddProfileAction()
  547. {
  548. ProfileDialogManager.ShowAddProfileDialog(this, _dialogCoordinator);
  549. }
  550. public ICommand EditProfileCommand => new RelayCommand(p => EditProfileAction());
  551. private void EditProfileAction()
  552. {
  553. ProfileDialogManager.ShowEditProfileDialog(this, _dialogCoordinator, SelectedProfile);
  554. }
  555. public ICommand CopyAsProfileCommand => new RelayCommand(p => CopyAsProfileAction());
  556. private void CopyAsProfileAction()
  557. {
  558. ProfileDialogManager.ShowCopyAsProfileDialog(this, _dialogCoordinator, SelectedProfile);
  559. }
  560. public ICommand DeleteProfileCommand => new RelayCommand(p => DeleteProfileAction());
  561. private void DeleteProfileAction()
  562. {
  563. ProfileDialogManager.ShowDeleteProfileDialog(this, _dialogCoordinator, SelectedProfile);
  564. }
  565. public ICommand EditGroupCommand => new RelayCommand(EditGroupAction);
  566. private void EditGroupAction(object group)
  567. {
  568. ProfileDialogManager.ShowEditGroupDialog(this, _dialogCoordinator, group.ToString());
  569. }
  570. public ICommand FlushDNSCommand => new RelayCommand(p => FlushDNSAction(), FlushDNS_CanExecute);
  571. private bool FlushDNS_CanExecute(object paramter) => Application.Current.MainWindow != null && !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen;
  572. private async void FlushDNSAction()
  573. {
  574. IsConfigurationRunning = true;
  575. DisplayStatusMessage = false;
  576. await Models.Network.NetworkInterface.FlushDnsAsync();
  577. IsConfigurationRunning = false;
  578. }
  579. public ICommand ClearSearchCommand => new RelayCommand(p => ClearSearchAction());
  580. private void ClearSearchAction()
  581. {
  582. Search = string.Empty;
  583. }
  584. public ICommand ReleaseRenewCommand => new RelayCommand(p => ReleaseRenewAction(), ReleaseRenew_CanExecute);
  585. private bool ReleaseRenew_CanExecute(object paramter) => Application.Current.MainWindow != null && !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen;
  586. private async void ReleaseRenewAction()
  587. {
  588. IsConfigurationRunning = true;
  589. await Models.Network.NetworkInterface.ReleaseRenewAsync(Models.Network.NetworkInterface.IPConfigReleaseRenewMode.ReleaseRenew);
  590. IsConfigurationRunning = false;
  591. }
  592. public ICommand ReleaseCommand => new RelayCommand(p => ReleaseAction(), Release_CanExecute);
  593. private bool Release_CanExecute(object paramter) => Application.Current.MainWindow != null && !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen;
  594. private async void ReleaseAction()
  595. {
  596. IsConfigurationRunning = true;
  597. await Models.Network.NetworkInterface.ReleaseRenewAsync(Models.Network.NetworkInterface.IPConfigReleaseRenewMode.Release);
  598. IsConfigurationRunning = false;
  599. }
  600. public ICommand RenewCommand => new RelayCommand(p => RenewAction(), Renew_CanExecute);
  601. private bool Renew_CanExecute(object paramter) => Application.Current.MainWindow != null && !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen;
  602. private async void RenewAction()
  603. {
  604. IsConfigurationRunning = true;
  605. await Models.Network.NetworkInterface.ReleaseRenewAsync(Models.Network.NetworkInterface.IPConfigReleaseRenewMode.Renew);
  606. IsConfigurationRunning = false;
  607. }
  608. public ICommand AddIPv4AddressCommand => new RelayCommand(p => AddIPv4AddressAction(), AddIPv4Address_CanExecute);
  609. private bool AddIPv4Address_CanExecute(object paramter) => Application.Current.MainWindow != null && !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen;
  610. private async void AddIPv4AddressAction()
  611. {
  612. var customDialog = new CustomDialog
  613. {
  614. Title = Localization.Resources.Strings.AddIPv4Address
  615. };
  616. var networkInterfaceAddIPAddressViewModel = new NetworkInterfaceAddIPAddressViewModel(async instance =>
  617. {
  618. await _dialogCoordinator.HideMetroDialogAsync(this, customDialog);
  619. AddIPv4Address(instance.IPAddress, instance.SubnetmaskOrCidr);
  620. }, instance =>
  621. {
  622. _dialogCoordinator.HideMetroDialogAsync(this, customDialog);
  623. });
  624. customDialog.Content = new NetworkInterfaceAddIPAddressDialog
  625. {
  626. DataContext = networkInterfaceAddIPAddressViewModel
  627. };
  628. await _dialogCoordinator.ShowMetroDialogAsync(this, customDialog);
  629. }
  630. #endregion
  631. #region Methods
  632. private void SetConfigurationDefaults(NetworkInterfaceInfo info)
  633. {
  634. if (info.DhcpEnabled)
  635. {
  636. ConfigEnableDynamicIPAddress = true;
  637. }
  638. else
  639. {
  640. ConfigEnableStaticIPAddress = true;
  641. ConfigIPAddress = info.IPv4Address.FirstOrDefault()?.ToString();
  642. ConfigSubnetmaskOrCidr = info.Subnetmask != null ? info.Subnetmask.FirstOrDefault()?.ToString() : string.Empty;
  643. ConfigGateway = info.IPv4Gateway?.Any() == true ? info.IPv4Gateway.FirstOrDefault()?.ToString() : string.Empty;
  644. }
  645. if (info.DNSAutoconfigurationEnabled)
  646. {
  647. ConfigEnableDynamicDNS = true;
  648. }
  649. else
  650. {
  651. ConfigEnableStaticDNS = true;
  652. var dnsServers = info.DNSServer.Where(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToList();
  653. ConfigPrimaryDNSServer = dnsServers.Count > 0 ? dnsServers[0].ToString() : string.Empty;
  654. ConfigSecondaryDNSServer = dnsServers.Count > 1 ? dnsServers[1].ToString() : string.Empty;
  655. }
  656. }
  657. public async void ApplyConfiguration()
  658. {
  659. IsConfigurationRunning = true;
  660. DisplayStatusMessage = false;
  661. var subnetmask = ConfigSubnetmaskOrCidr;
  662. // CIDR to subnetmask
  663. if (ConfigEnableStaticIPAddress && subnetmask.StartsWith("/"))
  664. subnetmask = Subnetmask.GetFromCidr(int.Parse(subnetmask.TrimStart('/'))).Subnetmask;
  665. // If primary and secondary DNS are empty --> autoconfiguration
  666. if (ConfigEnableStaticDNS && string.IsNullOrEmpty(ConfigPrimaryDNSServer) && string.IsNullOrEmpty(ConfigSecondaryDNSServer))
  667. ConfigEnableDynamicDNS = true;
  668. // When primary DNS is empty, swap it with secondary (if not empty)
  669. if (ConfigEnableStaticDNS && string.IsNullOrEmpty(ConfigPrimaryDNSServer) && !string.IsNullOrEmpty(ConfigSecondaryDNSServer))
  670. {
  671. ConfigPrimaryDNSServer = ConfigSecondaryDNSServer;
  672. ConfigSecondaryDNSServer = string.Empty;
  673. }
  674. var config = new NetworkInterfaceConfig
  675. {
  676. Name = SelectedNetworkInterface.Name,
  677. EnableStaticIPAddress = ConfigEnableStaticIPAddress,
  678. IPAddress = ConfigIPAddress,
  679. Subnetmask = subnetmask,
  680. Gateway = ConfigGateway,
  681. EnableStaticDNS = ConfigEnableStaticDNS,
  682. PrimaryDNSServer = ConfigPrimaryDNSServer,
  683. SecondaryDNSServer = ConfigSecondaryDNSServer
  684. };
  685. try
  686. {
  687. var networkInterface = new Models.Network.NetworkInterface();
  688. networkInterface.UserHasCanceled += NetworkInterface_UserHasCanceled;
  689. await networkInterface.ConfigureNetworkInterfaceAsync(config);
  690. ReloadNetworkInterfacesAction();
  691. }
  692. catch (Exception ex)
  693. {
  694. StatusMessage = ex.Message;
  695. DisplayStatusMessage = true;
  696. }
  697. finally
  698. {
  699. IsConfigurationRunning = false;
  700. }
  701. }
  702. public async void AddIPv4Address(string ipAddress, string subnetmaskOrCidr)
  703. {
  704. IsConfigurationRunning = true;
  705. DisplayStatusMessage = false;
  706. var subnetmask = subnetmaskOrCidr;
  707. // CIDR to subnetmask
  708. if (subnetmask.StartsWith("/"))
  709. subnetmask = Subnetmask.GetFromCidr(int.Parse(subnetmask.TrimStart('/'))).Subnetmask;
  710. var config = new NetworkInterfaceConfig
  711. {
  712. Name = SelectedNetworkInterface.Name,
  713. IPAddress = ipAddress,
  714. Subnetmask = subnetmask
  715. };
  716. try
  717. {
  718. await Models.Network.NetworkInterface.AddIPAddressToNetworkInterfaceAsync(config);
  719. ReloadNetworkInterfacesAction();
  720. }
  721. catch (Exception ex)
  722. {
  723. StatusMessage = ex.Message;
  724. DisplayStatusMessage = true;
  725. }
  726. finally
  727. {
  728. IsConfigurationRunning = false;
  729. }
  730. }
  731. public async void ApplyProfileConfig()
  732. {
  733. IsConfigurationRunning = true;
  734. DisplayStatusMessage = false;
  735. var subnetmask = SelectedProfile.NetworkInterface_SubnetmaskOrCidr;
  736. // CIDR to subnetmask
  737. if (SelectedProfile.NetworkInterface_EnableStaticIPAddress && subnetmask.StartsWith("/"))
  738. subnetmask = Subnetmask.GetFromCidr(int.Parse(subnetmask.TrimStart('/'))).Subnetmask;
  739. var enableStaticDNS = SelectedProfile.NetworkInterface_EnableStaticDNS;
  740. var primaryDNSServer = SelectedProfile.NetworkInterface_PrimaryDNSServer;
  741. var secondaryDNSServer = SelectedProfile.NetworkInterface_SecondaryDNSServer;
  742. // If primary and secondary DNS are empty --> autoconfiguration
  743. if (enableStaticDNS && string.IsNullOrEmpty(primaryDNSServer) && string.IsNullOrEmpty(secondaryDNSServer))
  744. enableStaticDNS = false;
  745. // When primary DNS is empty, swap it with secondary (if not empty)
  746. if (SelectedProfile.NetworkInterface_EnableStaticDNS && string.IsNullOrEmpty(primaryDNSServer) && !string.IsNullOrEmpty(secondaryDNSServer))
  747. {
  748. primaryDNSServer = secondaryDNSServer;
  749. secondaryDNSServer = string.Empty;
  750. }
  751. var config = new NetworkInterfaceConfig
  752. {
  753. Name = SelectedNetworkInterface.Name,
  754. EnableStaticIPAddress = SelectedProfile.NetworkInterface_EnableStaticIPAddress,
  755. IPAddress = SelectedProfile.NetworkInterface_IPAddress,
  756. Subnetmask = subnetmask,
  757. Gateway = SelectedProfile.NetworkInterface_Gateway,
  758. EnableStaticDNS = enableStaticDNS,
  759. PrimaryDNSServer = primaryDNSServer,
  760. SecondaryDNSServer = secondaryDNSServer
  761. };
  762. try
  763. {
  764. var networkInterface = new Models.Network.NetworkInterface();
  765. networkInterface.UserHasCanceled += NetworkInterface_UserHasCanceled;
  766. await networkInterface.ConfigureNetworkInterfaceAsync(config);
  767. ReloadNetworkInterfacesAction();
  768. }
  769. catch (Exception ex)
  770. {
  771. StatusMessage = ex.Message;
  772. DisplayStatusMessage = true;
  773. }
  774. finally
  775. {
  776. IsConfigurationRunning = false;
  777. }
  778. }
  779. private void StartDelayedSearch()
  780. {
  781. if (!IsSearching)
  782. {
  783. IsSearching = true;
  784. _searchDispatcherTimer.Start();
  785. }
  786. else
  787. {
  788. _searchDispatcherTimer.Stop();
  789. _searchDispatcherTimer.Start();
  790. }
  791. }
  792. private void StopDelayedSearch()
  793. {
  794. _searchDispatcherTimer.Stop();
  795. RefreshProfiles();
  796. IsSearching = false;
  797. }
  798. private void ResizeProfile(bool dueToChangedSize)
  799. {
  800. _canProfileWidthChange = false;
  801. if (dueToChangedSize)
  802. {
  803. ExpandProfileView = Math.Abs(ProfileWidth.Value - GlobalStaticConfiguration.Profile_WidthCollapsed) > GlobalStaticConfiguration.FloatPointFix;
  804. }
  805. else
  806. {
  807. if (ExpandProfileView)
  808. {
  809. ProfileWidth = Math.Abs(_tempProfileWidth - GlobalStaticConfiguration.Profile_WidthCollapsed) < GlobalStaticConfiguration.FloatPointFix ? new GridLength(GlobalStaticConfiguration.Profile_DefaultWidthExpanded) : new GridLength(_tempProfileWidth);
  810. }
  811. else
  812. {
  813. _tempProfileWidth = ProfileWidth.Value;
  814. ProfileWidth = new GridLength(GlobalStaticConfiguration.Profile_WidthCollapsed);
  815. }
  816. }
  817. _canProfileWidthChange = true;
  818. }
  819. public void ResetBandwidthChart()
  820. {
  821. if (Series == null)
  822. return;
  823. Series[0].Values.Clear();
  824. Series[1].Values.Clear();
  825. var currentDateTime = DateTime.Now;
  826. for (var i = 60; i > 0; i--)
  827. {
  828. var bandwidthInfo = new LvlChartsDefaultInfo(currentDateTime.AddSeconds(-i), double.NaN);
  829. Series[0].Values.Add(bandwidthInfo);
  830. Series[1].Values.Add(bandwidthInfo);
  831. }
  832. }
  833. private bool _resetBandwidthStatisticOnNextUpdate;
  834. private void StartBandwidthMeter(string networkInterfaceId)
  835. {
  836. // Reset chart
  837. ResetBandwidthChart();
  838. // Reset statistic
  839. _resetBandwidthStatisticOnNextUpdate = true;
  840. _bandwidthMeter = new BandwidthMeter(networkInterfaceId);
  841. _bandwidthMeter.UpdateSpeed += BandwidthMeter_UpdateSpeed;
  842. _bandwidthMeter.Start();
  843. }
  844. private void ResumeBandwidthMeter()
  845. {
  846. if (_bandwidthMeter != null && !_bandwidthMeter.IsRunning)
  847. {
  848. ResetBandwidthChart();
  849. _resetBandwidthStatisticOnNextUpdate = true;
  850. _bandwidthMeter.Start();
  851. }
  852. }
  853. private void StopBandwidthMeter()
  854. {
  855. if (_bandwidthMeter != null && _bandwidthMeter.IsRunning)
  856. _bandwidthMeter.Stop();
  857. }
  858. public void OnViewVisible()
  859. {
  860. RefreshProfiles();
  861. ResumeBandwidthMeter();
  862. }
  863. public void OnViewHide()
  864. {
  865. StopBandwidthMeter();
  866. }
  867. public void RefreshProfiles()
  868. {
  869. Profiles.Refresh();
  870. }
  871. public void OnProfileDialogOpen()
  872. {
  873. }
  874. public void OnProfileDialogClose()
  875. {
  876. }
  877. #endregion
  878. #region Events
  879. private void SearchDispatcherTimer_Tick(object sender, EventArgs e)
  880. {
  881. StopDelayedSearch();
  882. }
  883. private void BandwidthMeter_UpdateSpeed(object sender, BandwidthMeterSpeedArgs e)
  884. {
  885. // Reset statistics
  886. if(_resetBandwidthStatisticOnNextUpdate)
  887. {
  888. BandwidthStartTime = DateTime.Now;
  889. _bandwidthTotalBytesReceivedTemp = e.TotalBytesReceived;
  890. _bandwidthTotalBytesSentTemp = e.TotalBytesSent;
  891. _resetBandwidthStatisticOnNextUpdate = false;
  892. }
  893. // Measured time
  894. BandwidthMeasuredTime = DateTime.Now - BandwidthStartTime;
  895. // Current download/upload
  896. BandwidthTotalBytesReceived = e.TotalBytesReceived;
  897. BandwidthTotalBytesSent = e.TotalBytesSent;
  898. BandwidthBytesReceivedSpeed = e.ByteReceivedSpeed;
  899. BandwidthBytesSentSpeed = e.ByteSentSpeed;
  900. // Total download/upload
  901. BandwidthDiffBytesReceived = BandwidthTotalBytesReceived - _bandwidthTotalBytesReceivedTemp;
  902. BandwidthDiffBytesSent = BandwidthTotalBytesSent - _bandwidthTotalBytesSentTemp;
  903. // Add chart entry
  904. Series[0].Values.Add(new LvlChartsDefaultInfo(e.DateTime, e.ByteReceivedSpeed));
  905. Series[1].Values.Add(new LvlChartsDefaultInfo(e.DateTime, e.ByteSentSpeed));
  906. // Remove data older than 60 seconds
  907. if (Series[0].Values.Count > 59)
  908. Series[0].Values.RemoveAt(0);
  909. if (Series[1].Values.Count > 59)
  910. Series[1].Values.RemoveAt(0);
  911. }
  912. private void NetworkInterface_UserHasCanceled(object sender, EventArgs e)
  913. {
  914. StatusMessage = Localization.Resources.Strings.CanceledByUserMessage;
  915. DisplayStatusMessage = true;
  916. }
  917. private void SettingsManager_PropertyChanged(object sender, PropertyChangedEventArgs e)
  918. {
  919. }
  920. #endregion
  921. }
  922. }