commit e572273de917a5eb88cb6ca1fb51eb79cee586f4 Author: MrMelon Date: Tue Sep 22 23:10:16 2020 +0100 MelonVPN base commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0a34cab --- /dev/null +++ b/.gitignore @@ -0,0 +1,373 @@ +# Just throw the Visual Studio and Mono Develop gitignores in the same file and hope for the best + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +#User Specific +*.userprefs +*.usertasks + +#Mono Project Files +*.pidb +*.resources +test-results/ diff --git a/MelonVPN.sln b/MelonVPN.sln new file mode 100644 index 0000000..7aecf46 --- /dev/null +++ b/MelonVPN.sln @@ -0,0 +1,42 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MelonVPNClient", "MelonVPNClient\MelonVPNClient.csproj", "{071B91A9-6C1D-4A80-98EA-5077E4F66468}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MelonVPNDaemon", "MelonVPNDaemon\MelonVPNDaemon.csproj", "{AFF161B8-AF8E-4A16-9AA4-B692EB0D838E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MelonVPNCore", "MelonVPNCore\MelonVPNCore.csproj", "{B2F2F96C-3E5D-4176-9D66-479F357BC078}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MelonVPNConnectedClientUpdate", "MelonVPNConnectedClientUpdate\MelonVPNConnectedClientUpdate.csproj", "{B318A58E-028B-43A2-A753-2D7FBCA4EE40}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {071B91A9-6C1D-4A80-98EA-5077E4F66468}.Debug|x86.ActiveCfg = Debug|x86 + {071B91A9-6C1D-4A80-98EA-5077E4F66468}.Debug|x86.Build.0 = Debug|x86 + {071B91A9-6C1D-4A80-98EA-5077E4F66468}.Release|x86.ActiveCfg = Release|x86 + {071B91A9-6C1D-4A80-98EA-5077E4F66468}.Release|x86.Build.0 = Release|x86 + {AFF161B8-AF8E-4A16-9AA4-B692EB0D838E}.Debug|x86.ActiveCfg = Debug|x86 + {AFF161B8-AF8E-4A16-9AA4-B692EB0D838E}.Debug|x86.Build.0 = Debug|x86 + {AFF161B8-AF8E-4A16-9AA4-B692EB0D838E}.Release|x86.ActiveCfg = Release|x86 + {AFF161B8-AF8E-4A16-9AA4-B692EB0D838E}.Release|x86.Build.0 = Release|x86 + {B2F2F96C-3E5D-4176-9D66-479F357BC078}.Debug|x86.ActiveCfg = Debug|x86 + {B2F2F96C-3E5D-4176-9D66-479F357BC078}.Debug|x86.Build.0 = Debug|x86 + {B2F2F96C-3E5D-4176-9D66-479F357BC078}.Release|x86.ActiveCfg = Release|x86 + {B2F2F96C-3E5D-4176-9D66-479F357BC078}.Release|x86.Build.0 = Release|x86 + {B318A58E-028B-43A2-A753-2D7FBCA4EE40}.Debug|x86.ActiveCfg = Debug|x86 + {B318A58E-028B-43A2-A753-2D7FBCA4EE40}.Debug|x86.Build.0 = Debug|x86 + {B318A58E-028B-43A2-A753-2D7FBCA4EE40}.Release|x86.ActiveCfg = Release|x86 + {B318A58E-028B-43A2-A753-2D7FBCA4EE40}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + Policies = $0 + $0.DotNetNamingPolicy = $1 + $1.DirectoryNamespaceAssociation = PrefixedHierarchical + $0.StandardHeader = $2 + version = 1.0 + EndGlobalSection +EndGlobal diff --git a/MelonVPNClient/MainWindow.cs b/MelonVPNClient/MainWindow.cs new file mode 100644 index 0000000..98b4328 --- /dev/null +++ b/MelonVPNClient/MainWindow.cs @@ -0,0 +1,230 @@ +using System; +using System.Net.NetworkInformation; +using System.Threading; +using Gtk; +using MelonVPNCore; + +public partial class MainWindow : Window +{ + private Label statusLabel; + private Button startBtn; + private Button stopBtn; + private Button refreshBtn; + private Button viewClientsBtn; + private Thread startupCheckThread; + private ThreadWrapper wrapper; + + public MainWindow() : base(WindowType.Toplevel) + { + Build(); + + Title = "Melon VPN"; + SetSizeRequest(300, 300); + SetDefaultSize(300, 300); + SetPosition(WindowPosition.Center); + + Resizable = false; + TypeHint = Gdk.WindowTypeHint.Normal; + Present(); + + statusLabel = new Label + { + Visible = true, + Text = "Loading..." + }; + fixed1.Put(statusLabel, 10, 10); + + startBtn = new Button + { + Visible = true, + Label = "Start" + }; + startBtn.SetSizeRequest(80, 30); + startBtn.Clicked += OnStartClicked; + fixed1.Put(startBtn, 10, 40); + + stopBtn = new Button + { + Visible = true, + Label = "Stop" + }; + stopBtn.SetSizeRequest(80, 30); + stopBtn.Clicked += OnStopClicked; + fixed1.Put(stopBtn, 100, 40); + + refreshBtn = new Button + { + Visible = true, + Label = "Refresh" + }; + refreshBtn.SetSizeRequest(80, 30); + refreshBtn.Clicked += OnRefreshClicked; + fixed1.Put(refreshBtn, 190, 40); + + viewClientsBtn = new Button + { + Visible = true, + Label = "View Clients" + }; + viewClientsBtn.SetSizeRequest(100, 30); + viewClientsBtn.Clicked += OnViewClientsClicked; + fixed1.Put(viewClientsBtn, 10, 80); + + GUISocketServer.Receive += delegate (object sender, ClientResponseState s) + { + Console.WriteLine(s); + Application.Invoke(delegate + { + UpdateStatus(s); + }); + }; + GUISocketServer.ClientListUpdate += delegate (object sender, ConnectedClient[] clients) + { + Console.WriteLine(clients.Length); + foreach (ConnectedClient c in clients) + { + Console.WriteLine(c.name + "--" + c.ip); + } + }; + wrapper = new ThreadWrapper(GUISocketServer.StartServer); + + startupCheckThread = new Thread(StartupCheckMethod) + { + IsBackground = true + }; + startupCheckThread.Start(); + } + + string GetVpnInternalIp() + { + if (NetworkInterface.GetIsNetworkAvailable()) + { + foreach (NetworkInterface f in NetworkInterface.GetAllNetworkInterfaces()) + { + IPInterfaceProperties p = f.GetIPProperties(); + IPAddressInformationCollection addressesColl = p.AnycastAddresses; + foreach (IPAddressInformation ip in addressesColl) + { + if (ip.Address.ToString().StartsWith("10.137.248.", StringComparison.CurrentCulture)) + { + return ip.Address.ToString(); + } + } + } + } + return ""; + } + + void StartupCheckMethod() + { + ClientResponseState s = Client.SendDataMessage(DataMessage.Status); + Console.WriteLine(s); + Application.Invoke(delegate + { + UpdateStatus(s); + }); + } + + void Refresh() + { + ClientResponseState s = Client.SendDataMessage(DataMessage.Status); + switch (s) + { + case ClientResponseState.Error: + case ClientResponseState.ServerError: + UpdateStatus(s); + MessageDialog md = new MessageDialog(this, + DialogFlags.DestroyWithParent, MessageType.Error, + ButtonsType.Ok, "Error stopping VPN. Is the daemon running?"); + md.Run(); + md.Destroy(); + break; + case ClientResponseState.Online: + case ClientResponseState.Offline: + UpdateStatus(s); + break; + } + } + + void UpdateStatus(ClientResponseState s) + { + switch (s) + { + case ClientResponseState.Error: + statusLabel.Text = "Client Error"; + break; + case ClientResponseState.ServerError: + statusLabel.Text = "Server Error"; + break; + case ClientResponseState.Blank: + statusLabel.Text = "No reply"; + break; + case ClientResponseState.Online: + statusLabel.Text = "Online - " + GetVpnInternalIp(); + break; + case ClientResponseState.Offline: + statusLabel.Text = "Offline"; + break; + default: + statusLabel.Text = "Unknown"; + break; + } + } + + protected void OnDeleteEvent(object sender, DeleteEventArgs a) + { + if (wrapper != null) + { + wrapper.Kill(); + wrapper.Join(); + } + Application.Quit(); + a.RetVal = true; + } + + void OnStartClicked(object sender, EventArgs e) + { + ClientResponseState s = Client.SendDataMessage(DataMessage.Start); + switch (s) + { + case ClientResponseState.Error: + case ClientResponseState.ServerError: + case ClientResponseState.Offline: + UpdateStatus(s); + MessageDialog md = new MessageDialog(this, + DialogFlags.DestroyWithParent, MessageType.Error, + ButtonsType.Ok, "Error starting VPN. Is the daemon running?"); + md.Run(); + md.Destroy(); + break; + } + } + + void OnStopClicked(object sender, EventArgs e) + { + ClientResponseState s = Client.SendDataMessage(DataMessage.Stop); + switch (s) + { + case ClientResponseState.Error: + case ClientResponseState.ServerError: + case ClientResponseState.Online: + UpdateStatus(s); + MessageDialog md = new MessageDialog(this, + DialogFlags.DestroyWithParent, MessageType.Error, + ButtonsType.Ok, "Error stopping VPN. Is the daemon running?"); + md.Run(); + md.Destroy(); + break; + } + } + + void OnRefreshClicked(object sender, EventArgs e) + { + Refresh(); + } + + void OnViewClientsClicked(object sender, EventArgs e) + { + Refresh(); + } +} diff --git a/MelonVPNClient/MelonVPNClient.csproj b/MelonVPNClient/MelonVPNClient.csproj new file mode 100644 index 0000000..44b6e83 --- /dev/null +++ b/MelonVPNClient/MelonVPNClient.csproj @@ -0,0 +1,90 @@ + + + + Debug + x86 + {071B91A9-6C1D-4A80-98EA-5077E4F66468} + WinExe + MelonVPNClient + MelonVPNClient + v4.8 + 1.0 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + x86 + + + true + bin\Release + prompt + 4 + x86 + + + + + False + gtk-sharp-2.0 + + + False + gtk-sharp-2.0 + + + False + glib-sharp-3.0 + + + False + glade-sharp-2.0 + + + False + gtk-sharp-3.0 + + + False + gtk-sharp-2.0 + + + + gio-sharp-3.0 + + + + + gui.stetic + + + + + + + + + + + + {B2F2F96C-3E5D-4176-9D66-479F357BC078} + MelonVPNCore + + + + + PreserveNewest + + + + + PreserveNewest + + + + diff --git a/MelonVPNClient/Program.cs b/MelonVPNClient/Program.cs new file mode 100644 index 0000000..d7679ba --- /dev/null +++ b/MelonVPNClient/Program.cs @@ -0,0 +1,15 @@ +using Gtk; + +namespace MelonVPNClient +{ + class MainClass + { + public static void Main(string[] args) + { + Application.Init(); + MainWindow win = new MainWindow(); + win.Show(); + Application.Run(); + } + } +} diff --git a/MelonVPNClient/Properties/AssemblyInfo.cs b/MelonVPNClient/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ffc75dc --- /dev/null +++ b/MelonVPNClient/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("MelonVPNClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("${AuthorCopyright}")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/MelonVPNClient/gtk-gui/MainWindow.cs b/MelonVPNClient/gtk-gui/MainWindow.cs new file mode 100644 index 0000000..d819174 --- /dev/null +++ b/MelonVPNClient/gtk-gui/MainWindow.cs @@ -0,0 +1,29 @@ + +// This file has been generated by the GUI designer. Do not modify. + +public partial class MainWindow +{ + private global::Gtk.Fixed fixed1; + + protected virtual void Build() + { + global::Stetic.Gui.Initialize(this); + // Widget MainWindow + this.Name = "MainWindow"; + this.Title = global::Mono.Unix.Catalog.GetString("MainWindow"); + this.WindowPosition = ((global::Gtk.WindowPosition)(4)); + // Container child MainWindow.Gtk.Container+ContainerChild + this.fixed1 = new global::Gtk.Fixed(); + this.fixed1.Name = "fixed1"; + this.fixed1.HasWindow = false; + this.Add(this.fixed1); + if ((this.Child != null)) + { + this.Child.ShowAll(); + } + this.DefaultWidth = 204; + this.DefaultHeight = 86; + this.Show(); + this.DeleteEvent += new global::Gtk.DeleteEventHandler(this.OnDeleteEvent); + } +} diff --git a/MelonVPNClient/gtk-gui/generated.cs b/MelonVPNClient/gtk-gui/generated.cs new file mode 100644 index 0000000..4842e95 --- /dev/null +++ b/MelonVPNClient/gtk-gui/generated.cs @@ -0,0 +1,30 @@ + +// This file has been generated by the GUI designer. Do not modify. +namespace Stetic +{ + internal class Gui + { + private static bool initialized; + + internal static void Initialize(Gtk.Widget iconRenderer) + { + if ((Stetic.Gui.initialized == false)) + { + Stetic.Gui.initialized = true; + } + } + } + + internal class ActionGroups + { + public static Gtk.ActionGroup GetActionGroup(System.Type type) + { + return Stetic.ActionGroups.GetActionGroup(type.FullName); + } + + public static Gtk.ActionGroup GetActionGroup(string name) + { + return null; + } + } +} diff --git a/MelonVPNClient/gtk-gui/gui.stetic b/MelonVPNClient/gtk-gui/gui.stetic new file mode 100644 index 0000000..3efaffc --- /dev/null +++ b/MelonVPNClient/gtk-gui/gui.stetic @@ -0,0 +1,22 @@ + + + + .. + + + + + + + + MainWindow + CenterOnParent + + + + + False + + + + \ No newline at end of file diff --git a/MelonVPNClient/melonvpn.desktop b/MelonVPNClient/melonvpn.desktop new file mode 100755 index 0000000..27cbdd6 --- /dev/null +++ b/MelonVPNClient/melonvpn.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Categories=Network; +Icon= +Name=Melon VPN +Path= +Terminal=false +Type=Application +Exec=/usr/bin/melonvpnclient diff --git a/MelonVPNClient/melonvpnclient b/MelonVPNClient/melonvpnclient new file mode 100755 index 0000000..89850a0 --- /dev/null +++ b/MelonVPNClient/melonvpnclient @@ -0,0 +1 @@ +mono /usr/lib/melon-vpn/MelonVPNClient.exe diff --git a/MelonVPNConnectedClientUpdate/MelonVPNConnectedClientUpdate.csproj b/MelonVPNConnectedClientUpdate/MelonVPNConnectedClientUpdate.csproj new file mode 100644 index 0000000..83c851e --- /dev/null +++ b/MelonVPNConnectedClientUpdate/MelonVPNConnectedClientUpdate.csproj @@ -0,0 +1,46 @@ + + + + Debug + x86 + {B318A58E-028B-43A2-A753-2D7FBCA4EE40} + Exe + MelonVPNConnectedClientUpdate + MelonVPNConnectedClientUpdate + v4.8 + 1.0 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + x86 + + + true + bin\Release + prompt + 4 + true + x86 + + + + + + + + + + + {B2F2F96C-3E5D-4176-9D66-479F357BC078} + MelonVPNCore + + + + \ No newline at end of file diff --git a/MelonVPNConnectedClientUpdate/Program.cs b/MelonVPNConnectedClientUpdate/Program.cs new file mode 100644 index 0000000..749fbf5 --- /dev/null +++ b/MelonVPNConnectedClientUpdate/Program.cs @@ -0,0 +1,13 @@ +using System; +using MelonVPNCore; + +namespace MelonVPNConnectedClientUpdate +{ + class MainClass + { + public static void Main(string[] args) + { + Client.SendCustomMessage(Messages.GetClientListMessage(Console.ReadLine())); + } + } +} diff --git a/MelonVPNConnectedClientUpdate/Properties/AssemblyInfo.cs b/MelonVPNConnectedClientUpdate/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4ef1482 --- /dev/null +++ b/MelonVPNConnectedClientUpdate/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("MelonVPNConnectedClientUpdate")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("${AuthorCopyright}")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/MelonVPNCore/Client.cs b/MelonVPNCore/Client.cs new file mode 100644 index 0000000..9dd9cd1 --- /dev/null +++ b/MelonVPNCore/Client.cs @@ -0,0 +1,41 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace MelonVPNCore +{ + public static class Client + { + public static ClientResponseState SendDataMessage(DataMessage msg) => SendDataMessage(msg, false); + public static ClientResponseState SendDataMessage(DataMessage msg, bool IsSendingFromDaemon) => SendCustomMessage(Messages.GetMessage(msg), IsSendingFromDaemon); + public static ClientResponseState SendCustomMessage(string msg) => SendCustomMessage(msg, false); + public static ClientResponseState SendCustomMessage(string msg, bool IsSendingFromDaemon) + { + IPHostEntry host = Dns.GetHostEntry("localhost"); + IPAddress ipAddress = host.AddressList[0]; + IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, IsSendingFromDaemon ? 22036 : 22035); + + try + { + if (msg == Messages.EOF || msg == "") return ClientResponseState.Blank; + + Socket client = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + client.Connect(remoteEndPoint); + client.ReceiveTimeout = 5000; + client.SendTimeout = 5000; + + byte[] bytes = Encoding.ASCII.GetBytes(msg); + + client.Send(bytes); + client.Close(); + return ClientResponseState.Sent; + } + catch (Exception e) + { + Console.WriteLine(e); + return ClientResponseState.Error; + } + } + } +} \ No newline at end of file diff --git a/MelonVPNCore/ClientListParser.cs b/MelonVPNCore/ClientListParser.cs new file mode 100644 index 0000000..f30009e --- /dev/null +++ b/MelonVPNCore/ClientListParser.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Linq; + +namespace MelonVPNCore +{ + public static class ClientListParser + { + public static ConnectedClient[] Parse(string json) + { + List clients = new List(); + JArray a = JArray.Parse(json); + + foreach (JObject o in a.Children()) + { + clients.Add(new ConnectedClient(o.GetValue("Name").ToString(), o.GetValue("IP").ToString())); + } + return clients.ToArray(); + } + } +} diff --git a/MelonVPNCore/ClientResponseState.cs b/MelonVPNCore/ClientResponseState.cs new file mode 100644 index 0000000..68298bd --- /dev/null +++ b/MelonVPNCore/ClientResponseState.cs @@ -0,0 +1,13 @@ +namespace MelonVPNCore +{ + public enum ClientResponseState + { + Online, + Offline, + Error, + ServerError, + None, + Blank, + Sent + } +} diff --git a/MelonVPNCore/ConnectedClient.cs b/MelonVPNCore/ConnectedClient.cs new file mode 100644 index 0000000..3f7cd43 --- /dev/null +++ b/MelonVPNCore/ConnectedClient.cs @@ -0,0 +1,14 @@ +namespace MelonVPNCore +{ + public class ConnectedClient + { + public readonly string name; + public readonly string ip; + + public ConnectedClient(string name, string ip) + { + this.name = name; + this.ip = ip; + } + } +} diff --git a/MelonVPNCore/DaemonSocketServer.cs b/MelonVPNCore/DaemonSocketServer.cs new file mode 100644 index 0000000..b8dc53f --- /dev/null +++ b/MelonVPNCore/DaemonSocketServer.cs @@ -0,0 +1,136 @@ +using System; +using System.Diagnostics; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace MelonVPNCore +{ + public static class DaemonSocketServer + { + public static void StartServer() + { + IPHostEntry host = Dns.GetHostEntry("localhost"); + IPAddress ipAddress = host.AddressList[0]; + IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 22035); + + try + { + Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + listener.Bind(localEndPoint); + listener.Listen(10); + + Process currentVpnProcess = null; + string lastClientUpdate = Messages.EOF; + + while (true) + { + Socket handler = listener.Accept(); + + string data = null; + byte[] bytes = null; + + while (true) + { + bytes = new byte[1024]; + int bytesRec = handler.Receive(bytes); + data += Encoding.ASCII.GetString(bytes, 0, bytesRec); + if (data.IndexOf(Messages.EOF, StringComparison.CurrentCulture) > -1) break; + } + + if (data.StartsWith(Messages.ClientListStartMsg, StringComparison.CurrentCulture)) + { + lastClientUpdate = data; + Client.SendCustomMessage(lastClientUpdate, true); + } + else if (data == Messages.StatusMsg) + { + Console.WriteLine("Status requested"); + if (currentVpnProcess != null && !currentVpnProcess.HasExited) + { + Console.WriteLine("Sending response: online"); + Client.SendDataMessage(DataMessage.Online, true); + Client.SendCustomMessage(lastClientUpdate, true); + } + else + { + Console.WriteLine("Sending response: offline"); + Client.SendDataMessage(DataMessage.Offline, true); + } + } + else if (data == Messages.StartMsg) + { + if (currentVpnProcess == null) + { + Console.WriteLine("Starting VPN"); + try + { + Console.WriteLine("Starting embedded process"); + currentVpnProcess = new Process + { + StartInfo = new ProcessStartInfo("simple-vpn", "client /etc/melon-vpn/client.cfg") + }; + currentVpnProcess.Exited += delegate + { + Client.SendDataMessage(DataMessage.Offline, true); + currentVpnProcess = null; + }; + currentVpnProcess.Start(); + Console.WriteLine("Sending online reply"); + Thread.Sleep(1500); + Client.SendDataMessage(DataMessage.Online, true); + } + catch (Exception e) + { + Console.WriteLine("There was an error. But I fixed it."); + Console.WriteLine("It looked like this: " + e); + currentVpnProcess = null; + Client.SendDataMessage(DataMessage.Error, true); + } + } + else + { + Console.WriteLine("VPN already started"); + } + } + else if (data == Messages.StopMsg) + { + if (currentVpnProcess != null) + { + Console.WriteLine("Stopping VPN"); + try + { + Console.WriteLine("Stopping embedded process"); + currentVpnProcess.Kill(); + currentVpnProcess = null; + Console.WriteLine("Sending offline reply"); + Client.SendDataMessage(DataMessage.Offline, true); + } + catch (Exception e) + { + Console.WriteLine("There was an error. But I fixed it."); + Console.WriteLine("It looked like this: " + e); + currentVpnProcess = null; + Client.SendDataMessage(DataMessage.Error, true); + } + } + else + { + Console.WriteLine("VPN already stopped"); + } + } + + Client.SendDataMessage(DataMessage.Blank, true); + + handler.Shutdown(SocketShutdown.Both); + handler.Close(); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + } +} diff --git a/MelonVPNCore/DataMessage.cs b/MelonVPNCore/DataMessage.cs new file mode 100644 index 0000000..8637678 --- /dev/null +++ b/MelonVPNCore/DataMessage.cs @@ -0,0 +1,13 @@ +namespace MelonVPNCore +{ + public enum DataMessage + { + Status, + Online, + Offline, + Start, + Stop, + Blank, + Error + } +} diff --git a/MelonVPNCore/GUISocketServer.cs b/MelonVPNCore/GUISocketServer.cs new file mode 100644 index 0000000..d4cbd31 --- /dev/null +++ b/MelonVPNCore/GUISocketServer.cs @@ -0,0 +1,68 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace MelonVPNCore +{ + public static class GUISocketServer + { + public static event EventHandler Receive; + public static event EventHandler ClientListUpdate; + + public static void StartServer() + { + IPHostEntry host = Dns.GetHostEntry("localhost"); + IPAddress ipAddress = host.AddressList[0]; + IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 22036); + + try + { + Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + listener.Bind(localEndPoint); + listener.Listen(10); + + while (true) + { + Socket handler = listener.Accept(); + + string data = ""; + byte[] bytes = null; + + while (true) + { + bytes = new byte[1024]; + int bytesRec = handler.Receive(bytes); + data += Encoding.ASCII.GetString(bytes, 0, bytesRec); + if (data.IndexOf(Messages.EOF, StringComparison.CurrentCulture) > -1) break; + } + + ClientResponseState ret = ClientResponseState.None; + if (data == Messages.OnlineMsg) ret = ClientResponseState.Online; + if (data == Messages.OfflineMsg) ret = ClientResponseState.Offline; + if (data == Messages.ErrorMsg) ret = ClientResponseState.ServerError; + Console.WriteLine(data); + if (data.StartsWith(Messages.ClientListStartMsg, StringComparison.CurrentCulture)) + { + string jsonWithEof = data.Substring(Messages.ClientListStartMsg.Length); + string jsonData = data.Substring(0, jsonWithEof.Length - Messages.EOF.Length); + Console.WriteLine("clients: " + jsonData); + //ClientListParser.Parse(jsonData); + ConnectedClient[] clients = new ConnectedClient[0]; + ClientListUpdate?.Invoke(null, clients); + } + + handler.Shutdown(SocketShutdown.Both); + handler.Close(); + + Receive?.Invoke(null, ret); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + Console.WriteLine("GUI socket server reathed the end"); + } + } +} diff --git a/MelonVPNCore/MelonVPNCore.csproj b/MelonVPNCore/MelonVPNCore.csproj new file mode 100644 index 0000000..0fe0ee3 --- /dev/null +++ b/MelonVPNCore/MelonVPNCore.csproj @@ -0,0 +1,49 @@ + + + + {B2F2F96C-3E5D-4176-9D66-479F357BC078} + Library + MelonVPNCore + MelonVPNCore + v4.8 + 1.0 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + x86 + + + true + bin\Release + prompt + 4 + x86 + + + + + + + + + + + + + + + + ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + + + + + + \ No newline at end of file diff --git a/MelonVPNCore/Messages.cs b/MelonVPNCore/Messages.cs new file mode 100644 index 0000000..159e19e --- /dev/null +++ b/MelonVPNCore/Messages.cs @@ -0,0 +1,29 @@ +namespace MelonVPNCore +{ + public static class Messages + { + public static string EOF = ""; + public static string Code = "80d168e76f6bd40efe897881f35bcd895459e42a"; + public static string StatusMsg = "STATUS::" + Code + EOF; + public static string OnlineMsg = "ONLINE::" + Code + EOF; + public static string OfflineMsg = "OFFLINE::" + Code + EOF; + public static string StartMsg = "START::" + Code + EOF; + public static string StopMsg = "STOP::" + Code + EOF; + public static string ErrorMsg = "ERROR::" + Code + EOF; + public static string ClientListStartMsg = "CLIENTLIST::" + Code + "::"; + + public static string GetMessage(DataMessage a) + { + if (a == DataMessage.Status) return StatusMsg; + if (a == DataMessage.Online) return OnlineMsg; + if (a == DataMessage.Offline) return OfflineMsg; + if (a == DataMessage.Start) return StartMsg; + if (a == DataMessage.Stop) return StopMsg; + if (a == DataMessage.Error) return ErrorMsg; + if (a == DataMessage.Blank) return EOF; + return EOF; + } + + public static string GetClientListMessage(string a) => ClientListStartMsg + a + EOF; + } +} diff --git a/MelonVPNCore/SocketClient.cs b/MelonVPNCore/SocketClient.cs new file mode 100644 index 0000000..34c46b3 --- /dev/null +++ b/MelonVPNCore/SocketClient.cs @@ -0,0 +1,140 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace MelonVPNCore +{ + public class AsynchronousClient + { + private const int port = 22035; + + private ManualResetEvent connectDone = new ManualResetEvent(false); + private ManualResetEvent receiveDone = new ManualResetEvent(false); + + private string response = ""; + private Socket client; + + private void StartClient() + { + // Connect to a remote device. + try + { + IPHostEntry ipHostInfo = Dns.GetHostEntry("127.0.0.1"); + IPAddress ipAddress = ipHostInfo.AddressList[0]; + IPEndPoint remoteEP = new IPEndPoint(ipAddress, port); + + client = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client); + connectDone.WaitOne(); + + // Receive the response from the remote device. + Receive(client); + receiveDone.WaitOne(); + + // Write the response to the console. + Console.WriteLine("Response received : {0}", response); + + // Release the socket. + client.Shutdown(SocketShutdown.Both); + client.Close(); + + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + } + + public void Send(string msg) + { + Send(client, msg + ""); + } + + public string Receive() + { + if (client == null) return null; + Receive(client); + receiveDone.WaitOne(); + return response; + } + + private void ConnectCallback(IAsyncResult ar) + { + try + { + Socket client = (Socket)ar.AsyncState; + client.EndConnect(ar); + Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString()); + + connectDone.Set(); + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + } + + public string Receive() + { + try + { + StateObject state = new StateObject + { + workSocket = client + }; + client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); + } + catch (Exception e) + { + Console.WriteLine(e); + } + receiveDone.WaitOne(); + } + + private static void ReceiveCallback(IAsyncResult ar) + { + try + { + StateObject state = (StateObject)ar.AsyncState; + Socket client = state.workSocket; + int bytesRead = client.EndReceive(ar); + if (bytesRead > 0) + { + state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); + client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); + } + else + { + if (state.sb.Length > 1) response = state.sb.ToString(); + if (receiveDone != null) receiveDone.Set(); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + private static void Send(Socket client, string data) + { + byte[] byteData = Encoding.ASCII.GetBytes(data); + client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client); + } + + private static void SendCallback(IAsyncResult ar) + { + try + { + Socket client = (Socket)ar.AsyncState; + int bytesSent = client.EndSend(ar); + Console.WriteLine("Sent {0} bytes to server.", bytesSent); + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + } +} \ No newline at end of file diff --git a/MelonVPNCore/SocketServer.cs b/MelonVPNCore/SocketServer.cs new file mode 100644 index 0000000..8f0a307 --- /dev/null +++ b/MelonVPNCore/SocketServer.cs @@ -0,0 +1,10 @@ +using System; +namespace MelonVPNCore +{ + public class SocketServer + { + public SocketServer() + { + } + } +} diff --git a/MelonVPNCore/ThreadWrapper.cs b/MelonVPNCore/ThreadWrapper.cs new file mode 100644 index 0000000..4192993 --- /dev/null +++ b/MelonVPNCore/ThreadWrapper.cs @@ -0,0 +1,21 @@ +using System.Threading; + +namespace MelonVPNCore +{ + public class ThreadWrapper + { + private Thread wrapper; + + public ThreadWrapper(ThreadStart action) + { + wrapper = new Thread(action) + { + IsBackground = true + }; + wrapper.Start(); + } + + public void Join() => wrapper.Join(); + public void Kill() => wrapper.Abort(); + } +} diff --git a/MelonVPNCore/packages.config b/MelonVPNCore/packages.config new file mode 100644 index 0000000..281c145 --- /dev/null +++ b/MelonVPNCore/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/MelonVPNDaemon/MelonVPNDaemon.csproj b/MelonVPNDaemon/MelonVPNDaemon.csproj new file mode 100644 index 0000000..20f5840 --- /dev/null +++ b/MelonVPNDaemon/MelonVPNDaemon.csproj @@ -0,0 +1,54 @@ + + + + Debug + x86 + {AFF161B8-AF8E-4A16-9AA4-B692EB0D838E} + Exe + MelonVPNDaemon + MelonVPNDaemon + v4.8 + 1.0 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + x86 + + + true + bin\Release + prompt + 4 + true + x86 + + + + + + + + + + + {B2F2F96C-3E5D-4176-9D66-479F357BC078} + MelonVPNCore + + + + + PreserveNewest + + + PreserveNewest + + + + \ No newline at end of file diff --git a/MelonVPNDaemon/Program.cs b/MelonVPNDaemon/Program.cs new file mode 100644 index 0000000..3f0c051 --- /dev/null +++ b/MelonVPNDaemon/Program.cs @@ -0,0 +1,14 @@ +using MelonVPNCore; + +namespace MelonVPNDaemon +{ + class Program + { + public static int Main(string[] args) + { + ThreadWrapper wrapper = new ThreadWrapper(DaemonSocketServer.StartServer); + wrapper.Join(); + return 1; + } + } +} diff --git a/MelonVPNDaemon/Properties/AssemblyInfo.cs b/MelonVPNDaemon/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..690b010 --- /dev/null +++ b/MelonVPNDaemon/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("MelonVPNDaemon")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("${AuthorCopyright}")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/MelonVPNDaemon/Server.cs b/MelonVPNDaemon/Server.cs new file mode 100644 index 0000000..67556f8 --- /dev/null +++ b/MelonVPNDaemon/Server.cs @@ -0,0 +1,155 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace MelonVPNDaemon { + + +public class AsynchronousSocketListener +{ + // Thread signal. + public static ManualResetEvent allDone = new ManualResetEvent(false); + + public AsynchronousSocketListener() + { + } + + public static void StartListening() + { + // Establish the local endpoint for the socket. + // The DNS name of the computer + // running the listener is "host.contoso.com". + IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); + IPAddress ipAddress = ipHostInfo.AddressList[0]; + IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); + + // Create a TCP/IP socket. + Socket listener = new Socket(ipAddress.AddressFamily, + SocketType.Stream, ProtocolType.Tcp); + + // Bind the socket to the local endpoint and listen for incoming connections. + try + { + listener.Bind(localEndPoint); + listener.Listen(100); + + while (true) + { + // Set the event to nonsignaled state. + allDone.Reset(); + + // Start an asynchronous socket to listen for connections. + Console.WriteLine("Waiting for a connection..."); + listener.BeginAccept( + new AsyncCallback(AcceptCallback), + listener); + + // Wait until a connection is made before continuing. + allDone.WaitOne(); + } + + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + + Console.WriteLine("\nPress ENTER to continue..."); + Console.Read(); + + } + + public static void AcceptCallback(IAsyncResult ar) + { + // Signal the main thread to continue. + allDone.Set(); + + // Get the socket that handles the client request. + Socket listener = (Socket)ar.AsyncState; + Socket handler = listener.EndAccept(ar); + + // Create the state object. + StateObject state = new StateObject(); + state.workSocket = handler; + handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, + new AsyncCallback(ReadCallback), state); + } + + public static void ReadCallback(IAsyncResult ar) + { + String content = String.Empty; + + // Retrieve the state object and the handler socket + // from the asynchronous state object. + StateObject state = (StateObject)ar.AsyncState; + Socket handler = state.workSocket; + + // Read data from the client socket. + int bytesRead = handler.EndReceive(ar); + + if (bytesRead > 0) + { + // There might be more data, so store the data received so far. + state.sb.Append(Encoding.ASCII.GetString( + state.buffer, 0, bytesRead)); + + // Check for end-of-file tag. If it is not there, read + // more data. + content = state.sb.ToString(); + if (content.IndexOf("") > -1) + { + // All the data has been read from the + // client. Display it on the console. + Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", + content.Length, content); + // Echo the data back to the client. + Send(handler, content); + } + else + { + // Not all data received. Get more. + handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, + new AsyncCallback(ReadCallback), state); + } + } + } + + private static void Send(Socket handler, String data) + { + // Convert the string data to byte data using ASCII encoding. + byte[] byteData = Encoding.ASCII.GetBytes(data); + + // Begin sending the data to the remote device. + handler.BeginSend(byteData, 0, byteData.Length, 0, + new AsyncCallback(SendCallback), handler); + } + + private static void SendCallback(IAsyncResult ar) + { + try + { + // Retrieve the socket from the state object. + Socket handler = (Socket)ar.AsyncState; + + // Complete sending the data to the remote device. + int bytesSent = handler.EndSend(ar); + Console.WriteLine("Sent {0} bytes to client.", bytesSent); + + handler.Shutdown(SocketShutdown.Both); + handler.Close(); + + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + } + + public static int Main(String[] args) + { + StartListening(); + return 0; + } +} \ No newline at end of file diff --git a/MelonVPNDaemon/client.cfg b/MelonVPNDaemon/client.cfg new file mode 100644 index 0000000..0f2bbcb --- /dev/null +++ b/MelonVPNDaemon/client.cfg @@ -0,0 +1,4 @@ +vpn = wss://example.com +key = 1234 +name = temp +peers = mono /usr/lib/melon-vpn/MelonVPNConnectedClientUpdate.exe diff --git a/MelonVPNDaemon/melonvpndaemon.service b/MelonVPNDaemon/melonvpndaemon.service new file mode 100644 index 0000000..7b26a0b --- /dev/null +++ b/MelonVPNDaemon/melonvpndaemon.service @@ -0,0 +1,16 @@ +# Melon VPN Daemon +[Unit] +Description=Manage Melon VPN Service +After=network.target + +[Service] +WorkingDirectory=/ +ExecStart=mono /usr/lib/melon-vpn/MelonVPNDaemon.exe +User=root +Group=root +Type=simple +Restart=on-failure +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/build b/build new file mode 100755 index 0000000..9f537ee --- /dev/null +++ b/build @@ -0,0 +1,8 @@ +#!/bin/bash +echo "[info] Preparing to setup dependencies" +./install-dependencies +echo "[info] Preparing to build projects from source" +./build-source +echo "[info] Preparing to install components" +./install-components +echo "[info] Build process finished" diff --git a/build-source b/build-source new file mode 100755 index 0000000..4f8c464 --- /dev/null +++ b/build-source @@ -0,0 +1,4 @@ +#!/bin/bash +echo "Preparing to build MelonVPN" +msbuild MelonVPN.sln -m /t:MelonVPNCore /t:MelonVPNConnectedClientUpdate /t:MelonVPNDaemon /t:MelonVPNClient /p:Configuration=Release /p:Platform=x86 +echo "Run \"./install\" to install all the components for MelonVPN" diff --git a/install-components b/install-components new file mode 100755 index 0000000..434a159 --- /dev/null +++ b/install-components @@ -0,0 +1,33 @@ +#!/bin/bash +sudo mkdir -p /usr/lib/melon-vpn/ +sudo cp MelonVPNCore/bin/Release/MelonVPNCore.dll /usr/lib/melon-vpn/ +sudo cp MelonVPNConnectedClientUpdate/bin/Release/MelonVPNConnectedClientUpdate.exe /usr/lib/melon-vpn/ +sudo cp MelonVPNDaemon/bin/Release/MelonVPNDaemon.exe /usr/lib/melon-vpn/ +if [ -f /etc/systemd/system/melonvpndaemon.service ]; then + echo "[info] Found daemon service at \"/etc/systemd/system/melonvpndaemon.service\" delete this to reinstall the default service" +else + sudo cp MelonVPNDaemon/bin/Release/melonvpndaemon.service /etc/systemd/system/ +fi +sudo mkdir -p /etc/melon-vpn/ +if [ -f /etc/melon-vpn/client.cfg ]; then + echo "[info] Found config at \"/etc/melon-vpn/client.cfg\" delete this to reinstall the default config" +else + sudo cp MelonVPNDaemon/bin/Release/client.cfg /etc/melon-vpn/ +fi +if [ -f /usr/share/applications/melonvpn.desktop ]; then + echo "[info] Found desktop file at \"/usr/share/applications/melonvpn.desktop\" delete this to reinstall the default one" +else + sudo cp MelonVPNClient/bin/Release/melonvpn.desktop /usr/share/applications/ +fi +sudo chown root:root /etc/melon-vpn/client.cfg +sudo cp MelonVPNClient/bin/Release/MelonVPNClient.exe /usr/lib/melon-vpn/ +sudo cp MelonVPNClient/bin/Release/MelonVPNClient.exe.config /usr/lib/melon-vpn/ +sudo cp MelonVPNClient/bin/Release/melonvpnclient /usr/bin/ +sudo chmod +x /usr/bin/melonvpnclient +echo "[info] Restarting daemon" +sudo systemctl stop melonvpndaemon +sudo systemctl disable melonvpndaemon +sudo systemctl daemon-reload +sudo systemctl enable melonvpndaemon +sudo systemctl start melonvpndaemon +echo "[info] Remember to setup \"/etc/melon-vpn/client.cfg\"" diff --git a/install-dependencies b/install-dependencies new file mode 100755 index 0000000..7bbb5fd --- /dev/null +++ b/install-dependencies @@ -0,0 +1,22 @@ +#!/bin/bash +if [ "$(go version | head -c 13)" == "go version go" ]; then + echo "Assuming go is installed" + if [ -f /usr/bin/simple-vpn ]; then + echo "Found \"/usr/bin/simple-vpn\" assuming it is installed correctly" + else + echo "Cloning simple-vpn" + git clone https://github.com/skx/simple-vpn + cd simple-vpn + echo "Installing simple-vpn" + go build + sudo cp ./simple-vpn /usr/bin/ -i + cd .. + echo "Cleaning up" + rm simple-vpn -rf + echo "Components installed..." + fi +else + echo "Please install golang before continuing" + exit +fi +echo "Run \"./build\" to continue with installing MelonVPN"