├── ToyVpn ├── pch.cpp ├── App.idl ├── Assets │ ├── StoreLogo.png │ ├── SplashScreen.scale-200.png │ ├── LockScreenLogo.scale-200.png │ ├── Square150x150Logo.scale-200.png │ ├── Square44x44Logo.scale-200.png │ ├── Wide310x150Logo.scale-200.png │ └── Square44x44Logo.targetsize-24_altform-unplated.png ├── MainPage.idl ├── packages.config ├── App.xaml ├── App.h ├── pch.h ├── MainPage.h ├── readme.txt ├── MainPage.xaml ├── ToyVpn.vcxproj.filters ├── Package.appxmanifest ├── MainPage.cpp ├── App.cpp └── ToyVpn.vcxproj ├── ToyVpnBG ├── pch.cpp ├── ToyVpnBG.def ├── packages.config ├── VpnBackgroundTask.idl ├── VpnBackgroundTask.h ├── pch.h ├── VpnBackgroundTask.cpp ├── readme.txt ├── ToyVpnBG.vcxproj.filters ├── VpnPlugin.h ├── VpnPlugin.cpp └── ToyVpnBG.vcxproj ├── README.md ├── LICENSE ├── strutil.h ├── ToyVpn.sln └── .gitignore /ToyVpn/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /ToyVpnBG/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /ToyVpn/App.idl: -------------------------------------------------------------------------------- 1 | namespace ToyVpn 2 | { 3 | } 4 | -------------------------------------------------------------------------------- /ToyVpn/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysc3839/UWPToyVpn/HEAD/ToyVpn/Assets/StoreLogo.png -------------------------------------------------------------------------------- /ToyVpn/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysc3839/UWPToyVpn/HEAD/ToyVpn/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /ToyVpn/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysc3839/UWPToyVpn/HEAD/ToyVpn/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /ToyVpn/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysc3839/UWPToyVpn/HEAD/ToyVpn/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /ToyVpn/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysc3839/UWPToyVpn/HEAD/ToyVpn/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /ToyVpn/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysc3839/UWPToyVpn/HEAD/ToyVpn/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /ToyVpnBG/ToyVpnBG.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE 3 | DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE 4 | -------------------------------------------------------------------------------- /ToyVpn/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysc3839/UWPToyVpn/HEAD/ToyVpn/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /ToyVpn/MainPage.idl: -------------------------------------------------------------------------------- 1 | namespace ToyVpn 2 | { 3 | [default_interface] 4 | runtimeclass MainPage : Windows.UI.Xaml.Controls.Page 5 | { 6 | MainPage(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ToyVpn/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ToyVpnBG/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ToyVpnBG/VpnBackgroundTask.idl: -------------------------------------------------------------------------------- 1 | namespace ToyVpnBG 2 | { 3 | [default_interface] 4 | runtimeclass VpnBackgroundTask : Windows.ApplicationModel.Background.IBackgroundTask 5 | { 6 | VpnBackgroundTask(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ToyVpn/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UWPToyVpn 2 | UWPToyVpn is a sample application that shows how to build a VPN client using the [Windows.Networking.Vpn](https://docs.microsoft.com/en-us/uwp/api/Windows.Networking.Vpn) class. 3 | 4 | It was inspired by Android's [ToyVpn](https://android.googlesource.com/platform/development/+/master/samples/ToyVpn). 5 | 6 | The server-side implementation is compatible with [ToyVpn's](https://android.googlesource.com/platform/development/+/master/samples/ToyVpn/server/linux). 7 | -------------------------------------------------------------------------------- /ToyVpn/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "App.xaml.g.h" 3 | 4 | namespace winrt::ToyVpn::implementation 5 | { 6 | struct App : AppT 7 | { 8 | App(); 9 | 10 | void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const&); 11 | void OnSuspending(IInspectable const&, Windows::ApplicationModel::SuspendingEventArgs const&); 12 | void OnNavigationFailed(IInspectable const&, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs const&); 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /ToyVpnBG/VpnBackgroundTask.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VpnBackgroundTask.g.h" 4 | 5 | namespace winrt::ToyVpnBG::implementation 6 | { 7 | struct VpnBackgroundTask : VpnBackgroundTaskT 8 | { 9 | VpnBackgroundTask() = default; 10 | 11 | void Run(Windows::ApplicationModel::Background::IBackgroundTaskInstance const& taskInstance); 12 | }; 13 | } 14 | 15 | namespace winrt::ToyVpnBG::factory_implementation 16 | { 17 | struct VpnBackgroundTask : VpnBackgroundTaskT 18 | { 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /ToyVpnBG/pch.h: -------------------------------------------------------------------------------- 1 | // 2 | // pch.h 3 | // Header for platform projection include files 4 | // 5 | 6 | #pragma once 7 | 8 | #define WIN32_LEAN_AND_MEAN 9 | //#include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | -------------------------------------------------------------------------------- /ToyVpn/pch.h: -------------------------------------------------------------------------------- 1 | // 2 | // pch.h 3 | // Header for platform projection include files 4 | // 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | -------------------------------------------------------------------------------- /ToyVpnBG/VpnBackgroundTask.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "VpnBackgroundTask.h" 3 | #include "VpnPlugin.h" 4 | 5 | using namespace winrt; 6 | using namespace Windows::ApplicationModel::Core; 7 | 8 | namespace winrt::ToyVpnBG::implementation 9 | { 10 | void VpnBackgroundTask::Run(Windows::ApplicationModel::Background::IBackgroundTaskInstance const& taskInstance) 11 | { 12 | auto deferral = taskInstance.GetDeferral(); 13 | try 14 | { 15 | hstring pluginId{ L"ToyVpnPlugin" }; 16 | 17 | IInspectable plugin; 18 | if (CoreApplication::Properties().HasKey(pluginId)) 19 | { 20 | plugin = CoreApplication::Properties().Lookup(pluginId); 21 | } 22 | else 23 | { 24 | plugin = make(); 25 | CoreApplication::Properties().Insert(pluginId, plugin); 26 | } 27 | 28 | Windows::Networking::Vpn::VpnChannel::ProcessEventAsync(plugin, taskInstance.TriggerDetails()); 29 | } 30 | catch (winrt::hresult_error const&) 31 | { 32 | } 33 | deferral.Complete(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ToyVpn/MainPage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Declaration of the MainPage class. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "MainPage.g.h" 8 | 9 | namespace winrt::ToyVpn::implementation 10 | { 11 | struct MainPage : MainPageT 12 | { 13 | MainPage(); 14 | 15 | void LaunchVPNSettings(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); 16 | Windows::Foundation::IAsyncAction SaveVPN(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); 17 | Windows::Foundation::IAsyncAction ConnectVPN(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); 18 | Windows::Foundation::IAsyncAction DisconnectVPN(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); 19 | 20 | private: 21 | void LoadSettings(); 22 | void SaveSettings(); 23 | }; 24 | } 25 | 26 | namespace winrt::ToyVpn::factory_implementation 27 | { 28 | struct MainPage : MainPageT 29 | { 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 ysc3839 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ToyVpn/readme.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | C++/WinRT ToyVpn Project Overview 3 | ======================================================================== 4 | 5 | This project demonstrates how to get started writing XAML apps directly 6 | with standard C++, using the C++/WinRT SDK component and XAML compiler 7 | support to generate implementation headers from interface (IDL) files. 8 | These headers can then be used to implement the local Windows Runtime 9 | classes referenced in the app's XAML pages. 10 | 11 | Steps: 12 | 1. Create an interface (IDL) file to define any local Windows Runtime 13 | classes referenced in the app's XAML pages. 14 | 2. Build the project once to generate implementation templates under 15 | the "Generated Files" folder, as well as skeleton class definitions 16 | under "Generated Files\sources". 17 | 3. Use the skeleton class definitions for reference to implement your 18 | Windows Runtime classes. 19 | 20 | ======================================================================== 21 | Learn more about C++/WinRT here: 22 | http://aka.ms/cppwinrt/ 23 | ======================================================================== 24 | -------------------------------------------------------------------------------- /strutil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void rtrimwsv(std::wstring_view& sv) 4 | { 5 | size_t end = sv.find_last_not_of(L' '); 6 | if (end != std::wstring_view::npos) 7 | sv.remove_suffix(sv.size() - end - 1); 8 | } 9 | 10 | // https://www.bfilipek.com/2018/07/string-view-perf-followup.html 11 | std::vector splitwsv(std::wstring_view strv, wchar_t delim = L' ') 12 | { 13 | std::vector output; 14 | size_t first = 0; 15 | 16 | while (first < strv.size()) 17 | { 18 | const auto second = strv.find_first_of(delim, first); 19 | 20 | if (first != second) 21 | output.emplace_back(strv.substr(first, second - first)); 22 | 23 | if (second == std::string_view::npos) 24 | break; 25 | 26 | first = second + 1; 27 | } 28 | 29 | return output; 30 | } 31 | 32 | std::vector splitws(std::wstring_view strv, wchar_t delim = L' ') 33 | { 34 | std::vector output; 35 | size_t first = 0; 36 | 37 | while (first < strv.size()) 38 | { 39 | const auto second = strv.find_first_of(delim, first); 40 | 41 | if (first != second) 42 | output.emplace_back(strv.substr(first, second - first)); 43 | 44 | if (second == std::string_view::npos) 45 | break; 46 | 47 | first = second + 1; 48 | } 49 | 50 | return output; 51 | } 52 | -------------------------------------------------------------------------------- /ToyVpnBG/readme.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | C++/WinRT ToyVpnBG Project Overview 3 | ======================================================================== 4 | 5 | This project demonstrates how to get started authoring Windows Runtime 6 | classes directly with standard C++, using the C++/WinRT SDK component 7 | to generate implementation headers from interface (IDL) files. The 8 | generated Windows Runtime component binary and WinMD files should then 9 | be bundled with the Universal Windows Platform (UWP) app consuming them. 10 | 11 | Steps: 12 | 1. Create an interface (IDL) file to define your Windows Runtime class, 13 | its default interface, and any other interfaces it implements. 14 | 2. Build the project once to generate module.g.cpp, module.h.cpp, and 15 | implementation templates under the "Generated Files" folder, as 16 | well as skeleton class definitions under "Generated Files\sources". 17 | 3. Use the skeleton class definitions for reference to implement your 18 | Windows Runtime classes. 19 | 20 | ======================================================================== 21 | Learn more about C++/WinRT here: 22 | http://aka.ms/cppwinrt/ 23 | ======================================================================== 24 | -------------------------------------------------------------------------------- /ToyVpnBG/ToyVpnBG.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | accd3aa8-1ba0-4223-9bbe-0c431709210b 6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms 7 | 8 | 9 | {926ab91d-31b4-48c3-b9a4-e681349f27f0} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ToyVpnBG/VpnPlugin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace winrt::ToyVpnBG::implementation 4 | { 5 | enum HandshakeState 6 | { 7 | Waiting, 8 | Received, 9 | Canceled 10 | }; 11 | 12 | struct VpnPlugin : implements 13 | { 14 | VpnPlugin() = default; 15 | 16 | void Connect(Windows::Networking::Vpn::VpnChannel const& channel); 17 | void Disconnect(Windows::Networking::Vpn::VpnChannel const& channel); 18 | void GetKeepAlivePayload(Windows::Networking::Vpn::VpnChannel const& channel, Windows::Networking::Vpn::VpnPacketBuffer& keepAlivePacket); 19 | void Encapsulate(Windows::Networking::Vpn::VpnChannel const& channel, Windows::Networking::Vpn::VpnPacketBufferList const& packets, Windows::Networking::Vpn::VpnPacketBufferList const& encapulatedPackets); 20 | void Decapsulate(Windows::Networking::Vpn::VpnChannel const& channel, Windows::Networking::Vpn::VpnPacketBuffer const& encapBuffer, Windows::Networking::Vpn::VpnPacketBufferList const& decapsulatedPackets, Windows::Networking::Vpn::VpnPacketBufferList const& controlPacketsToSend); 21 | 22 | private: 23 | void Handshake(Windows::Networking::Sockets::DatagramSocket const& tunnel, std::atomic const& handshakeState, std::wstring const& secret); 24 | void Configure(Windows::Networking::Vpn::VpnChannel const& channel, hstring const& parametershs); 25 | }; 26 | 27 | struct VpnPluginContext : implements 28 | { 29 | friend struct VpnPlugin; 30 | 31 | VpnPluginContext() = default; 32 | 33 | private: 34 | std::atomic handshakeState{ Waiting }; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /ToyVpn/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |