VMConfigPortForwardingViewController.m 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. //
  2. // Copyright © 2020 osy. All rights reserved.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #import "VMConfigPortForwardingViewController.h"
  17. #import "UTMQemuConfiguration+Networking.h"
  18. #import "UTMQemuConfigurationPortForward.h"
  19. @interface VMConfigPortForwardingViewController ()
  20. @end
  21. @implementation VMConfigPortForwardingViewController
  22. @synthesize configuration;
  23. - (void)viewDidLoad {
  24. [super viewDidLoad];
  25. self.navigationItem.rightBarButtonItems = @[ self.addButtonItem, self.editButtonItem ];
  26. }
  27. - (void)viewWillAppear:(BOOL)animated {
  28. [super viewWillAppear:animated];
  29. [self refreshViewFromConfiguration];
  30. }
  31. - (void)refreshViewFromConfiguration {
  32. [self.tableView reloadData];
  33. }
  34. #pragma mark - Table view data source
  35. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  36. return 1;
  37. }
  38. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  39. NSAssert(section == 0, @"Invalid section");
  40. return [self.configuration countPortForwards];
  41. }
  42. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  43. NSAssert(indexPath.section == 0, @"Invalid section");
  44. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"portForwardCell" forIndexPath:indexPath];
  45. UTMQemuConfigurationPortForward *portForward = [self.configuration portForwardForIndex:indexPath.row];
  46. cell.textLabel.text = [NSString stringWithFormat:@"%@:%@ ➡️ %@:%@", portForward.hostAddress, portForward.hostPort, portForward.guestAddress, portForward.guestPort];
  47. cell.detailTextLabel.text = portForward.protocol;
  48. return cell;
  49. }
  50. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
  51. NSAssert(indexPath.section == 0, @"Invalid section");
  52. if (editingStyle == UITableViewCellEditingStyleDelete) {
  53. [self.configuration removePortForwardAtIndex:indexPath.row];
  54. // Delete the row from the data source
  55. [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
  56. }
  57. }
  58. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  59. NSAssert(indexPath.section == 0, @"Invalid section");
  60. UTMQemuConfigurationPortForward *portForward = [self.configuration portForwardForIndex:indexPath.row];
  61. if (portForward) {
  62. [self createPortForwardFormTCP:[portForward.protocol isEqualToString:@"tcp"]
  63. existing:portForward
  64. atIndex:indexPath.row];
  65. }
  66. [tableView deselectRowAtIndexPath:indexPath animated:YES];
  67. }
  68. #pragma mark - Add new port
  69. - (void)createPortForwardFormTCP:(BOOL)tcp {
  70. [self createPortForwardFormTCP:tcp existing:nil atIndex:0];
  71. }
  72. - (void)createPortForwardFormTCP:(BOOL)tcp existing:(nullable UTMQemuConfigurationPortForward *)existing atIndex:(NSUInteger)index {
  73. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:tcp ? NSLocalizedString(@"TCP Forward", @"VMConfigPortForwardingViewController") : NSLocalizedString(@"UDP Forward", @"VMConfigPortForwardingViewController")
  74. message:nil
  75. preferredStyle:UIAlertControllerStyleAlert];
  76. [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
  77. textField.placeholder = NSLocalizedString(@"Host address (optional)", @"VMConfigPortForwardingViewController");
  78. textField.keyboardType = UIKeyboardTypeDecimalPad;
  79. textField.text = existing.hostAddress;
  80. }];
  81. [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
  82. textField.placeholder = NSLocalizedString(@"Host port (required)", @"VMConfigPortForwardingViewController");
  83. textField.keyboardType = UIKeyboardTypeNumberPad;
  84. textField.text = existing ? [existing.hostPort stringValue] : @"";
  85. }];
  86. [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
  87. textField.placeholder = NSLocalizedString(@"Guest address (optional)", @"VMConfigPortForwardingViewController");
  88. textField.keyboardType = UIKeyboardTypeDecimalPad;
  89. textField.text = existing.guestAddress;
  90. }];
  91. [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
  92. textField.placeholder = NSLocalizedString(@"Guest port (required)", @"VMConfigPortForwardingViewController");
  93. textField.keyboardType = UIKeyboardTypeNumberPad;
  94. textField.text = existing ? [existing.guestPort stringValue] : @"";
  95. }];
  96. [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"VMConfigPortForwardingViewController")
  97. style:UIAlertActionStyleCancel
  98. handler:nil]];
  99. [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Done", @"VMConfigPortForwardingViewController")
  100. style:UIAlertActionStyleDefault
  101. handler:^(UIAlertAction * _Nonnull action) {
  102. UTMQemuConfigurationPortForward *portForward = [[UTMQemuConfigurationPortForward alloc] init];
  103. portForward.protocol = tcp ? @"tcp" : @"udp";
  104. portForward.hostAddress = alertController.textFields[0].text;
  105. portForward.hostPort = @([alertController.textFields[1].text integerValue]);
  106. portForward.guestAddress = alertController.textFields[2].text;
  107. portForward.guestPort = @([alertController.textFields[3].text integerValue]);
  108. //TODO: validate input
  109. if (existing) {
  110. [self.configuration updatePortForwardAtIndex:index withValue:portForward];
  111. } else {
  112. [self.configuration newPortForward:portForward];
  113. }
  114. [self.tableView reloadData];
  115. }]];
  116. [self presentViewController:alertController animated:YES completion:nil];
  117. }
  118. #pragma mark - Event handlers
  119. - (IBAction)addButton:(UIBarButtonItem *)sender {
  120. UIAlertController *newForward = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"New port forward", @"VMConfigPortForwardingViewController")
  121. message:nil
  122. preferredStyle:UIAlertControllerStyleActionSheet];
  123. [newForward addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"TCP Forward", @"VMConfigPortForwardingViewController")
  124. style:UIAlertActionStyleDefault
  125. handler:^(UIAlertAction * _Nonnull action) {
  126. [self createPortForwardFormTCP:YES];
  127. }]];
  128. [newForward addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"UDP Forward", @"VMConfigPortForwardingViewController")
  129. style:UIAlertActionStyleDefault
  130. handler:^(UIAlertAction * _Nonnull action) {
  131. [self createPortForwardFormTCP:NO];
  132. }]];
  133. newForward.popoverPresentationController.barButtonItem = sender;
  134. [self presentViewController:newForward animated:YES completion:nil];
  135. }
  136. @end