2018-05-24 20:07:04 +00:00
|
|
|
//
|
2018-05-26 07:17:36 +00:00
|
|
|
// TunnelConfigurationTableViewController.swift
|
2018-05-24 20:07:04 +00:00
|
|
|
// WireGuard
|
|
|
|
//
|
|
|
|
// Created by Jeroen Leenarts on 24-05-18.
|
2018-07-15 09:55:41 +00:00
|
|
|
// Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All rights reserved.
|
2018-05-24 20:07:04 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
import CoreData
|
|
|
|
import BNRCoreDataStack
|
2018-05-27 20:38:44 +00:00
|
|
|
import PromiseKit
|
2018-05-24 20:07:04 +00:00
|
|
|
|
2018-05-26 07:17:36 +00:00
|
|
|
protocol TunnelConfigurationTableViewControllerDelegate: class {
|
2018-05-27 20:38:44 +00:00
|
|
|
func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController)
|
2018-05-24 20:07:04 +00:00
|
|
|
}
|
|
|
|
|
2018-05-26 07:17:36 +00:00
|
|
|
class TunnelConfigurationTableViewController: UITableViewController {
|
2018-05-27 20:38:44 +00:00
|
|
|
|
|
|
|
@IBOutlet weak var saveButton: UIBarButtonItem!
|
|
|
|
|
|
|
|
private var viewContext: NSManagedObjectContext!
|
|
|
|
private weak var delegate: TunnelConfigurationTableViewControllerDelegate?
|
|
|
|
private var tunnel: Tunnel!
|
|
|
|
|
|
|
|
func configure(context: NSManagedObjectContext, delegate: TunnelConfigurationTableViewControllerDelegate? = nil, tunnel: Tunnel? = nil) {
|
|
|
|
viewContext = context
|
|
|
|
self.delegate = delegate
|
|
|
|
self.tunnel = tunnel ?? generateNewTunnelConfig()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private func generateNewTunnelConfig() -> Tunnel {
|
|
|
|
var tunnel: Tunnel! = nil
|
|
|
|
|
|
|
|
viewContext.performAndWait {
|
|
|
|
tunnel = Tunnel(context: viewContext)
|
2018-08-05 13:58:01 +00:00
|
|
|
let peer = Peer(context: viewContext)
|
|
|
|
peer.allowedIPs = "0.0.0.0/0, ::/0"
|
|
|
|
tunnel.addToPeers(peer)
|
2018-05-27 20:38:44 +00:00
|
|
|
|
|
|
|
let interface = Interface(context: viewContext)
|
|
|
|
|
|
|
|
tunnel.interface = interface
|
|
|
|
}
|
|
|
|
return tunnel
|
|
|
|
}
|
2018-05-24 20:07:04 +00:00
|
|
|
|
2018-05-29 20:47:52 +00:00
|
|
|
@IBAction func addPeer(_ sender: Any) {
|
|
|
|
if let moc = tunnel.managedObjectContext {
|
|
|
|
tableView.beginUpdates()
|
|
|
|
let insertedAt = IndexPath(row: tunnel.peers?.count ?? 0, section: 1)
|
|
|
|
tableView.insertRows(at: [insertedAt], with: .automatic)
|
2018-08-05 13:58:01 +00:00
|
|
|
|
|
|
|
let peer = Peer(context: moc)
|
|
|
|
peer.allowedIPs = "0.0.0.0/0, ::/0"
|
|
|
|
tunnel.addToPeers(peer)
|
|
|
|
|
2018-05-29 20:47:52 +00:00
|
|
|
tableView.endUpdates()
|
|
|
|
tableView.scrollToRow(at: insertedAt, at: .middle, animated: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-26 07:41:09 +00:00
|
|
|
override func numberOfSections(in tableView: UITableView) -> Int {
|
2018-05-24 20:07:04 +00:00
|
|
|
return 3
|
|
|
|
}
|
|
|
|
|
2018-05-26 07:41:09 +00:00
|
|
|
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
|
|
switch section {
|
|
|
|
case 1:
|
2018-05-27 20:38:44 +00:00
|
|
|
return tunnel?.peers?.count ?? 1
|
2018-05-26 07:41:09 +00:00
|
|
|
default:
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 20:07:04 +00:00
|
|
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
2018-05-26 07:41:09 +00:00
|
|
|
switch indexPath.section {
|
2018-05-24 20:07:04 +00:00
|
|
|
case 0:
|
2018-05-29 20:21:44 +00:00
|
|
|
let cell = tableView.dequeueReusableCell(type: InterfaceTableViewCell.self, for: indexPath)
|
|
|
|
cell.model = tunnel.interface
|
|
|
|
return cell
|
2018-05-24 20:07:04 +00:00
|
|
|
case 1:
|
2018-05-29 20:21:44 +00:00
|
|
|
let cell = tableView.dequeueReusableCell(type: PeerTableViewCell.self, for: indexPath)
|
|
|
|
if let peer = tunnel.peers?.object(at: indexPath.row) as? Peer {
|
|
|
|
cell.peer = peer
|
|
|
|
} else {
|
|
|
|
let peer = Peer(context: tunnel.managedObjectContext!)
|
|
|
|
tunnel.addToPeers(peer)
|
|
|
|
cell.peer = peer
|
|
|
|
}
|
2018-05-29 20:47:52 +00:00
|
|
|
cell.delegate = self
|
|
|
|
return cell
|
2018-05-24 20:07:04 +00:00
|
|
|
default:
|
2018-05-29 20:47:52 +00:00
|
|
|
let cell = tableView.dequeueReusableCell(type: AddPeerTableViewCell.self, for: indexPath)
|
|
|
|
cell.tunnel = tunnel
|
|
|
|
return cell
|
2018-05-24 20:07:04 +00:00
|
|
|
}
|
|
|
|
}
|
2018-05-27 20:38:44 +00:00
|
|
|
|
|
|
|
@IBAction func saveTunnelConfiguration(_ sender: Any) {
|
|
|
|
Promise<Void>(resolver: { (seal) in
|
|
|
|
viewContext.perform({
|
|
|
|
self.viewContext.saveContext({ (result) in
|
|
|
|
switch result {
|
|
|
|
case .success:
|
|
|
|
seal.fulfill(())
|
|
|
|
case .failure(let error):
|
|
|
|
seal.reject(error)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}).then { () -> Promise<Void> in
|
|
|
|
self.delegate?.didSave(tunnel: self.tunnel, tunnelConfigurationTableViewController: self)
|
|
|
|
return Promise.value(())
|
|
|
|
}.catch { error in
|
|
|
|
print("Error saving: \(error)")
|
|
|
|
}
|
|
|
|
}
|
2018-05-24 20:07:04 +00:00
|
|
|
}
|
|
|
|
|
2018-05-29 20:47:52 +00:00
|
|
|
extension TunnelConfigurationTableViewController: PeerTableViewCellDelegate {
|
|
|
|
func delete(peer: Peer) {
|
|
|
|
if let moc = tunnel.managedObjectContext {
|
|
|
|
tableView.beginUpdates()
|
|
|
|
let deletedAt = IndexPath(row: tunnel.peers?.index(of: peer) ?? 0, section: 1)
|
|
|
|
tableView.deleteRows(at: [deletedAt], with: .automatic)
|
|
|
|
tunnel.removeFromPeers(peer)
|
|
|
|
moc.delete(peer)
|
|
|
|
tableView.endUpdates()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 20:07:04 +00:00
|
|
|
class InterfaceTableViewCell: UITableViewCell {
|
2018-08-05 13:58:01 +00:00
|
|
|
var model: Interface! {
|
|
|
|
didSet {
|
|
|
|
nameField.text = model.tunnel?.title
|
|
|
|
privateKeyField.text = model.privateKey
|
|
|
|
listenPortField.text = String(model.listenPort)
|
|
|
|
dnsField.text = model.dns
|
|
|
|
mtuField.text = String(model.mtu)
|
|
|
|
}
|
|
|
|
}
|
2018-05-27 20:38:44 +00:00
|
|
|
|
|
|
|
@IBOutlet weak var nameField: UITextField!
|
|
|
|
@IBOutlet weak var privateKeyField: UITextField!
|
|
|
|
@IBOutlet weak var publicKeyField: UITextField!
|
|
|
|
@IBOutlet weak var listenPortField: UITextField!
|
|
|
|
@IBOutlet weak var dnsField: UITextField!
|
|
|
|
@IBOutlet weak var mtuField: UITextField!
|
2018-05-24 20:07:04 +00:00
|
|
|
}
|
|
|
|
|
2018-05-27 20:38:44 +00:00
|
|
|
extension InterfaceTableViewCell: UITextFieldDelegate {
|
2018-05-29 20:21:44 +00:00
|
|
|
@IBAction
|
|
|
|
func textfieldDidChange(_ sender: UITextField) {
|
|
|
|
let string = sender.text
|
|
|
|
|
|
|
|
if sender == nameField {
|
|
|
|
model.tunnel?.title = string
|
|
|
|
} else if sender == privateKeyField {
|
|
|
|
model.privateKey = string
|
|
|
|
} else if sender == listenPortField {
|
|
|
|
if let string = string, let port = Int16(string) {
|
|
|
|
model.listenPort = port
|
|
|
|
}
|
|
|
|
} else if sender == dnsField {
|
|
|
|
model.dns = string
|
|
|
|
} else if sender == mtuField {
|
|
|
|
if let string = string, let mtu = Int32(string) {
|
|
|
|
model.mtu = mtu
|
|
|
|
}
|
|
|
|
}
|
2018-05-27 20:38:44 +00:00
|
|
|
}
|
2018-05-29 20:47:52 +00:00
|
|
|
}
|
2018-05-27 20:38:44 +00:00
|
|
|
|
2018-05-29 20:47:52 +00:00
|
|
|
protocol PeerTableViewCellDelegate: class {
|
|
|
|
func delete(peer: Peer)
|
2018-05-27 20:38:44 +00:00
|
|
|
}
|
|
|
|
|
2018-05-24 20:07:04 +00:00
|
|
|
class PeerTableViewCell: UITableViewCell {
|
2018-08-05 13:58:01 +00:00
|
|
|
var peer: Peer! {
|
|
|
|
didSet {
|
|
|
|
publicKeyField.text = peer.publicKey
|
|
|
|
preSharedKeyField.text = peer.presharedKey
|
|
|
|
allowedIpsField.text = peer.allowedIPs
|
|
|
|
endpointField.text = peer.endpoint
|
|
|
|
persistentKeepaliveField.text = String(peer.persistentKeepalive)
|
|
|
|
}
|
|
|
|
}
|
2018-05-29 20:47:52 +00:00
|
|
|
weak var delegate: PeerTableViewCellDelegate?
|
2018-05-27 20:38:44 +00:00
|
|
|
|
|
|
|
@IBOutlet weak var publicKeyField: UITextField!
|
|
|
|
@IBOutlet weak var preSharedKeyField: UITextField!
|
|
|
|
@IBOutlet weak var allowedIpsField: UITextField!
|
|
|
|
@IBOutlet weak var endpointField: UITextField!
|
|
|
|
@IBOutlet weak var persistentKeepaliveField: UITextField!
|
2018-05-24 20:07:04 +00:00
|
|
|
|
2018-05-29 20:47:52 +00:00
|
|
|
@IBAction func deletePeer(_ sender: Any) {
|
|
|
|
delegate?.delete(peer: peer)
|
|
|
|
}
|
2018-05-24 20:07:04 +00:00
|
|
|
}
|
|
|
|
|
2018-05-27 20:38:44 +00:00
|
|
|
extension PeerTableViewCell: UITextFieldDelegate {
|
2018-05-29 20:21:44 +00:00
|
|
|
@IBAction
|
|
|
|
func textfieldDidChange(_ sender: UITextField) {
|
|
|
|
let string = sender.text
|
|
|
|
|
|
|
|
if sender == publicKeyField {
|
|
|
|
peer.publicKey = string
|
|
|
|
} else if sender == preSharedKeyField {
|
|
|
|
peer.presharedKey = string
|
|
|
|
} else if sender == allowedIpsField {
|
|
|
|
peer.allowedIPs = string
|
|
|
|
} else if sender == endpointField {
|
|
|
|
peer.endpoint = string
|
|
|
|
} else if sender == persistentKeepaliveField {
|
|
|
|
if let string = string, let persistentKeepalive = Int16(string) {
|
|
|
|
peer.persistentKeepalive = persistentKeepalive
|
|
|
|
}
|
|
|
|
}
|
2018-05-27 20:38:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 20:07:04 +00:00
|
|
|
class AddPeerTableViewCell: UITableViewCell {
|
2018-05-29 20:47:52 +00:00
|
|
|
var tunnel: Tunnel!
|
2018-05-27 20:38:44 +00:00
|
|
|
|
|
|
|
@IBAction func addPeer(_ sender: Any) {
|
2018-05-29 20:47:52 +00:00
|
|
|
if let moc = tunnel.managedObjectContext {
|
|
|
|
tunnel.addToPeers(Peer(context: moc))
|
|
|
|
}
|
2018-05-27 20:38:44 +00:00
|
|
|
}
|
2018-05-24 20:07:04 +00:00
|
|
|
}
|
|
|
|
|
2018-05-26 07:17:36 +00:00
|
|
|
extension TunnelConfigurationTableViewController: Identifyable {}
|
2018-05-24 20:07:04 +00:00
|
|
|
extension InterfaceTableViewCell: Identifyable {}
|
|
|
|
extension PeerTableViewCell: Identifyable {}
|
|
|
|
extension AddPeerTableViewCell: Identifyable {}
|