aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WireGuardNetworkExtension/PacketTunnelProvider.swift61
-rw-r--r--WireGuardNetworkExtension/WireGuardGoWrapper.h5
-rw-r--r--WireGuardNetworkExtension/WireGuardGoWrapper.m48
-rw-r--r--WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h1
-rw-r--r--wireguard-go-bridge/wireguard.h2
5 files changed, 79 insertions, 38 deletions
diff --git a/WireGuardNetworkExtension/PacketTunnelProvider.swift b/WireGuardNetworkExtension/PacketTunnelProvider.swift
index f5ba60a..4b282ac 100644
--- a/WireGuardNetworkExtension/PacketTunnelProvider.swift
+++ b/WireGuardNetworkExtension/PacketTunnelProvider.swift
@@ -9,54 +9,57 @@
import NetworkExtension
import os.log
+enum PacketTunnelProviderError: Error {
+ case tunnelSetupFailed
+}
+
+/// A packet tunnel provider object.
class PacketTunnelProvider: NEPacketTunnelProvider {
+
+ // MARK: Properties
+
+ /// A reference to the WireGuard wrapper object.
let wireGuardWrapper = WireGuardGoWrapper()
- private let tunnelQueue = DispatchQueue(label: PacketTunnelProvider.description())
+ /// The completion handler to call when the tunnel is fully established.
+ var pendingStartCompletion: ((Error?) -> Void)?
+
+ /// The completion handler to call when the tunnel is fully disconnected.
+ var pendingStopCompletion: (() -> Void)?
- //TODO create a way to transfer config into extension
+ // MARK: NEPacketTunnelProvider
+ /// Begin the process of establishing the tunnel.
override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) {
os_log("Starting tunnel", log: Log.general, type: .info)
- // Add code here to start the process of connecting the tunnel.
- //TODO get a settings string in here.
- tunnelQueue.sync {
- wireGuardWrapper.turnOn(withInterfaceName: "TODO", settingsString: "TODO")
+ //TODO tunnel settings
+ if wireGuardWrapper.turnOn(withInterfaceName: "test", settingsString: "") {
+ // Success
+ completionHandler(nil)
+ } else {
+ completionHandler(PacketTunnelProviderError.tunnelSetupFailed)
}
}
+ /// Begin the process of stopping the tunnel.
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
os_log("Stopping tunnel", log: Log.general, type: .info)
- // Add code here to start the process of stopping the tunnel.
- tunnelQueue.sync {
- wireGuardWrapper.turnOff()
- }
+
+ wireGuardWrapper.turnOff()
completionHandler()
}
+ /// Handle IPC messages from the app.
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
- // Add code here to handle the message.
- if let handler = completionHandler {
- handler(messageData)
- }
- }
-
- private func loopReadPackets(_ handler: @escaping ([Data]?, Error?) -> Void) {
- packetFlow.readPackets { [weak self] (_, _) in
- // TODO write packets into the tunnel
- self?.loopReadPackets(handler)
+ guard let messageString = NSString(data: messageData, encoding: String.Encoding.utf8.rawValue) else {
+ completionHandler?(nil)
+ return
}
- }
- func writePacket(_ packet: Data, completionHandler: ((Error?) -> Void)?) {
- packetFlow.writePackets([packet], withProtocols: [AF_INET] as [NSNumber])
- completionHandler?(nil)
- }
+ os_log("Got a message from the app: %s", log: Log.general, type: .info, messageString)
- func writePackets(_ packets: [Data], completionHandler: ((Error?) -> Void)?) {
- let protocols = [Int32](repeating: AF_INET, count: packets.count) as [NSNumber]
- packetFlow.writePackets(packets, withProtocols: protocols)
- completionHandler?(nil)
+ let responseData = "Hello app".data(using: String.Encoding.utf8)
+ completionHandler?(responseData)
}
}
diff --git a/WireGuardNetworkExtension/WireGuardGoWrapper.h b/WireGuardNetworkExtension/WireGuardGoWrapper.h
index 51a88bd..b9038b4 100644
--- a/WireGuardNetworkExtension/WireGuardGoWrapper.h
+++ b/WireGuardNetworkExtension/WireGuardGoWrapper.h
@@ -7,10 +7,13 @@
//
#import <Foundation/Foundation.h>
+#import <NetworkExtension/NetworkExtension.h>
@interface WireGuardGoWrapper : NSObject
-- (void) turnOnWithInterfaceName: (NSString *)interfaceName settingsString: (NSString *)settingsString;
+@property (nonatomic, weak) NEPacketTunnelFlow *packetFlow;
+
+- (BOOL) turnOnWithInterfaceName: (NSString *)interfaceName settingsString: (NSString *)settingsString;
- (void) turnOff;
@end
diff --git a/WireGuardNetworkExtension/WireGuardGoWrapper.m b/WireGuardNetworkExtension/WireGuardGoWrapper.m
index f15e34e..a24a239 100644
--- a/WireGuardNetworkExtension/WireGuardGoWrapper.m
+++ b/WireGuardNetworkExtension/WireGuardGoWrapper.m
@@ -6,10 +6,10 @@
// Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All rights reserved.
//
-#import "WireGuardGoWrapper.h"
-
#include <os/log.h>
+
#include "wireguard.h"
+#import "WireGuardGoWrapper.h"
/// Trampoline function
static ssize_t do_read(const void *ctx, const unsigned char *buf, size_t len);
@@ -24,12 +24,25 @@ static void do_log(int level, const char *tag, const char *msg);
@property (nonatomic, assign) int handle;
@property (nonatomic, assign) BOOL isClosed;
+@property (nonatomic, strong) NSMutableArray<NSData *> *packets;
+@property (nonatomic, strong) NSMutableArray<NSNumber *> *protocols;
+
+@property (nonatomic, strong) NSCondition *condition;
@end
@implementation WireGuardGoWrapper
-- (void) turnOnWithInterfaceName: (NSString *)interfaceName settingsString: (NSString *)settingsString
+- (instancetype)init
+{
+ self = [super init];
+ if (self) {
+ self.condition = [NSCondition new];
+ }
+ return self;
+}
+
+- (BOOL) turnOnWithInterfaceName: (NSString *)interfaceName settingsString: (NSString *)settingsString
{
wgSetLogger(do_log);
@@ -38,6 +51,8 @@ static void do_log(int level, const char *tag, const char *msg);
const char * settings = [settingsString UTF8String];
self.handle = wgTurnOn((gostring_t){ .p = ifName, .n = interfaceName.length }, (gostring_t){ .p = settings, .n = settingsString.length }, do_read, do_write, (__bridge void *)(self));
+
+ return self.handle > 0;
}
- (void) turnOff
@@ -61,16 +76,35 @@ static void do_log(int level, const char *tag, const char *msg);
static ssize_t do_read(const void *ctx, const unsigned char *buf, size_t len)
{
WireGuardGoWrapper *wrapper = (__bridge WireGuardGoWrapper *)ctx;
- printf("Reading from instance with ctx %p into buffer %p of length %zu\n", ctx, buf, len);
- sleep(1);
- // TODO received data from tunnel, write to Packetflow
+ if (wrapper.packets.count == 0) {
+
+ [wrapper.packetFlow readPacketsWithCompletionHandler:^(NSArray<NSData *> * _Nonnull packets, NSArray<NSNumber *> * _Nonnull protocols) {
+ [wrapper.packets addObjectsFromArray:packets];
+ [wrapper.protocols addObjectsFromArray:protocols];
+ // TODO make sure that the completion handler and the do_read are not performed on the same thread.
+ [wrapper.condition signal];
+ }];
+ [wrapper.condition wait];
+ }
+
+ NSData *packet = [wrapper.packets objectAtIndex:0];
+// NSNumber *protocol = [wrapper.protocols objectAtIndex:0];
+ [wrapper.packets removeObjectAtIndex:0];
+ [wrapper.protocols removeObjectAtIndex:0];
+
+ len = [packet length];
+ buf = (Byte*)malloc(len);
+ memcpy(buf, [packet bytes], len);
+
return wrapper.isClosed ? -1 : 0;
}
static ssize_t do_write(const void *ctx, const unsigned char *buf, size_t len)
{
WireGuardGoWrapper *wrapper = (__bridge WireGuardGoWrapper *)ctx;
- printf("Writing from instance with ctx %p into buffer %p of length %zu\n", ctx, buf, len);
+ //TODO: determine IPv4 or IPv6 status.
+ NSData *packet = [[NSData alloc] initWithBytes:buf length:len];
+ [wrapper.packetFlow writePackets:@[packet] withProtocols:@[@AF_INET]];
return len;
}
diff --git a/WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h b/WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h
index cfbb258..c677810 100644
--- a/WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h
+++ b/WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h
@@ -3,3 +3,4 @@
//
#import "WireGuardGoWrapper.h"
+#include "wireguard.h"
diff --git a/wireguard-go-bridge/wireguard.h b/wireguard-go-bridge/wireguard.h
index 483d564..d009f72 100644
--- a/wireguard-go-bridge/wireguard.h
+++ b/wireguard-go-bridge/wireguard.h
@@ -14,6 +14,6 @@ typedef void(*logger_fn_t)(int level, const char *tag, const char *msg);
extern void wgSetLogger(logger_fn_t logger_fn);
extern int wgTurnOn(gostring_t ifname, gostring_t settings, read_write_fn_t read_fn, read_write_fn_t write_fn, void *ctx);
extern void wgTurnOff(int handle);
-extern char *wgVersion();
+extern char *wgVersion(void);
#endif