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
|
# [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
|
## Building
|
||||||
|
|
||||||
- Clone this repo recursively:
|
- Clone this repo:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ git clone --recursive https://git.zx2c4.com/wireguard-ios
|
$ git clone https://git.zx2c4.com/wireguard-apple
|
||||||
$ cd wireguard-ios
|
$ cd wireguard-apple
|
||||||
```
|
```
|
||||||
|
|
||||||
- Rename and populate developer team ID file:
|
- Rename and populate developer team ID file:
|
||||||
|
|||||||
@@ -308,7 +308,6 @@
|
|||||||
"macMenuHideApp" = "Hide WireGuard";
|
"macMenuHideApp" = "Hide WireGuard";
|
||||||
"macMenuHideOtherApps" = "Hide Others";
|
"macMenuHideOtherApps" = "Hide Others";
|
||||||
"macMenuShowAllApps" = "Show All";
|
"macMenuShowAllApps" = "Show All";
|
||||||
"macMenuQuitManagingTunnels" = "Quit Tunnel Manager";
|
|
||||||
|
|
||||||
"macMenuFile" = "File";
|
"macMenuFile" = "File";
|
||||||
"macMenuCloseWindow" = "Close Window";
|
"macMenuCloseWindow" = "Close Window";
|
||||||
@@ -406,6 +405,12 @@
|
|||||||
|
|
||||||
// Mac alert
|
// 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";
|
"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.";
|
"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";
|
"macPrivacyNoticeMessage" = "Privacy notice: be sure you trust this configuration file";
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
VERSION_NAME = 0.0.20190531
|
VERSION_NAME = 0.0.20190609
|
||||||
VERSION_ID = 9
|
VERSION_ID = 11
|
||||||
|
|||||||
@@ -78,6 +78,33 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
return false
|
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() {
|
@objc func quit() {
|
||||||
if let manageWindow = manageTunnelsWindowObject, manageWindow.attachedSheet != nil {
|
if let manageWindow = manageTunnelsWindowObject, manageWindow.attachedSheet != nil {
|
||||||
NSApp.activate(ignoringOtherApps: true)
|
NSApp.activate(ignoringOtherApps: true)
|
||||||
@@ -105,10 +132,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
|
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 {
|
guard let currentTunnel = tunnelsTracker?.currentTunnel, currentTunnel.status == .active || currentTunnel.status == .activating else {
|
||||||
return .terminateNow
|
return .terminateNow
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ class MainMenu: NSMenu {
|
|||||||
|
|
||||||
menu.addItem(NSMenuItem.separator())
|
menu.addItem(NSMenuItem.separator())
|
||||||
|
|
||||||
menu.addItem(withTitle: tr("macMenuQuitManagingTunnels"),
|
menu.addItem(withTitle: tr("macMenuQuit"),
|
||||||
action: #selector(NSWindow.performClose(_:)), keyEquivalent: "q")
|
action: #selector(AppDelegate.confirmAndQuit), keyEquivalent: "q")
|
||||||
|
|
||||||
return menu
|
return menu
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,25 @@
|
|||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
class LogViewCell: NSTextField {
|
class LogViewCell: NSTableCellView {
|
||||||
|
var text: String = "" {
|
||||||
|
didSet { textField?.stringValue = text }
|
||||||
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
super.init(frame: .zero)
|
super.init(frame: .zero)
|
||||||
isSelectable = false
|
|
||||||
isEditable = false
|
let textField = NSTextField(wrappingLabelWithString: "")
|
||||||
isBordered = false
|
addSubview(textField)
|
||||||
backgroundColor = .clear
|
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) {
|
required init?(coder: NSCoder) {
|
||||||
@@ -17,19 +29,19 @@ class LogViewCell: NSTextField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func prepareForReuse() {
|
override func prepareForReuse() {
|
||||||
stringValue = ""
|
textField?.stringValue = ""
|
||||||
preferredMaxLayoutWidth = 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LogViewTimestampCell: LogViewCell {
|
class LogViewTimestampCell: LogViewCell {
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
maximumNumberOfLines = 1
|
if let textField = textField {
|
||||||
lineBreakMode = .byClipping
|
textField.maximumNumberOfLines = 1
|
||||||
preferredMaxLayoutWidth = 0
|
textField.lineBreakMode = .byClipping
|
||||||
setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
|
textField.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
|
||||||
setContentHuggingPriority(.defaultLow, for: .vertical)
|
textField.setContentHuggingPriority(.defaultLow, for: .vertical)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
@@ -40,10 +52,12 @@ class LogViewTimestampCell: LogViewCell {
|
|||||||
class LogViewMessageCell: LogViewCell {
|
class LogViewMessageCell: LogViewCell {
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
maximumNumberOfLines = 0
|
if let textField = textField {
|
||||||
lineBreakMode = .byWordWrapping
|
textField.maximumNumberOfLines = 0
|
||||||
setContentCompressionResistancePriority(.required, for: .vertical)
|
textField.lineBreakMode = .byWordWrapping
|
||||||
setContentHuggingPriority(.required, for: .vertical)
|
textField.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||||
|
textField.setContentHuggingPriority(.required, for: .vertical)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ class LogViewController: NSViewController {
|
|||||||
])
|
])
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
containerView.widthAnchor.constraint(equalToConstant: 640),
|
containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: 640),
|
||||||
|
containerView.widthAnchor.constraint(lessThanOrEqualToConstant: 1200),
|
||||||
containerView.heightAnchor.constraint(greaterThanOrEqualToConstant: 240)
|
containerView.heightAnchor.constraint(greaterThanOrEqualToConstant: 240)
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -192,6 +193,10 @@ class LogViewController: NSViewController {
|
|||||||
updateLogEntriesTimer = nil
|
updateLogEntriesTimer = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewWillAppear() {
|
||||||
|
view.window?.setFrameAutosaveName(NSWindow.FrameAutosaveName("LogWindow"))
|
||||||
|
}
|
||||||
|
|
||||||
override func viewWillDisappear() {
|
override func viewWillDisappear() {
|
||||||
super.viewWillDisappear()
|
super.viewWillDisappear()
|
||||||
stopUpdatingLogEntries()
|
stopUpdatingLogEntries()
|
||||||
@@ -250,12 +255,11 @@ extension LogViewController: NSTableViewDelegate {
|
|||||||
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
||||||
if LogColumn.time.isRepresenting(tableColumn: tableColumn) {
|
if LogColumn.time.isRepresenting(tableColumn: tableColumn) {
|
||||||
let cell: LogViewTimestampCell = tableView.dequeueReusableCell()
|
let cell: LogViewTimestampCell = tableView.dequeueReusableCell()
|
||||||
cell.stringValue = logEntries[row].timestamp
|
cell.text = logEntries[row].timestamp
|
||||||
return cell
|
return cell
|
||||||
} else if LogColumn.logMessage.isRepresenting(tableColumn: tableColumn) {
|
} else if LogColumn.logMessage.isRepresenting(tableColumn: tableColumn) {
|
||||||
let cell: LogViewMessageCell = tableView.dequeueReusableCell()
|
let cell: LogViewMessageCell = tableView.dequeueReusableCell()
|
||||||
cell.stringValue = logEntries[row].message
|
cell.text = logEntries[row].message
|
||||||
cell.preferredMaxLayoutWidth = tableColumn?.width ?? 0
|
|
||||||
return cell
|
return cell
|
||||||
} else {
|
} else {
|
||||||
fatalError()
|
fatalError()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
private var handle: Int32?
|
private var handle: Int32?
|
||||||
private var networkMonitor: NWPathMonitor?
|
private var networkMonitor: NWPathMonitor?
|
||||||
private var ifname: String?
|
private var ifname: String?
|
||||||
private var lastSeenInterfaces: [String] = []
|
private var lastPath: Network.NWPath?
|
||||||
private var packetTunnelSettingsGenerator: PacketTunnelSettingsGenerator?
|
private var packetTunnelSettingsGenerator: PacketTunnelSettingsGenerator?
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@@ -143,18 +143,15 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
|
|
||||||
private func pathUpdate(path: Network.NWPath) {
|
private func pathUpdate(path: Network.NWPath) {
|
||||||
guard let handle = handle else { return }
|
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)")
|
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 os(iOS)
|
||||||
if let packetTunnelSettingsGenerator = packetTunnelSettingsGenerator {
|
if let packetTunnelSettingsGenerator = packetTunnelSettingsGenerator {
|
||||||
_ = packetTunnelSettingsGenerator.endpointUapiConfiguration().withGoString { return wgSetConfig(handle, $0) }
|
_ = packetTunnelSettingsGenerator.endpointUapiConfiguration().withGoString { return wgSetConfig(handle, $0) }
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
let interfaces = path.availableInterfaces.filter { $0.name != ifname }.compactMap { $0.name }
|
if path != lastPath {
|
||||||
if !interfaces.elementsEqual(lastSeenInterfaces) {
|
lastPath = path
|
||||||
lastSeenInterfaces = interfaces
|
|
||||||
wgBumpSockets(handle)
|
wgBumpSockets(handle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export CGO_ENABLED := 1
|
|||||||
build: $(DESTDIR)/libwg-go.a
|
build: $(DESTDIR)/libwg-go.a
|
||||||
version-header: $(DESTDIR)/wireguard-go-version.h
|
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)
|
GOBUILDVERSION_CURRENT := $(shell go version 2>/dev/null)
|
||||||
export REAL_GOROOT := $(shell go env GOROOT 2>/dev/null)
|
export REAL_GOROOT := $(shell go env GOROOT 2>/dev/null)
|
||||||
export GOROOT := $(BUILDDIR)/goroot
|
export GOROOT := $(BUILDDIR)/goroot
|
||||||
|
|||||||
Reference in New Issue
Block a user