Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| de8fedf87a | |||
| 98d306da5b | |||
| c7b7b1247b | |||
| a66f13eb01 | |||
| f50e7ae686 | |||
| 4d6692548c | |||
| 1dccd39818 | |||
| 4cb775c72f | |||
| 4cb783c447 |
@@ -1,12 +1,14 @@
|
||||
# [WireGuard](https://www.wireguard.com/) for iOS and macOS
|
||||
|
||||
This project contains an application for iOS and for macOS, as well as many components shared between the two of them. You may toggle between the two platforms by selecting the target from within Xcode.
|
||||
|
||||
## Building
|
||||
|
||||
- Clone this repo recursively:
|
||||
- Clone this repo:
|
||||
|
||||
```
|
||||
$ git clone --recursive https://git.zx2c4.com/wireguard-ios
|
||||
$ cd wireguard-ios
|
||||
$ git clone https://git.zx2c4.com/wireguard-apple
|
||||
$ cd wireguard-apple
|
||||
```
|
||||
|
||||
- Rename and populate developer team ID file:
|
||||
|
||||
@@ -308,7 +308,6 @@
|
||||
"macMenuHideApp" = "Hide WireGuard";
|
||||
"macMenuHideOtherApps" = "Hide Others";
|
||||
"macMenuShowAllApps" = "Show All";
|
||||
"macMenuQuitManagingTunnels" = "Quit Tunnel Manager";
|
||||
|
||||
"macMenuFile" = "File";
|
||||
"macMenuCloseWindow" = "Close Window";
|
||||
@@ -406,6 +405,12 @@
|
||||
|
||||
// Mac alert
|
||||
|
||||
"macConfirmAndQuitAlertMessage" = "Do you want to close the tunnels manager or quit WireGuard entirely?";
|
||||
"macConfirmAndQuitAlertInfo" = "If you close the tunnels manager, WireGuard will continue to be available from the menu bar icon.";
|
||||
"macConfirmAndQuitInfoWithActiveTunnel (%@)" = "If you close the tunnels manager, WireGuard will continue to be available from the menu bar icon.\n\nNote that if you quit WireGuard entirely the currently active tunnel ('%@') will still remain active until you deactivate it from this application or through the Network panel in System Preferences.";
|
||||
"macConfirmAndQuitAlertQuitWireGuard" = "Quit WireGuard";
|
||||
"macConfirmAndQuitAlertCloseWindow" = "Close Tunnels Manager";
|
||||
|
||||
"macAppExitingWithActiveTunnelMessage" = "WireGuard is exiting with an active tunnel";
|
||||
"macAppExitingWithActiveTunnelInfo" = "The tunnel will remain active after exiting. You may disable it by reopening this application or through the Network panel in System Preferences.";
|
||||
"macPrivacyNoticeMessage" = "Privacy notice: be sure you trust this configuration file";
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
VERSION_NAME = 0.0.20190531
|
||||
VERSION_ID = 9
|
||||
VERSION_NAME = 0.0.20190609
|
||||
VERSION_ID = 11
|
||||
|
||||
@@ -78,6 +78,33 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
return false
|
||||
}
|
||||
|
||||
@objc func confirmAndQuit() {
|
||||
let alert = NSAlert()
|
||||
alert.messageText = tr("macConfirmAndQuitAlertMessage")
|
||||
if let currentTunnel = tunnelsTracker?.currentTunnel, currentTunnel.status == .active || currentTunnel.status == .activating {
|
||||
alert.informativeText = tr(format: "macConfirmAndQuitInfoWithActiveTunnel (%@)", currentTunnel.name)
|
||||
} else {
|
||||
alert.informativeText = tr("macConfirmAndQuitAlertInfo")
|
||||
}
|
||||
alert.addButton(withTitle: tr("macConfirmAndQuitAlertCloseWindow"))
|
||||
alert.addButton(withTitle: tr("macConfirmAndQuitAlertQuitWireGuard"))
|
||||
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
if let manageWindow = manageTunnelsWindowObject {
|
||||
manageWindow.orderFront(self)
|
||||
alert.beginSheetModal(for: manageWindow) { response in
|
||||
switch response {
|
||||
case .alertFirstButtonReturn:
|
||||
manageWindow.close()
|
||||
case .alertSecondButtonReturn:
|
||||
NSApp.terminate(nil)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc func quit() {
|
||||
if let manageWindow = manageTunnelsWindowObject, manageWindow.attachedSheet != nil {
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
@@ -105,10 +132,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
}
|
||||
|
||||
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
|
||||
if UserDefaults.standard.bool(forKey: "shouldSuppressAppStoreUpdateDetection") {
|
||||
wg_log(.debug, staticMessage: "App Store update detection is suppressed")
|
||||
return .terminateNow
|
||||
}
|
||||
guard let currentTunnel = tunnelsTracker?.currentTunnel, currentTunnel.status == .active || currentTunnel.status == .activating else {
|
||||
return .terminateNow
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ class MainMenu: NSMenu {
|
||||
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
menu.addItem(withTitle: tr("macMenuQuitManagingTunnels"),
|
||||
action: #selector(NSWindow.performClose(_:)), keyEquivalent: "q")
|
||||
menu.addItem(withTitle: tr("macMenuQuit"),
|
||||
action: #selector(AppDelegate.confirmAndQuit), keyEquivalent: "q")
|
||||
|
||||
return menu
|
||||
}
|
||||
|
||||
@@ -3,13 +3,25 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
class LogViewCell: NSTextField {
|
||||
class LogViewCell: NSTableCellView {
|
||||
var text: String = "" {
|
||||
didSet { textField?.stringValue = text }
|
||||
}
|
||||
|
||||
init() {
|
||||
super.init(frame: .zero)
|
||||
isSelectable = false
|
||||
isEditable = false
|
||||
isBordered = false
|
||||
backgroundColor = .clear
|
||||
|
||||
let textField = NSTextField(wrappingLabelWithString: "")
|
||||
addSubview(textField)
|
||||
textField.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.activate([
|
||||
textField.leadingAnchor.constraint(equalTo: self.leadingAnchor),
|
||||
textField.trailingAnchor.constraint(equalTo: self.trailingAnchor),
|
||||
textField.topAnchor.constraint(equalTo: self.topAnchor),
|
||||
textField.bottomAnchor.constraint(equalTo: self.bottomAnchor)
|
||||
])
|
||||
|
||||
self.textField = textField
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@@ -17,19 +29,19 @@ class LogViewCell: NSTextField {
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
stringValue = ""
|
||||
preferredMaxLayoutWidth = 0
|
||||
textField?.stringValue = ""
|
||||
}
|
||||
}
|
||||
|
||||
class LogViewTimestampCell: LogViewCell {
|
||||
override init() {
|
||||
super.init()
|
||||
maximumNumberOfLines = 1
|
||||
lineBreakMode = .byClipping
|
||||
preferredMaxLayoutWidth = 0
|
||||
setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
|
||||
setContentHuggingPriority(.defaultLow, for: .vertical)
|
||||
if let textField = textField {
|
||||
textField.maximumNumberOfLines = 1
|
||||
textField.lineBreakMode = .byClipping
|
||||
textField.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
|
||||
textField.setContentHuggingPriority(.defaultLow, for: .vertical)
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@@ -40,10 +52,12 @@ class LogViewTimestampCell: LogViewCell {
|
||||
class LogViewMessageCell: LogViewCell {
|
||||
override init() {
|
||||
super.init()
|
||||
maximumNumberOfLines = 0
|
||||
lineBreakMode = .byWordWrapping
|
||||
setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
setContentHuggingPriority(.required, for: .vertical)
|
||||
if let textField = textField {
|
||||
textField.maximumNumberOfLines = 0
|
||||
textField.lineBreakMode = .byWordWrapping
|
||||
textField.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
textField.setContentHuggingPriority(.required, for: .vertical)
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
|
||||
@@ -146,7 +146,8 @@ class LogViewController: NSViewController {
|
||||
])
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
containerView.widthAnchor.constraint(equalToConstant: 640),
|
||||
containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: 640),
|
||||
containerView.widthAnchor.constraint(lessThanOrEqualToConstant: 1200),
|
||||
containerView.heightAnchor.constraint(greaterThanOrEqualToConstant: 240)
|
||||
])
|
||||
|
||||
@@ -192,6 +193,10 @@ class LogViewController: NSViewController {
|
||||
updateLogEntriesTimer = nil
|
||||
}
|
||||
|
||||
override func viewWillAppear() {
|
||||
view.window?.setFrameAutosaveName(NSWindow.FrameAutosaveName("LogWindow"))
|
||||
}
|
||||
|
||||
override func viewWillDisappear() {
|
||||
super.viewWillDisappear()
|
||||
stopUpdatingLogEntries()
|
||||
@@ -250,12 +255,11 @@ extension LogViewController: NSTableViewDelegate {
|
||||
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
||||
if LogColumn.time.isRepresenting(tableColumn: tableColumn) {
|
||||
let cell: LogViewTimestampCell = tableView.dequeueReusableCell()
|
||||
cell.stringValue = logEntries[row].timestamp
|
||||
cell.text = logEntries[row].timestamp
|
||||
return cell
|
||||
} else if LogColumn.logMessage.isRepresenting(tableColumn: tableColumn) {
|
||||
let cell: LogViewMessageCell = tableView.dequeueReusableCell()
|
||||
cell.stringValue = logEntries[row].message
|
||||
cell.preferredMaxLayoutWidth = tableColumn?.width ?? 0
|
||||
cell.text = logEntries[row].message
|
||||
return cell
|
||||
} else {
|
||||
fatalError()
|
||||
|
||||
@@ -11,7 +11,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
private var handle: Int32?
|
||||
private var networkMonitor: NWPathMonitor?
|
||||
private var ifname: String?
|
||||
private var lastSeenInterfaces: [String] = []
|
||||
private var lastPath: Network.NWPath?
|
||||
private var packetTunnelSettingsGenerator: PacketTunnelSettingsGenerator?
|
||||
|
||||
deinit {
|
||||
@@ -143,18 +143,15 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
|
||||
private func pathUpdate(path: Network.NWPath) {
|
||||
guard let handle = handle else { return }
|
||||
guard let ifname = ifname else { return }
|
||||
wg_log(.debug, message: "Network change detected with \(path.status) route and interface order \(path.availableInterfaces)")
|
||||
guard path.status == .satisfied else { return }
|
||||
|
||||
#if os(iOS)
|
||||
if let packetTunnelSettingsGenerator = packetTunnelSettingsGenerator {
|
||||
_ = packetTunnelSettingsGenerator.endpointUapiConfiguration().withGoString { return wgSetConfig(handle, $0) }
|
||||
}
|
||||
#endif
|
||||
let interfaces = path.availableInterfaces.filter { $0.name != ifname }.compactMap { $0.name }
|
||||
if !interfaces.elementsEqual(lastSeenInterfaces) {
|
||||
lastSeenInterfaces = interfaces
|
||||
if path != lastPath {
|
||||
lastPath = path
|
||||
wgBumpSockets(handle)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export CGO_ENABLED := 1
|
||||
build: $(DESTDIR)/libwg-go.a
|
||||
version-header: $(DESTDIR)/wireguard-go-version.h
|
||||
|
||||
GOBUILDVERSION_NEEDED := go version go1.12.1 darwin/amd64
|
||||
GOBUILDVERSION_NEEDED := go version go1.12.5 darwin/amd64
|
||||
GOBUILDVERSION_CURRENT := $(shell go version 2>/dev/null)
|
||||
export REAL_GOROOT := $(shell go env GOROOT 2>/dev/null)
|
||||
export GOROOT := $(BUILDDIR)/goroot
|
||||
|
||||
Reference in New Issue
Block a user