Skip to content

Commit

Permalink
Merge pull request #29 from mysteriumnetwork/windows [major]
Browse files Browse the repository at this point in the history
Windows wireguard service support
  • Loading branch information
tadaskay committed Jul 21, 2023
2 parents 7478aae + 65a2d23 commit b1954f3
Show file tree
Hide file tree
Showing 22 changed files with 703 additions and 55 deletions.
2 changes: 2 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BasedOnStyle: Google
ColumnLimit: 120
81 changes: 80 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,84 @@
"dart.lineLength": 150,
"[dart]": {
"editor.rulers": [150]
}
},
"files.insertFinalNewline": true,
"files.associations": {
"xstring": "cpp",
"iostream": "cpp",
"algorithm": "cpp",
"any": "cpp",
"atomic": "cpp",
"bit": "cpp",
"cctype": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"exception": "cpp",
"format": "cpp",
"forward_list": "cpp",
"functional": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"list": "cpp",
"locale": "cpp",
"map": "cpp",
"memory": "cpp",
"mutex": "cpp",
"new": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"set": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"string": "cpp",
"system_error": "cpp",
"thread": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"utility": "cpp",
"variant": "cpp",
"vector": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xstddef": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp",
"array": "cpp",
"coroutine": "cpp",
"codecvt": "cpp",
"*.rh": "cpp"
},
"C_Cpp.clang_format_fallbackStyle": "Google",
"C_Cpp.clang_format_path": ""
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A flutter plugin to setup and control VPN connection via [Wireguard](https://www

| | Android | iOS | Linux | macOS | Windows |
|-------------|---------|-------|-------|-------|-------------|
| **Support** | 21+ | 15.0+ | TBD | 12+ | TBD |
| **Support** | 21+ | 15.0+ | TBD | 12+ | 10+ |

## Usage

Expand Down
37 changes: 36 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';
import 'dart:developer' as developer;
import 'dart:isolate';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Expand All @@ -9,6 +10,22 @@ void main() {
runApp(const MyApp());
}

void nativeInitBackground(List<Object> args) async {
final rootIsolateToken = args[0] as RootIsolateToken;
BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);

try {
await WireguardDart().nativeInit();
debugPrint('Native init done');
} catch (e) {
debugPrint('Native init error');
developer.log(
'Native init',
error: e.toString(),
);
}
}

class MyApp extends StatefulWidget {
const MyApp({super.key});

Expand Down Expand Up @@ -57,9 +74,14 @@ class _MyAppState extends State<MyApp> {
});
}

void nativeInit() async {
RootIsolateToken rootIsolateToken = RootIsolateToken.instance!;
Isolate.spawn(nativeInitBackground, [rootIsolateToken]);
}

void setupTunnel() async {
try {
await _wireguardDartPlugin.setupTunnel(bundleId: "mysterium");
await _wireguardDartPlugin.setupTunnel(bundleId: "mysterium", win32ServiceName: "MysteriumVPN_Wireguard");
debugPrint("Setup tunnel success");
} catch (e) {
developer.log(
Expand Down Expand Up @@ -121,6 +143,19 @@ class _MyAppState extends State<MyApp> {
),
),
const SizedBox(height: 20),
TextButton(
onPressed: nativeInit,
style: ButtonStyle(
minimumSize: MaterialStateProperty.all<Size>(const Size(100, 50)),
padding: MaterialStateProperty.all(const EdgeInsets.fromLTRB(20, 15, 20, 15)),
backgroundColor: MaterialStateProperty.all<Color>(Colors.blueAccent),
overlayColor: MaterialStateProperty.all<Color>(Colors.white.withOpacity(0.1))),
child: const Text(
'Native initialization',
style: TextStyle(color: Colors.white),
),
),
const SizedBox(height: 20),
TextButton(
onPressed: setupTunnel,
style: ButtonStyle(
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Demonstrates how to use the wireguard_dart plugin.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

environment:
sdk: '>=2.18.4 <3.0.0'
sdk: '>=2.19.0 <3.0.0'

# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
Expand Down
8 changes: 6 additions & 2 deletions lib/wireguard_dart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ class WireguardDart {
return WireguardDartPlatform.instance.generateKeyPair();
}

Future<void> setupTunnel({required String bundleId}) {
return WireguardDartPlatform.instance.setupTunnel(bundleId: bundleId);
Future<void> nativeInit() {
return WireguardDartPlatform.instance.nativeInit();
}

Future<void> setupTunnel({required String bundleId, String? win32ServiceName}) {
return WireguardDartPlatform.instance.setupTunnel(bundleId: bundleId, win32ServiceName: win32ServiceName);
}

Future<void> connect({required String cfg}) {
Expand Down
13 changes: 11 additions & 2 deletions lib/wireguard_dart_method_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,17 @@ class MethodChannelWireguardDart extends WireguardDartPlatform {
}

@override
Future<void> setupTunnel({required String bundleId}) async {
await methodChannel.invokeMethod<void>('setupTunnel', {'bundleId': bundleId});
Future<void> nativeInit() async {
await methodChannel.invokeMethod<void>('nativeInit');
}

@override
Future<void> setupTunnel({required String bundleId, String? win32ServiceName}) async {
var args = {
'bundleId': bundleId,
if (win32ServiceName != null) 'win32ServiceName': win32ServiceName,
};
await methodChannel.invokeMethod<void>('setupTunnel', args);
}

@override
Expand Down
6 changes: 5 additions & 1 deletion lib/wireguard_dart_platform_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ abstract class WireguardDartPlatform extends PlatformInterface {
throw UnimplementedError('generateKeyPair() has not been implemented');
}

Future<void> setupTunnel({required String bundleId}) {
Future<void> nativeInit() {
throw UnimplementedError('nativeInit() has not been implemented');
}

Future<void> setupTunnel({required String bundleId, String? win32ServiceName}) {
throw UnimplementedError('setupTunnel() has not been implemented');
}

Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ homepage: https://github.com/mysteriumnetwork/wireguard_dart
repository: https://github.com/mysteriumnetwork/wireguard_dart

environment:
sdk: '>=2.18.4 <3.0.0'
sdk: '>=2.19.0 <3.0.0'
flutter: ">=2.5.0"

dependencies:
Expand Down
6 changes: 5 additions & 1 deletion test/wireguard_dart_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import 'package:wireguard_dart/wireguard_dart_platform_interface.dart';
import 'package:wireguard_dart/wireguard_dart.dart';

class MockWireguardDartPlatform with MockPlatformInterfaceMixin implements WireguardDartPlatform {

@override
Future<void> nativeInit() => Future.value();

@override
Future<void> setupTunnel({required String bundleId}) => Future.value();
Future<void> setupTunnel({required String bundleId, String? win32ServiceName}) => Future.value();

@override
Future<void> connect({required String cfg}) => Future.value();
Expand Down
9 changes: 9 additions & 0 deletions windows/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ set(PLUGIN_NAME "wireguard_dart_plugin")
list(APPEND PLUGIN_SOURCES
"wireguard_dart_plugin.cpp"
"wireguard_dart_plugin.h"
"key_generator.cpp"
"key_generator.h"
"config_writer.cpp"
"config_writer.h"
"service_control.cpp"
"service_control.h"
"utils.cpp"
"utils.h"
)

# Define the plugin library target. Its name must not be changed (see comment
Expand Down Expand Up @@ -80,5 +88,6 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)
set(wireguard_dart_bundled_libraries
"${CMAKE_CURRENT_SOURCE_DIR}/lib/wireguard/amd64/wireguard.dll"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/tunnel/amd64/tunnel.dll"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/wireguard_svc/amd64/wireguard_svc.exe"
PARENT_SCOPE
)
39 changes: 39 additions & 0 deletions windows/config_writer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <windows.h>

#include <codecvt>
#include <stdexcept>
#include <string>

namespace wireguard_dart {

std::wstring WriteConfigToTempFile(std::string config) {
WCHAR temp_path[MAX_PATH];
DWORD temp_path_len = GetTempPath(MAX_PATH, temp_path);
if (temp_path_len > MAX_PATH || temp_path_len == 0) {
throw std::runtime_error("could not get temporary dir: " + GetLastError());
}

WCHAR temp_filename[MAX_PATH];
UINT temp_filename_result = GetTempFileName(temp_path, L"wg_conf", 0, temp_filename);
wcscat_s(temp_filename, L".conf");
if (temp_filename_result == 0) {
throw std::runtime_error("could not get temporary file name: " + GetLastError());
}

HANDLE temp_file = CreateFile(temp_filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (temp_file == INVALID_HANDLE_VALUE) {
throw std::runtime_error("unable to create temporary file: " + GetLastError());
}

DWORD bytes_written;
if (!WriteFile(temp_file, config.c_str(), static_cast<DWORD>(config.length()), &bytes_written, NULL)) {
throw std::runtime_error("could not write temporary config file:" + GetLastError());
}

if (!CloseHandle(temp_file)) {
throw std::runtime_error("unable to close temporary file:" + GetLastError());
}
return temp_filename;
}

}
7 changes: 7 additions & 0 deletions windows/config_writer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <string>

namespace wireguard_dart {

std::wstring WriteConfigToTempFile(std::string config);

}
29 changes: 29 additions & 0 deletions windows/key_generator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <string>
#include <utility>

#include "libbase64.h"
#include "tunnel.h"

namespace wireguard_dart {

const size_t kKeyLen = 32;
const size_t kBase64BufferSize = kKeyLen * 2; // Min size = src * 4/3 https://github.com/aklomp/base64#base64_encode

std::pair<std::string, std::string> GenerateKeyPair() {
char public_key_bytes[kKeyLen];
char private_key_bytes[kKeyLen];
WireGuardGenerateKeypair((unsigned char *)public_key_bytes, (unsigned char *)private_key_bytes);

char b64_buf[kBase64BufferSize];
size_t b64_output_len;

base64_encode(public_key_bytes, kKeyLen, b64_buf, &b64_output_len, 0);
const std::string public_key_b64(b64_buf, 0, b64_output_len);

base64_encode(private_key_bytes, kKeyLen, b64_buf, &b64_output_len, 0);
const std::string private_key_b64(b64_buf, 0, b64_output_len);

return std::make_pair(public_key_b64, private_key_b64);
}

} // namespace wireguard_dart
13 changes: 13 additions & 0 deletions windows/key_generator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef WIREGUARD_DART_KEY_GENERATOR_H
#define WIREGUARD_DART_KEY_GENERATOR_H

#include <string>
#include <utility>

namespace wireguard_dart {

std::pair<std::string, std::string> GenerateKeyPair();

}

#endif
Binary file added windows/lib/wireguard_svc/amd64/wireguard_svc.exe
Binary file not shown.
Loading

0 comments on commit b1954f3

Please sign in to comment.