]> git.ipfire.org Git - thirdparty/wireguard-apple.git/commitdiff
Finish trampoline code.
authorJeroen Leenarts <jeroen.leenarts@gmail.com>
Fri, 3 Aug 2018 20:24:41 +0000 (22:24 +0200)
committerJeroen Leenarts <jeroen.leenarts@gmail.com>
Fri, 3 Aug 2018 20:24:41 +0000 (22:24 +0200)
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
WireGuardNetworkExtension/PacketTunnelProvider.swift
WireGuardNetworkExtension/WireGuardGoWrapper.h
WireGuardNetworkExtension/WireGuardGoWrapper.m
WireGuardNetworkExtension/WireGuardNetworkExtension-Bridging-Header.h
wireguard-go-bridge/wireguard.h

index f5ba60aad846611d57de5068ed62bbb4e8d284f8..4b282ac5b58dd9dea1d91544f78ab052e4b8fc10 100644 (file)
@@ -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)
     }
 }
index 51a88bd37f6c37a5b28d3c1464efc431bcee3f3a..b9038b477edf7e1868396be93511fd46520f82b4 100644 (file)
@@ -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
index f15e34ebeaac8c9ae1df50c37fa99a6b57637b19..a24a2396a8a46c41358d1529637c6597caa16fce 100644 (file)
@@ -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;
 }
 
index cfbb25808b9082c71e7ac58b571f154847864d17..c67781081b1d2a93eb29fcf8578cda89ae716260 100644 (file)
@@ -3,3 +3,4 @@
 //
 
 #import "WireGuardGoWrapper.h"
+#include "wireguard.h"
index 483d564a6eb9bedbcad76eaa77d85ce9f31c6a2c..d009f7208325b701362964f8516e357499b808ac 100644 (file)
@@ -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