1
0
mirror of https://github.com/Ylianst/MeshCentralRouter synced 2025-12-06 00:13:33 +00:00

Initial version on GitHub

This commit is contained in:
Ylian Saint-Hilaire
2019-06-06 14:23:23 -07:00
commit 20984125ac
70 changed files with 20736 additions and 0 deletions

291
.gitignore vendored Normal file
View File

@@ -0,0 +1,291 @@
## Ignore nodejs things
HelpImages/
## 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
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.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
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# 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
# TODO: 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
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/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
# 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
# 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
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# 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/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

289
AddPortMapForm.Designer.cs generated Normal file
View File

@@ -0,0 +1,289 @@
namespace MeshCentralRouter
{
partial class AddPortMapForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AddPortMapForm));
this.cancelButton = new System.Windows.Forms.Button();
this.okButton = new System.Windows.Forms.Button();
this.localNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label1 = new System.Windows.Forms.Label();
this.nodeComboBox = new System.Windows.Forms.ComboBox();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.remoteNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label4 = new System.Windows.Forms.Label();
this.appComboBox = new System.Windows.Forms.ComboBox();
this.label5 = new System.Windows.Forms.Label();
this.groupComboBox = new System.Windows.Forms.ComboBox();
this.label6 = new System.Windows.Forms.Label();
this.tcpRadioButton = new System.Windows.Forms.RadioButton();
this.udpRadioButton = new System.Windows.Forms.RadioButton();
((System.ComponentModel.ISupportInitialize)(this.localNumericUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.remoteNumericUpDown)).BeginInit();
this.SuspendLayout();
//
// cancelButton
//
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(288, 167);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(75, 23);
this.cancelButton.TabIndex = 8;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
//
// okButton
//
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.okButton.Location = new System.Drawing.Point(207, 167);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 23);
this.okButton.TabIndex = 7;
this.okButton.Text = "OK";
this.okButton.UseVisualStyleBackColor = true;
this.okButton.Click += new System.EventHandler(this.okButton_Click);
//
// localNumericUpDown
//
this.localNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.localNumericUpDown.Location = new System.Drawing.Point(157, 33);
this.localNumericUpDown.Maximum = new decimal(new int[] {
65535,
0,
0,
0});
this.localNumericUpDown.Name = "localNumericUpDown";
this.localNumericUpDown.Size = new System.Drawing.Size(206, 20);
this.localNumericUpDown.TabIndex = 2;
this.localNumericUpDown.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 35);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(55, 13);
this.label1.TabIndex = 3;
this.label1.Text = "Local Port";
//
// nodeComboBox
//
this.nodeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.nodeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.nodeComboBox.FormattingEnabled = true;
this.nodeComboBox.Location = new System.Drawing.Point(157, 86);
this.nodeComboBox.Name = "nodeComboBox";
this.nodeComboBox.Size = new System.Drawing.Size(206, 21);
this.nodeComboBox.TabIndex = 4;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 89);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(81, 13);
this.label2.TabIndex = 5;
this.label2.Text = "Remote Device";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 142);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(66, 13);
this.label3.TabIndex = 7;
this.label3.Text = "Remote Port";
//
// remoteNumericUpDown
//
this.remoteNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.remoteNumericUpDown.Location = new System.Drawing.Point(157, 140);
this.remoteNumericUpDown.Maximum = new decimal(new int[] {
65535,
0,
0,
0});
this.remoteNumericUpDown.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.remoteNumericUpDown.Name = "remoteNumericUpDown";
this.remoteNumericUpDown.Size = new System.Drawing.Size(206, 20);
this.remoteNumericUpDown.TabIndex = 6;
this.remoteNumericUpDown.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
this.remoteNumericUpDown.Value = new decimal(new int[] {
80,
0,
0,
0});
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(12, 116);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(59, 13);
this.label4.TabIndex = 9;
this.label4.Text = "Application";
//
// appComboBox
//
this.appComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.appComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.appComboBox.FormattingEnabled = true;
this.appComboBox.Items.AddRange(new object[] {
"Custom",
"HTTP",
"HTTPS",
"RDP",
"PuTTY",
"WinSCP"});
this.appComboBox.Location = new System.Drawing.Point(157, 113);
this.appComboBox.Name = "appComboBox";
this.appComboBox.Size = new System.Drawing.Size(206, 21);
this.appComboBox.TabIndex = 5;
this.appComboBox.SelectedIndexChanged += new System.EventHandler(this.appComboBox_SelectedIndexChanged);
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(12, 62);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(73, 13);
this.label5.TabIndex = 11;
this.label5.Text = "Device Group";
//
// groupComboBox
//
this.groupComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.groupComboBox.FormattingEnabled = true;
this.groupComboBox.Location = new System.Drawing.Point(157, 59);
this.groupComboBox.Name = "groupComboBox";
this.groupComboBox.Size = new System.Drawing.Size(206, 21);
this.groupComboBox.TabIndex = 3;
this.groupComboBox.SelectedIndexChanged += new System.EventHandler(this.groupComboBox_SelectedIndexChanged);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(12, 9);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(46, 13);
this.label6.TabIndex = 12;
this.label6.Text = "Protocol";
//
// tcpRadioButton
//
this.tcpRadioButton.AutoSize = true;
this.tcpRadioButton.Checked = true;
this.tcpRadioButton.Location = new System.Drawing.Point(157, 9);
this.tcpRadioButton.Name = "tcpRadioButton";
this.tcpRadioButton.Size = new System.Drawing.Size(46, 17);
this.tcpRadioButton.TabIndex = 1;
this.tcpRadioButton.TabStop = true;
this.tcpRadioButton.Text = "TCP";
this.tcpRadioButton.UseVisualStyleBackColor = true;
this.tcpRadioButton.CheckedChanged += new System.EventHandler(this.tcpRadioButton_CheckedChanged);
//
// udpRadioButton
//
this.udpRadioButton.AutoSize = true;
this.udpRadioButton.Location = new System.Drawing.Point(209, 9);
this.udpRadioButton.Name = "udpRadioButton";
this.udpRadioButton.Size = new System.Drawing.Size(48, 17);
this.udpRadioButton.TabIndex = 1;
this.udpRadioButton.Text = "UDP";
this.udpRadioButton.UseVisualStyleBackColor = true;
this.udpRadioButton.CheckedChanged += new System.EventHandler(this.tcpRadioButton_CheckedChanged);
//
// AddPortMapForm
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(375, 202);
this.Controls.Add(this.udpRadioButton);
this.Controls.Add(this.tcpRadioButton);
this.Controls.Add(this.label6);
this.Controls.Add(this.label5);
this.Controls.Add(this.groupComboBox);
this.Controls.Add(this.label4);
this.Controls.Add(this.appComboBox);
this.Controls.Add(this.label3);
this.Controls.Add(this.remoteNumericUpDown);
this.Controls.Add(this.label2);
this.Controls.Add(this.nodeComboBox);
this.Controls.Add(this.label1);
this.Controls.Add(this.localNumericUpDown);
this.Controls.Add(this.okButton);
this.Controls.Add(this.cancelButton);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AddPortMapForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Port Mapping";
this.Load += new System.EventHandler(this.AddPortMapForm_Load);
((System.ComponentModel.ISupportInitialize)(this.localNumericUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.remoteNumericUpDown)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Button okButton;
private System.Windows.Forms.NumericUpDown localNumericUpDown;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.ComboBox nodeComboBox;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.NumericUpDown remoteNumericUpDown;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.ComboBox appComboBox;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.ComboBox groupComboBox;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.RadioButton tcpRadioButton;
private System.Windows.Forms.RadioButton udpRadioButton;
}
}

99
AddPortMapForm.cs Normal file
View File

@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MeshCentralRouter
{
public partial class AddPortMapForm : Form
{
private MeshCentralServer meshcentral;
public AddPortMapForm(MeshCentralServer meshcentral)
{
this.meshcentral = meshcentral;
InitializeComponent();
}
public int getProtocol() { return (int)(tcpRadioButton.Checked?1:2); }
public int getLocalPort() { return (int)localNumericUpDown.Value; }
public int getRemotePort() { return (int)remoteNumericUpDown.Value; }
public int getAppId() { return (int)appComboBox.SelectedIndex; }
public NodeClass getNode() { return (NodeClass)nodeComboBox.SelectedItem; }
private void AddPortMapForm_Load(object sender, EventArgs e)
{
// Fill the groups
groupComboBox.Items.Clear();
foreach (string meshid in meshcentral.meshes.Keys)
{
MeshClass mesh = meshcentral.meshes[meshid];
if (mesh.type == 2)
{
int nodeCount = 0;
foreach (string nodeid in meshcentral.nodes.Keys)
{
NodeClass node = meshcentral.nodes[nodeid];
if ((node.meshid == mesh.meshid) && ((node.conn & 1) != 0)) { nodeCount++; }
}
if (nodeCount > 0) { groupComboBox.Items.Add(mesh); }
}
}
// Set default selection
if (groupComboBox.Items.Count > 0) { groupComboBox.SelectedIndex = 0; }
appComboBox.SelectedIndex = 1;
fillNodesInDropDown();
}
private void fillNodesInDropDown()
{
MeshClass mesh = (MeshClass)groupComboBox.SelectedItem;
// Fill the nodes dropdown
nodeComboBox.Items.Clear();
foreach (string nodeid in meshcentral.nodes.Keys)
{
NodeClass node = meshcentral.nodes[nodeid];
if ((node.meshid == mesh.meshid) && ((node.conn & 1) != 0)) { nodeComboBox.Items.Add(node); }
}
if (nodeComboBox.Items.Count > 0) { nodeComboBox.SelectedIndex = 0; }
}
private void appComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (appComboBox.SelectedIndex == 1) { remoteNumericUpDown.Value = 80; }
if (appComboBox.SelectedIndex == 2) { remoteNumericUpDown.Value = 443; }
if (appComboBox.SelectedIndex == 3) { remoteNumericUpDown.Value = 3389; }
if (appComboBox.SelectedIndex == 4) { remoteNumericUpDown.Value = 22; }
if (appComboBox.SelectedIndex == 5) { remoteNumericUpDown.Value = 22; }
}
private void cancelButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
private void okButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
}
private void groupComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
fillNodesInDropDown();
}
private void tcpRadioButton_CheckedChanged(object sender, EventArgs e)
{
appComboBox.Enabled = tcpRadioButton.Checked;
if (udpRadioButton.Checked) { appComboBox.SelectedIndex = 0; }
}
}
}

1815
AddPortMapForm.resx Normal file

File diff suppressed because it is too large Load Diff

315
AddRelayMapForm.Designer.cs generated Normal file
View File

@@ -0,0 +1,315 @@
namespace MeshCentralRouter
{
partial class AddRelayMapForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AddRelayMapForm));
this.cancelButton = new System.Windows.Forms.Button();
this.okButton = new System.Windows.Forms.Button();
this.localNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label1 = new System.Windows.Forms.Label();
this.nodeComboBox = new System.Windows.Forms.ComboBox();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.remoteNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label4 = new System.Windows.Forms.Label();
this.appComboBox = new System.Windows.Forms.ComboBox();
this.label5 = new System.Windows.Forms.Label();
this.remoteIpTextBox = new System.Windows.Forms.TextBox();
this.label6 = new System.Windows.Forms.Label();
this.groupComboBox = new System.Windows.Forms.ComboBox();
this.udpRadioButton = new System.Windows.Forms.RadioButton();
this.tcpRadioButton = new System.Windows.Forms.RadioButton();
this.label7 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.localNumericUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.remoteNumericUpDown)).BeginInit();
this.SuspendLayout();
//
// cancelButton
//
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(288, 193);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(75, 23);
this.cancelButton.TabIndex = 0;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
//
// okButton
//
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.okButton.Location = new System.Drawing.Point(207, 193);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 23);
this.okButton.TabIndex = 1;
this.okButton.Text = "OK";
this.okButton.UseVisualStyleBackColor = true;
this.okButton.Click += new System.EventHandler(this.okButton_Click);
//
// localNumericUpDown
//
this.localNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.localNumericUpDown.Location = new System.Drawing.Point(157, 32);
this.localNumericUpDown.Maximum = new decimal(new int[] {
65535,
0,
0,
0});
this.localNumericUpDown.Name = "localNumericUpDown";
this.localNumericUpDown.Size = new System.Drawing.Size(206, 20);
this.localNumericUpDown.TabIndex = 2;
this.localNumericUpDown.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 34);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(55, 13);
this.label1.TabIndex = 3;
this.label1.Text = "Local Port";
//
// nodeComboBox
//
this.nodeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.nodeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.nodeComboBox.FormattingEnabled = true;
this.nodeComboBox.Location = new System.Drawing.Point(157, 85);
this.nodeComboBox.Name = "nodeComboBox";
this.nodeComboBox.Size = new System.Drawing.Size(206, 21);
this.nodeComboBox.TabIndex = 4;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 88);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(71, 13);
this.label2.TabIndex = 5;
this.label2.Text = "Relay Device";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 167);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(66, 13);
this.label3.TabIndex = 7;
this.label3.Text = "Remote Port";
//
// remoteNumericUpDown
//
this.remoteNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.remoteNumericUpDown.Location = new System.Drawing.Point(157, 165);
this.remoteNumericUpDown.Maximum = new decimal(new int[] {
65535,
0,
0,
0});
this.remoteNumericUpDown.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.remoteNumericUpDown.Name = "remoteNumericUpDown";
this.remoteNumericUpDown.Size = new System.Drawing.Size(206, 20);
this.remoteNumericUpDown.TabIndex = 6;
this.remoteNumericUpDown.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
this.remoteNumericUpDown.Value = new decimal(new int[] {
80,
0,
0,
0});
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(12, 115);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(59, 13);
this.label4.TabIndex = 9;
this.label4.Text = "Application";
//
// appComboBox
//
this.appComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.appComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.appComboBox.FormattingEnabled = true;
this.appComboBox.Items.AddRange(new object[] {
"Custom",
"HTTP",
"HTTPS",
"RDP",
"PuTTY",
"WinSCP"});
this.appComboBox.Location = new System.Drawing.Point(157, 112);
this.appComboBox.Name = "appComboBox";
this.appComboBox.Size = new System.Drawing.Size(206, 21);
this.appComboBox.TabIndex = 8;
this.appComboBox.SelectedIndexChanged += new System.EventHandler(this.appComboBox_SelectedIndexChanged);
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(12, 142);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(57, 13);
this.label5.TabIndex = 10;
this.label5.Text = "Remote IP";
//
// remoteIpTextBox
//
this.remoteIpTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.remoteIpTextBox.Location = new System.Drawing.Point(157, 139);
this.remoteIpTextBox.Name = "remoteIpTextBox";
this.remoteIpTextBox.Size = new System.Drawing.Size(206, 20);
this.remoteIpTextBox.TabIndex = 11;
this.remoteIpTextBox.Text = "127.0.0.1";
this.remoteIpTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
this.remoteIpTextBox.TextChanged += new System.EventHandler(this.remoteIpTextBox_TextChanged);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(12, 61);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(73, 13);
this.label6.TabIndex = 13;
this.label6.Text = "Device Group";
//
// groupComboBox
//
this.groupComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.groupComboBox.FormattingEnabled = true;
this.groupComboBox.Location = new System.Drawing.Point(157, 58);
this.groupComboBox.Name = "groupComboBox";
this.groupComboBox.Size = new System.Drawing.Size(206, 21);
this.groupComboBox.TabIndex = 12;
this.groupComboBox.SelectedIndexChanged += new System.EventHandler(this.groupComboBox_SelectedIndexChanged);
//
// udpRadioButton
//
this.udpRadioButton.AutoSize = true;
this.udpRadioButton.Location = new System.Drawing.Point(209, 9);
this.udpRadioButton.Name = "udpRadioButton";
this.udpRadioButton.Size = new System.Drawing.Size(48, 17);
this.udpRadioButton.TabIndex = 14;
this.udpRadioButton.Text = "UDP";
this.udpRadioButton.UseVisualStyleBackColor = true;
//
// tcpRadioButton
//
this.tcpRadioButton.AutoSize = true;
this.tcpRadioButton.Checked = true;
this.tcpRadioButton.Location = new System.Drawing.Point(157, 9);
this.tcpRadioButton.Name = "tcpRadioButton";
this.tcpRadioButton.Size = new System.Drawing.Size(46, 17);
this.tcpRadioButton.TabIndex = 15;
this.tcpRadioButton.TabStop = true;
this.tcpRadioButton.Text = "TCP";
this.tcpRadioButton.UseVisualStyleBackColor = true;
this.tcpRadioButton.CheckedChanged += new System.EventHandler(this.tcpRadioButton_CheckedChanged);
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(12, 9);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(46, 13);
this.label7.TabIndex = 16;
this.label7.Text = "Protocol";
//
// AddRelayMapForm
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(375, 228);
this.Controls.Add(this.udpRadioButton);
this.Controls.Add(this.tcpRadioButton);
this.Controls.Add(this.label7);
this.Controls.Add(this.label6);
this.Controls.Add(this.groupComboBox);
this.Controls.Add(this.remoteIpTextBox);
this.Controls.Add(this.label5);
this.Controls.Add(this.label4);
this.Controls.Add(this.appComboBox);
this.Controls.Add(this.label3);
this.Controls.Add(this.remoteNumericUpDown);
this.Controls.Add(this.label2);
this.Controls.Add(this.nodeComboBox);
this.Controls.Add(this.label1);
this.Controls.Add(this.localNumericUpDown);
this.Controls.Add(this.okButton);
this.Controls.Add(this.cancelButton);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AddRelayMapForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Relay Mapping";
this.Load += new System.EventHandler(this.AddRelayMapForm_Load);
((System.ComponentModel.ISupportInitialize)(this.localNumericUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.remoteNumericUpDown)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Button okButton;
private System.Windows.Forms.NumericUpDown localNumericUpDown;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.ComboBox nodeComboBox;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.NumericUpDown remoteNumericUpDown;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.ComboBox appComboBox;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox remoteIpTextBox;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.ComboBox groupComboBox;
private System.Windows.Forms.RadioButton udpRadioButton;
private System.Windows.Forms.RadioButton tcpRadioButton;
private System.Windows.Forms.Label label7;
}
}

112
AddRelayMapForm.cs Normal file
View File

@@ -0,0 +1,112 @@
using System;
using System.Net;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MeshCentralRouter
{
public partial class AddRelayMapForm : Form
{
private MeshCentralServer meshcentral;
public AddRelayMapForm(MeshCentralServer meshcentral)
{
this.meshcentral = meshcentral;
InitializeComponent();
updateInfo();
}
public int getProtocol() { return (int)(tcpRadioButton.Checked ? 1 : 2); }
public int getLocalPort() { return (int)localNumericUpDown.Value; }
public int getRemotePort() { return (int)remoteNumericUpDown.Value; }
public string getRemoteIP() { return remoteIpTextBox.Text; }
public int getAppId() { return (int)appComboBox.SelectedIndex; }
public NodeClass getNode() { return (NodeClass)nodeComboBox.SelectedItem; }
private void AddRelayMapForm_Load(object sender, EventArgs e)
{
// Fill the groups
groupComboBox.Items.Clear();
foreach (string meshid in meshcentral.meshes.Keys)
{
MeshClass mesh = meshcentral.meshes[meshid];
if (mesh.type == 2) {
int nodeCount = 0;
foreach (string nodeid in meshcentral.nodes.Keys) {
NodeClass node = meshcentral.nodes[nodeid];
if ((node.meshid == mesh.meshid) && ((node.conn & 1) != 0)) { nodeCount++; }
}
if (nodeCount > 0) { groupComboBox.Items.Add(mesh); }
}
}
// Set default selection
if (groupComboBox.Items.Count > 0) { groupComboBox.SelectedIndex = 0; }
appComboBox.SelectedIndex = 1;
fillNodesInDropDown();
}
private void fillNodesInDropDown()
{
MeshClass mesh = (MeshClass)groupComboBox.SelectedItem;
// Fill the nodes dropdown
nodeComboBox.Items.Clear();
foreach (string nodeid in meshcentral.nodes.Keys)
{
NodeClass node = meshcentral.nodes[nodeid];
if ((node.meshid == mesh.meshid) && ((node.conn & 1) != 0)) { nodeComboBox.Items.Add(node); }
}
if (nodeComboBox.Items.Count > 0) { nodeComboBox.SelectedIndex = 0; }
}
private void appComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (appComboBox.SelectedIndex == 1) { remoteNumericUpDown.Value = 80; }
if (appComboBox.SelectedIndex == 2) { remoteNumericUpDown.Value = 443; }
if (appComboBox.SelectedIndex == 3) { remoteNumericUpDown.Value = 3389; }
if (appComboBox.SelectedIndex == 4) { remoteNumericUpDown.Value = 22; }
if (appComboBox.SelectedIndex == 5) { remoteNumericUpDown.Value = 22; }
}
private void updateInfo()
{
IPAddress ipaddress = null;
try { ipaddress = IPAddress.Parse(remoteIpTextBox.Text); } catch (Exception) { }
okButton.Enabled = (ipaddress != null);
}
private void cancelButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
private void okButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
}
private void remoteIpTextBox_TextChanged(object sender, EventArgs e)
{
updateInfo();
}
private void groupComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
fillNodesInDropDown();
}
private void tcpRadioButton_CheckedChanged(object sender, EventArgs e)
{
appComboBox.Enabled = tcpRadioButton.Checked;
if (udpRadioButton.Checked) { appComboBox.SelectedIndex = 0; }
}
}
}

1815
AddRelayMapForm.resx Normal file

File diff suppressed because it is too large Load Diff

196
AppLaunchForm.Designer.cs generated Normal file
View File

@@ -0,0 +1,196 @@
namespace MeshCentralRouter
{
partial class AppLaunchForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AppLaunchForm));
this.cancelButton = new System.Windows.Forms.Button();
this.okButton = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.appNameLabel = new System.Windows.Forms.Label();
this.appPathTextBox = new System.Windows.Forms.TextBox();
this.appLinkLabel = new System.Windows.Forms.LinkLabel();
this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
this.folderButton = new System.Windows.Forms.Button();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// cancelButton
//
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(323, 128);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(75, 23);
this.cancelButton.TabIndex = 0;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
//
// okButton
//
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.okButton.Location = new System.Drawing.Point(242, 128);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 23);
this.okButton.TabIndex = 1;
this.okButton.Text = "OK";
this.okButton.UseVisualStyleBackColor = true;
this.okButton.Click += new System.EventHandler(this.okButton_Click);
//
// groupBox1
//
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox1.Controls.Add(this.folderButton);
this.groupBox1.Controls.Add(this.appNameLabel);
this.groupBox1.Controls.Add(this.appLinkLabel);
this.groupBox1.Controls.Add(this.appPathTextBox);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(386, 110);
this.groupBox1.TabIndex = 2;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Application Launch";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 25);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(35, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Name";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 51);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(25, 13);
this.label2.TabIndex = 1;
this.label2.Text = "Site";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 77);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(29, 13);
this.label3.TabIndex = 2;
this.label3.Text = "Path";
//
// appNameLabel
//
this.appNameLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.appNameLabel.Location = new System.Drawing.Point(83, 25);
this.appNameLabel.Name = "appNameLabel";
this.appNameLabel.Size = new System.Drawing.Size(238, 16);
this.appNameLabel.TabIndex = 3;
this.appNameLabel.Text = "Application Name";
//
// appPathTextBox
//
this.appPathTextBox.Location = new System.Drawing.Point(86, 74);
this.appPathTextBox.Name = "appPathTextBox";
this.appPathTextBox.Size = new System.Drawing.Size(294, 20);
this.appPathTextBox.TabIndex = 3;
this.appPathTextBox.TextChanged += new System.EventHandler(this.appPathTextBox_TextChanged);
//
// appLinkLabel
//
this.appLinkLabel.Location = new System.Drawing.Point(83, 49);
this.appLinkLabel.Name = "appLinkLabel";
this.appLinkLabel.Size = new System.Drawing.Size(238, 16);
this.appLinkLabel.TabIndex = 4;
this.appLinkLabel.TabStop = true;
this.appLinkLabel.Text = "Application Link";
this.appLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.appLinkLabel_LinkClicked);
//
// openFileDialog
//
this.openFileDialog.DefaultExt = "exe";
this.openFileDialog.Filter = "Executable (*.exe)|*.exe";
this.openFileDialog.Title = "Application Executable";
//
// folderButton
//
this.folderButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.folderButton.Image = global::MeshCentralRouter.Properties.Resources.Folder36;
this.folderButton.Location = new System.Drawing.Point(327, 15);
this.folderButton.Name = "folderButton";
this.folderButton.Size = new System.Drawing.Size(52, 52);
this.folderButton.TabIndex = 5;
this.folderButton.UseVisualStyleBackColor = true;
this.folderButton.Click += new System.EventHandler(this.folderPictureBox_Click);
//
// AppLaunchForm
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(410, 163);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.okButton);
this.Controls.Add(this.cancelButton);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AppLaunchForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "MeshCentral Router";
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Button okButton;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Label appNameLabel;
private System.Windows.Forms.LinkLabel appLinkLabel;
private System.Windows.Forms.TextBox appPathTextBox;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.OpenFileDialog openFileDialog;
private System.Windows.Forms.Button folderButton;
}
}

63
AppLaunchForm.cs Normal file
View File

@@ -0,0 +1,63 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MeshCentralRouter
{
public partial class AppLaunchForm : Form
{
public AppLaunchForm()
{
InitializeComponent();
UpdateInfo();
}
public void SetAppName(string name) { appNameLabel.Text = name; }
public void SetAppLink(string link) { appLinkLabel.Text = link; }
public void SetAppPath(string path) { appPathTextBox.Text = path; }
public string GetAppPath() { return appPathTextBox.Text; }
private void folderPictureBox_Click(object sender, EventArgs e)
{
openFileDialog.FileName = appPathTextBox.Text;
if (openFileDialog.ShowDialog(this) == DialogResult.OK)
{
appPathTextBox.Text = openFileDialog.FileName;
UpdateInfo();
}
}
private void appPathTextBox_TextChanged(object sender, EventArgs e)
{
UpdateInfo();
}
private void UpdateInfo()
{
okButton.Enabled = File.Exists(appPathTextBox.Text);
}
private void okButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
}
private void cancelButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
private void appLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start(appLinkLabel.Text);
}
}
}

1818
AppLaunchForm.resx Normal file

File diff suppressed because it is too large Load Diff

BIN
Empty-Banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

BIN
Folder36.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
Gear20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 742 B

BIN
Graphics.pptx Normal file

Binary file not shown.

BIN
Help20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

BIN
MC2-Banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
MC2-Logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

859
MainForm.Designer.cs generated Normal file
View File

@@ -0,0 +1,859 @@
namespace MeshCentralRouter
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.panel5 = new System.Windows.Forms.Panel();
this.mainPanel = new System.Windows.Forms.Panel();
this.mainTabControl = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.panel1 = new System.Windows.Forms.Panel();
this.stateLabel = new System.Windows.Forms.Label();
this.label28 = new System.Windows.Forms.Label();
this.label27 = new System.Windows.Forms.Label();
this.label26 = new System.Windows.Forms.Label();
this.passwordTextBox = new System.Windows.Forms.TextBox();
this.serverNameComboBox = new System.Windows.Forms.ComboBox();
this.userNameTextBox = new System.Windows.Forms.TextBox();
this.licenseLinkLabel = new System.Windows.Forms.LinkLabel();
this.versionLabel = new System.Windows.Forms.Label();
this.nextButton1 = new System.Windows.Forms.Button();
this.pictureBox3 = new System.Windows.Forms.PictureBox();
this.label1 = new System.Windows.Forms.Label();
this.pictureBox2 = new System.Windows.Forms.PictureBox();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.panel2 = new System.Windows.Forms.Panel();
this.label3 = new System.Windows.Forms.Label();
this.tokenTextBox = new System.Windows.Forms.TextBox();
this.pictureBox6 = new System.Windows.Forms.PictureBox();
this.backButton2 = new System.Windows.Forms.Button();
this.nextButton2 = new System.Windows.Forms.Button();
this.pictureBox4 = new System.Windows.Forms.PictureBox();
this.label2 = new System.Windows.Forms.Label();
this.tabPage3 = new System.Windows.Forms.TabPage();
this.panel3 = new System.Windows.Forms.Panel();
this.certDetailsTextBox = new System.Windows.Forms.TextBox();
this.certDetailsButton = new System.Windows.Forms.Button();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.backButton3 = new System.Windows.Forms.Button();
this.nextButton3 = new System.Windows.Forms.Button();
this.pictureBox5 = new System.Windows.Forms.PictureBox();
this.tabPage5 = new System.Windows.Forms.TabPage();
this.panel4 = new System.Windows.Forms.Panel();
this.settingsPictureBox = new System.Windows.Forms.PictureBox();
this.openWebSiteButton = new System.Windows.Forms.Button();
this.helpPictureBox = new System.Windows.Forms.PictureBox();
this.addRelayButton = new System.Windows.Forms.Button();
this.mapPanel = new System.Windows.Forms.Panel();
this.noMapLabel = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.addButton = new System.Windows.Forms.Button();
this.backButton5 = new System.Windows.Forms.Button();
this.nextButton5 = new System.Windows.Forms.Button();
this.pictureBox7 = new System.Windows.Forms.PictureBox();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.stateClearTimer = new System.Windows.Forms.Timer(this.components);
this.cookieRefreshTimer = new System.Windows.Forms.Timer(this.components);
this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
this.trayIconContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.panel5.SuspendLayout();
this.mainPanel.SuspendLayout();
this.mainTabControl.SuspendLayout();
this.tabPage1.SuspendLayout();
this.panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
this.tabPage2.SuspendLayout();
this.panel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox6)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).BeginInit();
this.tabPage3.SuspendLayout();
this.panel3.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox5)).BeginInit();
this.tabPage5.SuspendLayout();
this.panel4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.settingsPictureBox)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.helpPictureBox)).BeginInit();
this.mapPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox7)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.trayIconContextMenuStrip.SuspendLayout();
this.SuspendLayout();
//
// panel5
//
this.panel5.Controls.Add(this.mainPanel);
this.panel5.Controls.Add(this.pictureBox1);
this.panel5.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel5.Location = new System.Drawing.Point(0, 0);
this.panel5.Name = "panel5";
this.panel5.Size = new System.Drawing.Size(492, 416);
this.panel5.TabIndex = 8;
//
// mainPanel
//
this.mainPanel.Controls.Add(this.mainTabControl);
this.mainPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.mainPanel.Location = new System.Drawing.Point(0, 65);
this.mainPanel.Name = "mainPanel";
this.mainPanel.Size = new System.Drawing.Size(492, 351);
this.mainPanel.TabIndex = 9;
//
// mainTabControl
//
this.mainTabControl.Appearance = System.Windows.Forms.TabAppearance.FlatButtons;
this.mainTabControl.Controls.Add(this.tabPage1);
this.mainTabControl.Controls.Add(this.tabPage2);
this.mainTabControl.Controls.Add(this.tabPage3);
this.mainTabControl.Controls.Add(this.tabPage5);
this.mainTabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.mainTabControl.Location = new System.Drawing.Point(0, 0);
this.mainTabControl.Margin = new System.Windows.Forms.Padding(0);
this.mainTabControl.Name = "mainTabControl";
this.mainTabControl.SelectedIndex = 0;
this.mainTabControl.Size = new System.Drawing.Size(492, 351);
this.mainTabControl.TabIndex = 8;
this.mainTabControl.Visible = false;
//
// tabPage1
//
this.tabPage1.Controls.Add(this.panel1);
this.tabPage1.Location = new System.Drawing.Point(4, 25);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(484, 322);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "Login";
this.tabPage1.UseVisualStyleBackColor = true;
//
// panel1
//
this.panel1.Controls.Add(this.stateLabel);
this.panel1.Controls.Add(this.label28);
this.panel1.Controls.Add(this.label27);
this.panel1.Controls.Add(this.label26);
this.panel1.Controls.Add(this.passwordTextBox);
this.panel1.Controls.Add(this.serverNameComboBox);
this.panel1.Controls.Add(this.userNameTextBox);
this.panel1.Controls.Add(this.licenseLinkLabel);
this.panel1.Controls.Add(this.versionLabel);
this.panel1.Controls.Add(this.nextButton1);
this.panel1.Controls.Add(this.pictureBox3);
this.panel1.Controls.Add(this.label1);
this.panel1.Controls.Add(this.pictureBox2);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(3, 3);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(478, 316);
this.panel1.TabIndex = 6;
//
// stateLabel
//
this.stateLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.stateLabel.AutoSize = true;
this.stateLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.stateLabel.ForeColor = System.Drawing.Color.Red;
this.stateLabel.Location = new System.Drawing.Point(241, 225);
this.stateLabel.Name = "stateLabel";
this.stateLabel.Size = new System.Drawing.Size(88, 13);
this.stateLabel.TabIndex = 19;
this.stateLabel.Text = "Error Message";
this.stateLabel.Visible = false;
//
// label28
//
this.label28.AutoSize = true;
this.label28.Location = new System.Drawing.Point(238, 176);
this.label28.Name = "label28";
this.label28.Size = new System.Drawing.Size(53, 13);
this.label28.TabIndex = 18;
this.label28.Text = "Password";
//
// label27
//
this.label27.AutoSize = true;
this.label27.Location = new System.Drawing.Point(238, 135);
this.label27.Name = "label27";
this.label27.Size = new System.Drawing.Size(55, 13);
this.label27.TabIndex = 17;
this.label27.Text = "Username";
//
// label26
//
this.label26.AutoSize = true;
this.label26.Location = new System.Drawing.Point(238, 92);
this.label26.Name = "label26";
this.label26.Size = new System.Drawing.Size(38, 13);
this.label26.TabIndex = 16;
this.label26.Text = "Server";
//
// passwordTextBox
//
this.passwordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.passwordTextBox.Location = new System.Drawing.Point(241, 192);
this.passwordTextBox.Name = "passwordTextBox";
this.passwordTextBox.PasswordChar = '●';
this.passwordTextBox.Size = new System.Drawing.Size(213, 20);
this.passwordTextBox.TabIndex = 3;
this.passwordTextBox.TextChanged += new System.EventHandler(this.updatePanel1);
this.passwordTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.passwordTextBox_KeyPress);
//
// serverNameComboBox
//
this.serverNameComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.serverNameComboBox.DisplayMember = "meshcentral.com";
this.serverNameComboBox.FormattingEnabled = true;
this.serverNameComboBox.Items.AddRange(new object[] {
"meshcentral.com"});
this.serverNameComboBox.Location = new System.Drawing.Point(241, 110);
this.serverNameComboBox.Name = "serverNameComboBox";
this.serverNameComboBox.Size = new System.Drawing.Size(213, 21);
this.serverNameComboBox.TabIndex = 1;
this.serverNameComboBox.SelectedIndexChanged += new System.EventHandler(this.updatePanel1);
this.serverNameComboBox.TextChanged += new System.EventHandler(this.updatePanel1);
this.serverNameComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.serverNameComboBox_KeyPress);
//
// userNameTextBox
//
this.userNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.userNameTextBox.Location = new System.Drawing.Point(241, 151);
this.userNameTextBox.Name = "userNameTextBox";
this.userNameTextBox.Size = new System.Drawing.Size(213, 20);
this.userNameTextBox.TabIndex = 2;
this.userNameTextBox.TextChanged += new System.EventHandler(this.updatePanel1);
this.userNameTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.userNameTextBox_KeyPress);
//
// licenseLinkLabel
//
this.licenseLinkLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.licenseLinkLabel.AutoSize = true;
this.licenseLinkLabel.Location = new System.Drawing.Point(307, 260);
this.licenseLinkLabel.Name = "licenseLinkLabel";
this.licenseLinkLabel.Size = new System.Drawing.Size(171, 13);
this.licenseLinkLabel.TabIndex = 12;
this.licenseLinkLabel.TabStop = true;
this.licenseLinkLabel.Text = "Open Source, Apache 2.0 License";
this.licenseLinkLabel.TextAlign = System.Drawing.ContentAlignment.TopRight;
this.licenseLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.licenseLinkLabel_LinkClicked);
//
// versionLabel
//
this.versionLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.versionLabel.AutoSize = true;
this.versionLabel.ForeColor = System.Drawing.Color.Gray;
this.versionLabel.Location = new System.Drawing.Point(3, 260);
this.versionLabel.Name = "versionLabel";
this.versionLabel.Size = new System.Drawing.Size(37, 13);
this.versionLabel.TabIndex = 11;
this.versionLabel.Text = "v0.8.0";
//
// nextButton1
//
this.nextButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.nextButton1.Location = new System.Drawing.Point(391, 285);
this.nextButton1.Name = "nextButton1";
this.nextButton1.Size = new System.Drawing.Size(75, 23);
this.nextButton1.TabIndex = 4;
this.nextButton1.Text = "Login";
this.nextButton1.UseVisualStyleBackColor = true;
this.nextButton1.Click += new System.EventHandler(this.nextButton1_Click);
//
// pictureBox3
//
this.pictureBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pictureBox3.Image = global::MeshCentralRouter.Properties.Resources.Empty_Banner;
this.pictureBox3.Location = new System.Drawing.Point(0, 276);
this.pictureBox3.Name = "pictureBox3";
this.pictureBox3.Size = new System.Drawing.Size(478, 40);
this.pictureBox3.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBox3.TabIndex = 10;
this.pictureBox3.TabStop = false;
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(454, 29);
this.label1.TabIndex = 6;
this.label1.Text = "MeshCentral Router allows mapping of TCP ports on this computer to any computer i" +
"n your MeshCentral server account. Start my logging into your account.";
//
// pictureBox2
//
this.pictureBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pictureBox2.Image = global::MeshCentralRouter.Properties.Resources.MeshCentral;
this.pictureBox2.Location = new System.Drawing.Point(15, 68);
this.pictureBox2.Name = "pictureBox2";
this.pictureBox2.Size = new System.Drawing.Size(202, 170);
this.pictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.pictureBox2.TabIndex = 7;
this.pictureBox2.TabStop = false;
//
// tabPage2
//
this.tabPage2.Controls.Add(this.panel2);
this.tabPage2.Location = new System.Drawing.Point(4, 25);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(484, 322);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "Token";
this.tabPage2.UseVisualStyleBackColor = true;
//
// panel2
//
this.panel2.Controls.Add(this.label3);
this.panel2.Controls.Add(this.tokenTextBox);
this.panel2.Controls.Add(this.pictureBox6);
this.panel2.Controls.Add(this.backButton2);
this.panel2.Controls.Add(this.nextButton2);
this.panel2.Controls.Add(this.pictureBox4);
this.panel2.Controls.Add(this.label2);
this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel2.Location = new System.Drawing.Point(3, 3);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(478, 316);
this.panel2.TabIndex = 7;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(238, 135);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(38, 13);
this.label3.TabIndex = 19;
this.label3.Text = "Token";
//
// tokenTextBox
//
this.tokenTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.tokenTextBox.Location = new System.Drawing.Point(241, 151);
this.tokenTextBox.Name = "tokenTextBox";
this.tokenTextBox.Size = new System.Drawing.Size(213, 20);
this.tokenTextBox.TabIndex = 18;
this.tokenTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.tokenTextBox_KeyPress);
//
// pictureBox6
//
this.pictureBox6.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pictureBox6.Image = global::MeshCentralRouter.Properties.Resources.MeshCentral;
this.pictureBox6.Location = new System.Drawing.Point(15, 68);
this.pictureBox6.Name = "pictureBox6";
this.pictureBox6.Size = new System.Drawing.Size(202, 170);
this.pictureBox6.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.pictureBox6.TabIndex = 15;
this.pictureBox6.TabStop = false;
//
// backButton2
//
this.backButton2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.backButton2.Location = new System.Drawing.Point(310, 285);
this.backButton2.Name = "backButton2";
this.backButton2.Size = new System.Drawing.Size(75, 23);
this.backButton2.TabIndex = 13;
this.backButton2.Text = "Back";
this.backButton2.UseVisualStyleBackColor = true;
this.backButton2.Click += new System.EventHandler(this.backButton2_Click);
//
// nextButton2
//
this.nextButton2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.nextButton2.Location = new System.Drawing.Point(391, 285);
this.nextButton2.Name = "nextButton2";
this.nextButton2.Size = new System.Drawing.Size(75, 23);
this.nextButton2.TabIndex = 14;
this.nextButton2.Text = "Next";
this.nextButton2.UseVisualStyleBackColor = true;
this.nextButton2.Click += new System.EventHandler(this.nextButton2_Click);
//
// pictureBox4
//
this.pictureBox4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pictureBox4.Image = global::MeshCentralRouter.Properties.Resources.Empty_Banner;
this.pictureBox4.Location = new System.Drawing.Point(0, 276);
this.pictureBox4.Name = "pictureBox4";
this.pictureBox4.Size = new System.Drawing.Size(478, 40);
this.pictureBox4.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBox4.TabIndex = 10;
this.pictureBox4.TabStop = false;
//
// label2
//
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label2.Location = new System.Drawing.Point(12, 9);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(454, 32);
this.label2.TabIndex = 6;
this.label2.Text = "Enter the second factor authentication token.";
//
// tabPage3
//
this.tabPage3.Controls.Add(this.panel3);
this.tabPage3.Location = new System.Drawing.Point(4, 25);
this.tabPage3.Name = "tabPage3";
this.tabPage3.Size = new System.Drawing.Size(484, 322);
this.tabPage3.TabIndex = 2;
this.tabPage3.Text = "Certificate";
this.tabPage3.UseVisualStyleBackColor = true;
//
// panel3
//
this.panel3.Controls.Add(this.certDetailsTextBox);
this.panel3.Controls.Add(this.certDetailsButton);
this.panel3.Controls.Add(this.label4);
this.panel3.Controls.Add(this.label5);
this.panel3.Controls.Add(this.backButton3);
this.panel3.Controls.Add(this.nextButton3);
this.panel3.Controls.Add(this.pictureBox5);
this.panel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel3.Location = new System.Drawing.Point(0, 0);
this.panel3.Name = "panel3";
this.panel3.Size = new System.Drawing.Size(484, 322);
this.panel3.TabIndex = 8;
//
// certDetailsTextBox
//
this.certDetailsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.certDetailsTextBox.Location = new System.Drawing.Point(15, 82);
this.certDetailsTextBox.Multiline = true;
this.certDetailsTextBox.Name = "certDetailsTextBox";
this.certDetailsTextBox.ReadOnly = true;
this.certDetailsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.certDetailsTextBox.Size = new System.Drawing.Size(451, 162);
this.certDetailsTextBox.TabIndex = 25;
//
// certDetailsButton
//
this.certDetailsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.certDetailsButton.Location = new System.Drawing.Point(14, 251);
this.certDetailsButton.Name = "certDetailsButton";
this.certDetailsButton.Size = new System.Drawing.Size(153, 23);
this.certDetailsButton.TabIndex = 24;
this.certDetailsButton.Text = "View Certificate Details...";
this.certDetailsButton.UseVisualStyleBackColor = true;
this.certDetailsButton.Click += new System.EventHandler(this.certDetailsButton_Click);
//
// label4
//
this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label4.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(128)))));
this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label4.ForeColor = System.Drawing.Color.Red;
this.label4.Location = new System.Drawing.Point(8, 6);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(468, 22);
this.label4.TabIndex = 23;
this.label4.Text = "WARNING - Invalid Server Certificate";
this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label5
//
this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label5.Location = new System.Drawing.Point(12, 34);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(454, 45);
this.label5.TabIndex = 22;
this.label5.Text = resources.GetString("label5.Text");
//
// backButton3
//
this.backButton3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.backButton3.Location = new System.Drawing.Point(316, 291);
this.backButton3.Name = "backButton3";
this.backButton3.Size = new System.Drawing.Size(75, 23);
this.backButton3.TabIndex = 20;
this.backButton3.Text = "Back";
this.backButton3.UseVisualStyleBackColor = true;
this.backButton3.Click += new System.EventHandler(this.backButton3_Click);
//
// nextButton3
//
this.nextButton3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.nextButton3.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
this.nextButton3.Location = new System.Drawing.Point(397, 291);
this.nextButton3.Name = "nextButton3";
this.nextButton3.Size = new System.Drawing.Size(75, 23);
this.nextButton3.TabIndex = 21;
this.nextButton3.Text = "Ignore";
this.nextButton3.UseVisualStyleBackColor = false;
this.nextButton3.Click += new System.EventHandler(this.nextButton3_Click);
//
// pictureBox5
//
this.pictureBox5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pictureBox5.Image = global::MeshCentralRouter.Properties.Resources.Empty_Banner;
this.pictureBox5.Location = new System.Drawing.Point(0, 282);
this.pictureBox5.Name = "pictureBox5";
this.pictureBox5.Size = new System.Drawing.Size(484, 40);
this.pictureBox5.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBox5.TabIndex = 10;
this.pictureBox5.TabStop = false;
//
// tabPage5
//
this.tabPage5.Controls.Add(this.panel4);
this.tabPage5.Location = new System.Drawing.Point(4, 25);
this.tabPage5.Name = "tabPage5";
this.tabPage5.Size = new System.Drawing.Size(484, 322);
this.tabPage5.TabIndex = 4;
this.tabPage5.Text = "Mappings";
this.tabPage5.UseVisualStyleBackColor = true;
//
// panel4
//
this.panel4.Controls.Add(this.settingsPictureBox);
this.panel4.Controls.Add(this.openWebSiteButton);
this.panel4.Controls.Add(this.helpPictureBox);
this.panel4.Controls.Add(this.addRelayButton);
this.panel4.Controls.Add(this.mapPanel);
this.panel4.Controls.Add(this.label6);
this.panel4.Controls.Add(this.addButton);
this.panel4.Controls.Add(this.backButton5);
this.panel4.Controls.Add(this.nextButton5);
this.panel4.Controls.Add(this.pictureBox7);
this.panel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel4.Location = new System.Drawing.Point(0, 0);
this.panel4.Name = "panel4";
this.panel4.Size = new System.Drawing.Size(484, 322);
this.panel4.TabIndex = 8;
//
// settingsPictureBox
//
this.settingsPictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.settingsPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
this.settingsPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("settingsPictureBox.Image")));
this.settingsPictureBox.Location = new System.Drawing.Point(15, 244);
this.settingsPictureBox.Name = "settingsPictureBox";
this.settingsPictureBox.Size = new System.Drawing.Size(20, 20);
this.settingsPictureBox.TabIndex = 54;
this.settingsPictureBox.TabStop = false;
this.settingsPictureBox.Click += new System.EventHandler(this.settingsPictureBox_Click);
//
// openWebSiteButton
//
this.openWebSiteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.openWebSiteButton.Location = new System.Drawing.Point(15, 291);
this.openWebSiteButton.Name = "openWebSiteButton";
this.openWebSiteButton.Size = new System.Drawing.Size(109, 23);
this.openWebSiteButton.TabIndex = 53;
this.openWebSiteButton.Text = "Open Web Site";
this.openWebSiteButton.UseVisualStyleBackColor = true;
this.openWebSiteButton.Visible = false;
this.openWebSiteButton.Click += new System.EventHandler(this.openWebSiteButton_Click);
//
// helpPictureBox
//
this.helpPictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.helpPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
this.helpPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("helpPictureBox.Image")));
this.helpPictureBox.Location = new System.Drawing.Point(230, 244);
this.helpPictureBox.Name = "helpPictureBox";
this.helpPictureBox.Size = new System.Drawing.Size(20, 20);
this.helpPictureBox.TabIndex = 5;
this.helpPictureBox.TabStop = false;
this.helpPictureBox.Click += new System.EventHandler(this.helpPictureBox_Click);
//
// addRelayButton
//
this.addRelayButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.addRelayButton.Enabled = false;
this.addRelayButton.Location = new System.Drawing.Point(258, 243);
this.addRelayButton.Name = "addRelayButton";
this.addRelayButton.Size = new System.Drawing.Size(100, 23);
this.addRelayButton.TabIndex = 52;
this.addRelayButton.Text = "Add Relay Map...";
this.addRelayButton.UseVisualStyleBackColor = true;
this.addRelayButton.Click += new System.EventHandler(this.addRelayMapButton_Click);
//
// mapPanel
//
this.mapPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.mapPanel.AutoScroll = true;
this.mapPanel.BackColor = System.Drawing.SystemColors.ControlLightLight;
this.mapPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.mapPanel.Controls.Add(this.noMapLabel);
this.mapPanel.Location = new System.Drawing.Point(15, 37);
this.mapPanel.Name = "mapPanel";
this.mapPanel.Size = new System.Drawing.Size(449, 200);
this.mapPanel.TabIndex = 49;
//
// noMapLabel
//
this.noMapLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.noMapLabel.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.noMapLabel.Location = new System.Drawing.Point(91, 76);
this.noMapLabel.Name = "noMapLabel";
this.noMapLabel.Size = new System.Drawing.Size(262, 44);
this.noMapLabel.TabIndex = 4;
this.noMapLabel.Text = "No Port Mappings\r\n\r\nClick \"Add\" to get started.";
this.noMapLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label6
//
this.label6.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label6.Location = new System.Drawing.Point(13, 12);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(461, 22);
this.label6.TabIndex = 51;
this.label6.Text = "Active port mappings";
//
// addButton
//
this.addButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.addButton.Enabled = false;
this.addButton.Location = new System.Drawing.Point(364, 243);
this.addButton.Name = "addButton";
this.addButton.Size = new System.Drawing.Size(100, 23);
this.addButton.TabIndex = 50;
this.addButton.Text = "Add Map...";
this.addButton.UseVisualStyleBackColor = true;
this.addButton.Click += new System.EventHandler(this.addButton_Click);
//
// backButton5
//
this.backButton5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.backButton5.Location = new System.Drawing.Point(316, 291);
this.backButton5.Name = "backButton5";
this.backButton5.Size = new System.Drawing.Size(75, 23);
this.backButton5.TabIndex = 35;
this.backButton5.Text = "Log out";
this.backButton5.UseVisualStyleBackColor = true;
this.backButton5.Click += new System.EventHandler(this.backButton5_Click);
//
// nextButton5
//
this.nextButton5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.nextButton5.Location = new System.Drawing.Point(397, 291);
this.nextButton5.Name = "nextButton5";
this.nextButton5.Size = new System.Drawing.Size(75, 23);
this.nextButton5.TabIndex = 36;
this.nextButton5.Text = "Close";
this.nextButton5.UseVisualStyleBackColor = true;
this.nextButton5.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
//
// pictureBox7
//
this.pictureBox7.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pictureBox7.Image = global::MeshCentralRouter.Properties.Resources.Empty_Banner;
this.pictureBox7.Location = new System.Drawing.Point(0, 282);
this.pictureBox7.Name = "pictureBox7";
this.pictureBox7.Size = new System.Drawing.Size(484, 40);
this.pictureBox7.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBox7.TabIndex = 10;
this.pictureBox7.TabStop = false;
//
// pictureBox1
//
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Top;
this.pictureBox1.Image = global::MeshCentralRouter.Properties.Resources.MC2_Banner;
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(492, 65);
this.pictureBox1.TabIndex = 2;
this.pictureBox1.TabStop = false;
//
// stateClearTimer
//
this.stateClearTimer.Interval = 5000;
this.stateClearTimer.Tick += new System.EventHandler(this.stateClearTimer_Tick);
//
// cookieRefreshTimer
//
this.cookieRefreshTimer.Interval = 240000;
this.cookieRefreshTimer.Tick += new System.EventHandler(this.cookieRefreshTimer_Tick);
//
// notifyIcon
//
this.notifyIcon.ContextMenuStrip = this.trayIconContextMenuStrip;
this.notifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon.Icon")));
this.notifyIcon.Text = "MeshCentral Router";
this.notifyIcon.DoubleClick += new System.EventHandler(this.notifyIcon_DoubleClick);
//
// trayIconContextMenuStrip
//
this.trayIconContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.openToolStripMenuItem,
this.toolStripMenuItem1,
this.exitToolStripMenuItem});
this.trayIconContextMenuStrip.Name = "trayIconContextMenuStrip";
this.trayIconContextMenuStrip.Size = new System.Drawing.Size(113, 54);
//
// openToolStripMenuItem
//
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
this.openToolStripMenuItem.Size = new System.Drawing.Size(112, 22);
this.openToolStripMenuItem.Text = "&Open...";
this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(109, 6);
//
// exitToolStripMenuItem
//
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
this.exitToolStripMenuItem.Size = new System.Drawing.Size(112, 22);
this.exitToolStripMenuItem.Text = "E&xit";
this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click_1);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(492, 416);
this.Controls.Add(this.panel5);
this.DoubleBuffered = true;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.Name = "MainForm";
this.Text = " MeshCentral Router";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
this.Load += new System.EventHandler(this.MainForm_Load);
this.panel5.ResumeLayout(false);
this.mainPanel.ResumeLayout(false);
this.mainTabControl.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
this.tabPage2.ResumeLayout(false);
this.panel2.ResumeLayout(false);
this.panel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox6)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).EndInit();
this.tabPage3.ResumeLayout(false);
this.panel3.ResumeLayout(false);
this.panel3.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox5)).EndInit();
this.tabPage5.ResumeLayout(false);
this.panel4.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.settingsPictureBox)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.helpPictureBox)).EndInit();
this.mapPanel.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pictureBox7)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.trayIconContextMenuStrip.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel panel5;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.TabControl mainTabControl;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Label versionLabel;
private System.Windows.Forms.Button nextButton1;
private System.Windows.Forms.PictureBox pictureBox3;
private System.Windows.Forms.PictureBox pictureBox2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TabPage tabPage2;
private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.Button backButton2;
private System.Windows.Forms.Button nextButton2;
private System.Windows.Forms.PictureBox pictureBox4;
private System.Windows.Forms.TabPage tabPage3;
private System.Windows.Forms.Panel panel3;
private System.Windows.Forms.Button backButton3;
private System.Windows.Forms.Button nextButton3;
private System.Windows.Forms.PictureBox pictureBox5;
private System.Windows.Forms.TabPage tabPage5;
private System.Windows.Forms.Panel panel4;
private System.Windows.Forms.Button backButton5;
private System.Windows.Forms.Button nextButton5;
private System.Windows.Forms.PictureBox pictureBox7;
private System.Windows.Forms.Panel mainPanel;
private System.Windows.Forms.LinkLabel licenseLinkLabel;
private System.Windows.Forms.ComboBox serverNameComboBox;
private System.Windows.Forms.TextBox userNameTextBox;
private System.Windows.Forms.TextBox passwordTextBox;
private System.Windows.Forms.Label label28;
private System.Windows.Forms.Label label27;
private System.Windows.Forms.Label label26;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox tokenTextBox;
private System.Windows.Forms.PictureBox pictureBox6;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Panel mapPanel;
private System.Windows.Forms.Label noMapLabel;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Button addButton;
private System.Windows.Forms.Label stateLabel;
private System.Windows.Forms.Timer stateClearTimer;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Button certDetailsButton;
private System.Windows.Forms.TextBox certDetailsTextBox;
private System.Windows.Forms.Button addRelayButton;
private System.Windows.Forms.PictureBox helpPictureBox;
private System.Windows.Forms.Button openWebSiteButton;
private System.Windows.Forms.Timer cookieRefreshTimer;
private System.Windows.Forms.NotifyIcon notifyIcon;
private System.Windows.Forms.ContextMenuStrip trayIconContextMenuStrip;
private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
private System.Windows.Forms.PictureBox settingsPictureBox;
}
}

610
MainForm.cs Normal file
View File

@@ -0,0 +1,610 @@
/*
Copyright 2009-2017 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using System;
using System.Net;
using System.Reflection;
using System.Collections;
using System.Windows.Forms;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32;
namespace MeshCentralRouter
{
public partial class MainForm : Form
{
private int currentPanel = 0;
private DateTime refreshTime = DateTime.Now;
private MeshCentralServer meshcentral = null;
private X509Certificate2 lastBadConnectCert = null;
private string title;
private string[] args;
private bool debug = false;
private bool autoLogin = false;
private bool ignoreCert = false;
private bool inaddrany = false;
private bool forceExit = false;
public static void saveToRegistry(string name, string value)
{
try { Registry.SetValue(@"HKEY_CURRENT_USER\SOFTWARE\OpenSource\MeshRouter", name, value); } catch (Exception) { }
}
public static string loadFromRegistry(string name)
{
try { return Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\OpenSource\MeshRouter", name, "").ToString(); } catch (Exception) { return ""; }
}
public MainForm(string[] args)
{
this.args = args;
InitializeComponent();
mainPanel.Controls.Add(panel1);
mainPanel.Controls.Add(panel2);
mainPanel.Controls.Add(panel3);
mainPanel.Controls.Add(panel4);
pictureBox1.SendToBack();
Version version = Assembly.GetEntryAssembly().GetName().Version;
versionLabel.Text = "v" + version.Major + "." + version.Minor + "." + version.Build;
serverNameComboBox.Text = loadFromRegistry("ServerName");
userNameTextBox.Text = loadFromRegistry("UserName");
title = this.Text;
int argflags = 0;
foreach (string arg in this.args) {
if (arg.ToLower() == "-debug") { debug = true; }
if (arg.ToLower() == "-ignorecert") { ignoreCert = true; }
if (arg.ToLower() == "-all") { inaddrany = true; }
if (arg.ToLower() == "-inaddrany") { inaddrany = true; }
if (arg.ToLower() == "-tray") { notifyIcon.Visible = true; this.ShowInTaskbar = false; this.MinimizeBox = false; }
if (arg.Length > 6 && arg.Substring(0, 6).ToLower() == "-host:") { serverNameComboBox.Text = arg.Substring(6); argflags |= 1; }
if (arg.Length > 6 && arg.Substring(0, 6).ToLower() == "-user:") { userNameTextBox.Text = arg.Substring(6); argflags |= 2; }
if (arg.Length > 6 && arg.Substring(0, 6).ToLower() == "-pass:") { passwordTextBox.Text = arg.Substring(6); argflags |= 4; }
}
autoLogin = (argflags == 7);
}
private void setPanel(int newPanel)
{
if (currentPanel == newPanel) return;
if (newPanel == 4) { updatePanel4(); }
panel1.Visible = (newPanel == 1);
panel2.Visible = (newPanel == 2);
panel3.Visible = (newPanel == 3);
panel4.Visible = (newPanel == 4);
currentPanel = newPanel;
}
private void MainForm_Load(object sender, EventArgs e)
{
//Text += " - v" + Application.ProductVersion;
//installPathTextBox.Text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Open Source", "MeshCentral");
//serverModeComboBox.SelectedIndex = 0;
//windowColor = serverNameTextBox.BackColor;
setPanel(1);
updatePanel1(null, null);
// Start the multicast scanner
//scanner = new MeshDiscovery();
//scanner.OnNotify += Scanner_OnNotify;
//scanner.MulticastPing();
if (autoLogin) { nextButton1_Click(null, null); }
}
private void updatePanel1(object sender, EventArgs e)
{
bool ok = true;
if (serverNameComboBox.Text.Length == 0) { ok = false; }
if (userNameTextBox.Text.Length == 0) { ok = false; }
if (passwordTextBox.Text.Length == 0) { ok = false; }
nextButton1.Enabled = ok;
}
private void updatePanel2(object sender, EventArgs e)
{
bool ok = true;
if (tokenTextBox.Text.Length == 0) { ok = false; }
nextButton2.Enabled = ok;
}
private void updatePanel4()
{
//ServerState s = readServerStateEx(installPathTextBox.Text);
//if (s.state == ServerStateEnum.Running) { label7.Text = "MeshCentral is running this computer."; }
//else if (s.state == ServerStateEnum.Unknown) { label7.Text = "MeshCentral is installed on this computer."; }
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
forceExit = true;
Application.Exit();
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if ((notifyIcon.Visible == true) && (forceExit == false)) { e.Cancel = true; Visible = false; }
}
private void backButton5_Click(object sender, EventArgs e)
{
meshcentral.disconnect();
}
private void nextButton1_Click(object sender, EventArgs e)
{
// Attempt to login
addButton.Enabled = false;
addRelayButton.Enabled = false;
openWebSiteButton.Visible = false;
Uri serverurl = new Uri("wss://" + serverNameComboBox.Text + "/control.ashx");
meshcentral = new MeshCentralServer();
meshcentral.debug = debug;
meshcentral.ignoreCert = ignoreCert;
meshcentral.onStateChanged += Meshcentral_onStateChanged;
meshcentral.onNodesChanged += Meshcentral_onNodesChanged;
meshcentral.onLoginTokenChanged += Meshcentral_onLoginTokenChanged;
if (lastBadConnectCert != null) { meshcentral.okCertHash = lastBadConnectCert.GetCertHashString(); }
meshcentral.connect(serverurl, userNameTextBox.Text, passwordTextBox.Text, null);
}
private void nextButton3_Click(object sender, EventArgs e)
{
// Attempt to login, ignore bad cert.
addButton.Enabled = false;
addRelayButton.Enabled = false;
openWebSiteButton.Visible = false;
Uri serverurl = new Uri("wss://" + serverNameComboBox.Text + "/control.ashx");
meshcentral = new MeshCentralServer();
meshcentral.debug = debug;
meshcentral.ignoreCert = ignoreCert;
meshcentral.onStateChanged += Meshcentral_onStateChanged;
meshcentral.onNodesChanged += Meshcentral_onNodesChanged;
meshcentral.onLoginTokenChanged += Meshcentral_onLoginTokenChanged;
meshcentral.okCertHash = lastBadConnectCert.GetCertHashString();
meshcentral.connect(serverurl, userNameTextBox.Text, passwordTextBox.Text, null);
}
private void Meshcentral_onLoginTokenChanged()
{
if (this.InvokeRequired) { this.Invoke(new MeshCentralServer.onLoginTokenChangedHandler(Meshcentral_onLoginTokenChanged)); return; }
openWebSiteButton.Visible = true;
}
private void Meshcentral_onNodesChanged()
{
if (this.InvokeRequired) { this.Invoke(new MeshCentralServer.onNodeListChangedHandler(Meshcentral_onNodesChanged)); return; }
addRelayButton.Enabled = addButton.Enabled = ((meshcentral.nodes != null) && (meshcentral.nodes.Count > 0));
// Update any active mappings
foreach (Control c in mapPanel.Controls)
{
if (c.GetType() == typeof(MapUserControl))
{
MapUserControl cc = (MapUserControl)c;
cc.UpdateInfo();
}
}
addArgMappings();
reconnectUdpMaps();
}
private void Meshcentral_onStateChanged(int state)
{
if (this.InvokeRequired) { this.Invoke(new MeshCentralServer.onStateChangedHandler(Meshcentral_onStateChanged), state); return; }
if (state == 0) {
if (meshcentral.disconnectMsg == "tokenrequired") { tokenTextBox.Text = ""; setPanel(2); tokenTextBox.Focus(); } else { setPanel(1); }
if ((meshcentral.disconnectMsg != null) && meshcentral.disconnectMsg.StartsWith("noauth")) { stateLabel.Text = "Invalid username or password"; stateLabel.Visible = true; stateClearTimer.Enabled = true; serverNameComboBox.Focus(); }
else if (meshcentral.disconnectMsg == "cert") {
lastBadConnectCert = meshcentral.disconnectCert;
certDetailsTextBox.Text = "---Issuer---\r\n" + lastBadConnectCert.Issuer.Replace(", ", "\r\n") + "\r\n\r\n---Subject---\r\n" + lastBadConnectCert.Subject.Replace(", ", "\r\n");
setPanel(3);
certDetailsButton.Focus();
}
else if (meshcentral.disconnectMsg == null) { stateLabel.Text = "Unable to connect"; stateLabel.Visible = true; stateClearTimer.Enabled = true; serverNameComboBox.Focus(); }
// Clean up the UI
nextButton1.Enabled = true;
serverNameComboBox.Enabled = true;
userNameTextBox.Enabled = true;
passwordTextBox.Enabled = true;
this.Text = title;
// Clean up all mappings
foreach (Control c in mapPanel.Controls) {
if (c.GetType() == typeof(MapUserControl)) {
((MapUserControl)c).Dispose();
((MapUserControl)c).Dispose();
mapPanel.Controls.Remove(c);
}
}
noMapLabel.Visible = true;
// Clean up the server
cookieRefreshTimer.Enabled = false;
meshcentral.onStateChanged -= Meshcentral_onStateChanged;
meshcentral.onNodesChanged -= Meshcentral_onNodesChanged;
meshcentral = null;
} else if (state == 1) {
stateLabel.Visible = false;
//setPanel(1);
nextButton1.Enabled = false;
serverNameComboBox.Enabled = false;
userNameTextBox.Enabled = false;
passwordTextBox.Enabled = false;
cookieRefreshTimer.Enabled = false;
} else if (state == 2) {
meshcentral.disconnectMsg = "connected";
stateLabel.Visible = false;
setPanel(4);
addButton.Focus();
saveToRegistry("ServerName", serverNameComboBox.Text);
saveToRegistry("UserName", userNameTextBox.Text);
this.Text = title + " - " + userNameTextBox.Text;
cookieRefreshTimer.Enabled = true;
}
}
private void reconnectUdpMaps()
{
foreach (Control c in mapPanel.Controls)
{
if (c == noMapLabel) continue;
MapUserControl map = (MapUserControl)c;
if ((map.protocol == 2) && (map.mapper.totalConnectCounter == 0))
{
// This is an unconnected UDP map, check if the target node is connected.
foreach (NodeClass n in meshcentral.nodes.Values) {
if ((map.node == n) && ((n.conn & 1) != 0))
{
// Reconnect the UDP map
map.Start();
}
}
}
}
}
private ArrayList processedArgs = new ArrayList();
private void addArgMappings()
{
// Add mappings
for (int i = 0; i < this.args.Length; i++)
{
if (processedArgs.Contains(i)) { continue; } // This map was already added
string arg = this.args[i];
if (arg.Length > 5 && arg.Substring(0, 5).ToLower() == "-map:")
{
string[] x = arg.Substring(5).Split(':');
if (x.Length == 5)
{
// Protocol
int protocol = 0;
if (x[0].ToLower() == "tcp") { protocol = 1; }
if (x[0].ToLower() == "udp") { protocol = 2; }
if (protocol == 0) continue;
// LocalPort
ushort localPort = 0;
if (ushort.TryParse(x[1], out localPort) == false) continue;
// Node
string nodename = x[2];
NodeClass node = null;
foreach (NodeClass n in meshcentral.nodes.Values) { if (((n.conn & 1) != 0) && (n.name.ToLower() == nodename.ToLower())) { node = n; } }
if (node == null) continue;
// AppId
int appId = 0;
if (protocol == 1)
{
if (x[3].ToLower() == "http") { appId = 1; }
else if (x[3].ToLower() == "https") { appId = 2; }
else if (x[3].ToLower() == "rdp") { appId = 3; }
else if (x[3].ToLower() == "putty") { appId = 4; }
else if (x[3].ToLower() == "winscp") { appId = 5; }
}
// RemotePort
ushort remotePort = 0;
if (ushort.TryParse(x[4], out remotePort) == false) continue;
// Add a new port map
MapUserControl map = new MapUserControl();
map.xdebug = debug;
map.inaddrany = inaddrany;
map.protocol = protocol;
map.localPort = (int)localPort;
map.remotePort = (int)remotePort;
map.appId = appId;
map.node = node;
map.host = serverNameComboBox.Text;
map.authCookie = meshcentral.authCookie;
map.certhash = meshcentral.wshash;
map.parent = this;
map.Dock = DockStyle.Top;
map.Start();
mapPanel.Controls.Add(map);
noMapLabel.Visible = false;
processedArgs.Add(i);
}
}
else if (arg.Length > 10 && arg.Substring(0, 10).ToLower() == "-relaymap:")
{
string[] x = arg.Substring(10).Split(':');
if (x.Length == 6)
{
// Protocol
int protocol = 0;
if (x[0].ToLower() == "tcp") { protocol = 1; }
if (x[0].ToLower() == "udp") { protocol = 2; }
if (protocol == 0) continue;
// LocalPort
ushort localPort = 0;
if (ushort.TryParse(x[1], out localPort) == false) continue;
// Node
string nodename = x[2];
NodeClass node = null;
foreach (NodeClass n in meshcentral.nodes.Values) { if (((n.conn & 1) != 0) && (n.name.ToLower() == nodename.ToLower())) { node = n; } }
if (node == null) continue;
// AppId
int appId = 0;
if (protocol == 1)
{
if (x[3].ToLower() == "http") { appId = 1; }
else if (x[3].ToLower() == "https") { appId = 2; }
else if (x[3].ToLower() == "rdp") { appId = 3; }
else if (x[3].ToLower() == "putty") { appId = 4; }
else if (x[3].ToLower() == "winscp") { appId = 5; }
}
// Remote host
IPAddress remoteIp;
if (IPAddress.TryParse(x[4], out remoteIp) == false) continue;
// RemotePort
ushort remotePort = 0;
if (ushort.TryParse(x[5], out remotePort) == false) continue;
// Add a new port map
MapUserControl map = new MapUserControl();
map.xdebug = debug;
map.inaddrany = inaddrany;
map.protocol = protocol;
map.localPort = (int)localPort;
map.remoteIP = remoteIp.ToString();
map.remotePort = (int)remotePort;
map.appId = appId;
map.node = node;
map.host = serverNameComboBox.Text;
map.authCookie = meshcentral.authCookie;
map.certhash = meshcentral.wshash;
map.parent = this;
map.Dock = DockStyle.Top;
map.Start();
mapPanel.Controls.Add(map);
noMapLabel.Visible = false;
processedArgs.Add(i);
}
}
}
}
private void addButton_Click(object sender, EventArgs e)
{
AddPortMapForm form = new AddPortMapForm(meshcentral);
if (form.ShowDialog(this) == DialogResult.OK)
{
// Add a new port map
MapUserControl map = new MapUserControl();
map.xdebug = debug;
map.inaddrany = inaddrany;
map.protocol = form.getProtocol();
map.localPort = form.getLocalPort();
map.remotePort = form.getRemotePort();
map.appId = form.getAppId();
map.node = form.getNode();
map.host = serverNameComboBox.Text;
map.authCookie = meshcentral.authCookie;
map.certhash = meshcentral.wshash;
map.parent = this;
map.Dock = DockStyle.Top;
map.Start();
mapPanel.Controls.Add(map);
noMapLabel.Visible = false;
}
}
public void removeMap(MapUserControl map)
{
mapPanel.Controls.Remove(map);
noMapLabel.Visible = (mapPanel.Controls.Count <= 1);
}
private void backButton2_Click(object sender, EventArgs e)
{
setPanel(1);
}
private void nextButton2_Click(object sender, EventArgs e)
{
// Attempt to login with token
addButton.Enabled = false;
addRelayButton.Enabled = false;
openWebSiteButton.Visible = false;
Uri serverurl = new Uri("wss://" + serverNameComboBox.Text + "/control.ashx");
meshcentral = new MeshCentralServer();
meshcentral.ignoreCert = ignoreCert;
if (lastBadConnectCert != null) { meshcentral.okCertHash = lastBadConnectCert.GetCertHashString(); }
meshcentral.onStateChanged += Meshcentral_onStateChanged;
meshcentral.onNodesChanged += Meshcentral_onNodesChanged;
meshcentral.onLoginTokenChanged += Meshcentral_onLoginTokenChanged;
meshcentral.connect(serverurl, userNameTextBox.Text, passwordTextBox.Text, tokenTextBox.Text.Replace(" ", ""));
}
private void tokenTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13) { nextButton2_Click(this, null); e.Handled = true; }
}
private void serverNameComboBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13) { userNameTextBox.Focus(); e.Handled = true; }
}
private void userNameTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13) { passwordTextBox.Focus(); e.Handled = true; }
}
private void passwordTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13) { e.Handled = true; if (nextButton1.Enabled) { nextButton1_Click(this, null); } }
}
private void stateClearTimer_Tick(object sender, EventArgs e)
{
stateLabel.Visible = false;
stateClearTimer.Enabled = false;
}
private void licenseLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start("https://www.apache.org/licenses/LICENSE-2.0.html");
}
private void backButton3_Click(object sender, EventArgs e)
{
setPanel(1);
}
private void certDetailsButton_Click(object sender, EventArgs e)
{
X509Certificate2UI.DisplayCertificate(lastBadConnectCert);
}
private void addRelayMapButton_Click(object sender, EventArgs e)
{
AddRelayMapForm form = new AddRelayMapForm(meshcentral);
if (form.ShowDialog(this) == DialogResult.OK)
{
// Add a new port map
MapUserControl map = new MapUserControl();
map.xdebug = debug;
map.inaddrany = inaddrany;
map.protocol = form.getProtocol();
map.localPort = form.getLocalPort();
map.remotePort = form.getRemotePort();
map.remoteIP = form.getRemoteIP();
map.appId = form.getAppId();
map.node = form.getNode();
map.host = serverNameComboBox.Text;
map.authCookie = meshcentral.authCookie;
map.certhash = meshcentral.wshash;
map.parent = this;
map.Dock = DockStyle.Top;
map.Start();
mapPanel.Controls.Add(map);
noMapLabel.Visible = false;
}
}
private void helpPictureBox_Click(object sender, EventArgs e)
{
new MappingHelpForm().ShowDialog(this);
}
private void openWebSiteButton_Click(object sender, EventArgs e)
{
if (meshcentral.loginCookie != null) {
Uri serverurl = new Uri("https://" + serverNameComboBox.Text + "?login=" + meshcentral.loginCookie);
System.Diagnostics.Process.Start(serverurl.ToString());
}
}
private void cookieRefreshTimer_Tick(object sender, EventArgs e)
{
meshcentral.refreshCookies();
}
private void notifyIcon_DoubleClick(object sender, EventArgs e)
{
if (this.Visible == false) { this.Visible = true; } else { this.Visible = false; this.Focus(); }
}
private void exitToolStripMenuItem_Click_1(object sender, EventArgs e)
{
forceExit = true;
Application.Exit();
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Normal;
this.Visible = true;
this.Focus();
}
private void settingsPictureBox_Click(object sender, EventArgs e)
{
SettingsForm f = new SettingsForm();
f.BindAllInterfaces = inaddrany;
f.ShowSystemTray = (notifyIcon.Visible == true);
if (f.ShowDialog(this) == DialogResult.OK)
{
inaddrany = f.BindAllInterfaces;
if (f.ShowSystemTray) {
notifyIcon.Visible = true;
this.ShowInTaskbar = false;
this.MinimizeBox = false;
} else {
notifyIcon.Visible = false;
this.ShowInTaskbar = true;
this.MinimizeBox = true;
}
}
}
/*
private delegate void displayMessageHandler(string msg, int buttons, string extra, int progress);
private void displayMessage(string msg, int buttons = 0, string extra = "", int progress = 0)
{
if (this.InvokeRequired) { this.Invoke(new displayMessageHandler(displayMessage), msg, buttons, extra, progress); return; }
if (msg != null) { statusLabel.Text = msg; loadingLabel.Text = msg; }
statusLabel2.Text = extra;
label4.Text = extra;
nextButton3.Enabled = (buttons == 1);
backButton3.Enabled = (buttons == 2);
mainProgressBar.Visible = (progress > 0);
if (progress >= 0) { mainProgressBar.Value = progress; }
if (buttons == 3) { setPanel(6); }
linkLabel1.Visible = (progress == -1);
advConfigButton.Visible = (progress == -1);
}
*/
}
}

3557
MainForm.resx Normal file

File diff suppressed because it is too large Load Diff

132
MapUserControl.Designer.cs generated Normal file
View File

@@ -0,0 +1,132 @@
namespace MeshCentralRouter
{
partial class MapUserControl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MapUserControl));
this.devicePictureBox = new System.Windows.Forms.PictureBox();
this.deviceNameLabel = new System.Windows.Forms.Label();
this.routingStatusLabel = new System.Windows.Forms.Label();
this.appButton = new System.Windows.Forms.Button();
this.closeButton = new System.Windows.Forms.Button();
this.deviceImageList = new System.Windows.Forms.ImageList(this.components);
((System.ComponentModel.ISupportInitialize)(this.devicePictureBox)).BeginInit();
this.SuspendLayout();
//
// devicePictureBox
//
this.devicePictureBox.Image = global::MeshCentralRouter.Properties.Resources.icons01;
this.devicePictureBox.Location = new System.Drawing.Point(6, 3);
this.devicePictureBox.Name = "devicePictureBox";
this.devicePictureBox.Size = new System.Drawing.Size(50, 50);
this.devicePictureBox.TabIndex = 0;
this.devicePictureBox.TabStop = false;
//
// deviceNameLabel
//
this.deviceNameLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.deviceNameLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.deviceNameLabel.Location = new System.Drawing.Point(62, 12);
this.deviceNameLabel.Name = "deviceNameLabel";
this.deviceNameLabel.Size = new System.Drawing.Size(290, 15);
this.deviceNameLabel.TabIndex = 1;
this.deviceNameLabel.Text = "ComputerName";
//
// routingStatusLabel
//
this.routingStatusLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.routingStatusLabel.Location = new System.Drawing.Point(62, 32);
this.routingStatusLabel.Name = "routingStatusLabel";
this.routingStatusLabel.Size = new System.Drawing.Size(290, 15);
this.routingStatusLabel.TabIndex = 2;
this.routingStatusLabel.Text = "Routing Status";
//
// appButton
//
this.appButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.appButton.Location = new System.Drawing.Point(358, 6);
this.appButton.Name = "appButton";
this.appButton.Size = new System.Drawing.Size(75, 23);
this.appButton.TabIndex = 3;
this.appButton.Text = "Open...";
this.appButton.UseVisualStyleBackColor = true;
this.appButton.Click += new System.EventHandler(this.appButton_Click);
//
// closeButton
//
this.closeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.closeButton.Location = new System.Drawing.Point(358, 30);
this.closeButton.Name = "closeButton";
this.closeButton.Size = new System.Drawing.Size(75, 23);
this.closeButton.TabIndex = 4;
this.closeButton.Text = "Remove";
this.closeButton.UseVisualStyleBackColor = true;
this.closeButton.Click += new System.EventHandler(this.closeButton_Click);
//
// deviceImageList
//
this.deviceImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("deviceImageList.ImageStream")));
this.deviceImageList.TransparentColor = System.Drawing.Color.Transparent;
this.deviceImageList.Images.SetKeyName(0, "icons01.png");
this.deviceImageList.Images.SetKeyName(1, "icons02.png");
this.deviceImageList.Images.SetKeyName(2, "icons03.png");
this.deviceImageList.Images.SetKeyName(3, "icons04.png");
this.deviceImageList.Images.SetKeyName(4, "icons05.png");
this.deviceImageList.Images.SetKeyName(5, "icons06.png");
//
// MapUserControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.ControlLight;
this.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.Controls.Add(this.closeButton);
this.Controls.Add(this.appButton);
this.Controls.Add(this.routingStatusLabel);
this.Controls.Add(this.deviceNameLabel);
this.Controls.Add(this.devicePictureBox);
this.Name = "MapUserControl";
this.Size = new System.Drawing.Size(441, 63);
((System.ComponentModel.ISupportInitialize)(this.devicePictureBox)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PictureBox devicePictureBox;
private System.Windows.Forms.Label deviceNameLabel;
private System.Windows.Forms.Label routingStatusLabel;
private System.Windows.Forms.Button appButton;
private System.Windows.Forms.Button closeButton;
private System.Windows.Forms.ImageList deviceImageList;
}
}

173
MapUserControl.cs Normal file
View File

@@ -0,0 +1,173 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32;
namespace MeshCentralRouter
{
public partial class MapUserControl : UserControl
{
public int protocol;
public int localPort;
public string remoteIP = null;
public int remotePort;
public int appId;
public NodeClass node;
public MainForm parent;
public MeshMapper mapper;
public string host;
public string authCookie;
public string certhash;
public bool xdebug = false;
public bool inaddrany = false;
public static void saveToRegistry(string name, string value)
{
try { Registry.SetValue(@"HKEY_CURRENT_USER\SOFTWARE\OpenSource\MeshRouter", name, value); } catch (Exception) { }
}
public static string loadFromRegistry(string name)
{
try { return Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\OpenSource\MeshRouter", name, "").ToString(); } catch (Exception) { return ""; }
}
public MapUserControl()
{
InitializeComponent();
}
public void UpdateInfo()
{
deviceNameLabel.Text = node.name;
devicePictureBox.Image = deviceImageList.Images[node.icon - 1];
}
public void Start()
{
routingStatusLabel.Text = "Starting...";
appButton.Enabled = (appId != 0);
mapper = new MeshMapper();
mapper.xdebug = xdebug;
mapper.inaddrany = inaddrany;
mapper.certhash = certhash;
mapper.onStateMsgChanged += Mapper_onStateMsgChanged;
string serverurl = "wss://" + host + "/meshrelay.ashx?auth=" + Uri.EscapeDataString(authCookie) + "&nodeid=" + node.nodeid;
if (protocol == 1) {
serverurl += ("&tcpport=" + remotePort);
if (remoteIP != null) { serverurl += "&tcpaddr=" + remoteIP; }
} else if (protocol == 2) {
serverurl += ("&udpport=" + remotePort);
if (remoteIP != null) { serverurl += "&udpaddr=" + remoteIP; }
}
mapper.start(protocol, localPort, serverurl, remotePort, remoteIP);
UpdateInfo();
}
public void Stop()
{
routingStatusLabel.Text = "Stopped.";
appButton.Enabled = false;
mapper.onStateMsgChanged -= Mapper_onStateMsgChanged;
mapper.stop();
mapper = null;
}
private void Mapper_onStateMsgChanged(string statemsg)
{
if (this.InvokeRequired) { this.Invoke(new MeshMapper.onStateMsgChangedHandler(Mapper_onStateMsgChanged), statemsg); return; }
if (protocol == 2) {
statemsg = "UDP: " + statemsg;
} else {
if (appId == 1) { statemsg = "HTTP: " + statemsg; }
else if (appId == 2) { statemsg = "HTTPS: " + statemsg; }
else if (appId == 3) { statemsg = "RDP: " + statemsg; }
else if (appId == 4) { statemsg = "PuTTY: " + statemsg; }
else if (appId == 5) { statemsg = "WinSCP: " + statemsg; }
else { statemsg = "TCP: " + statemsg; }
}
routingStatusLabel.Text = statemsg;
}
private void appButton_Click(object sender, EventArgs e)
{
if (appId == 1) { System.Diagnostics.Process.Start("http://localhost:" + mapper.localport); }
if (appId == 2) { System.Diagnostics.Process.Start("https://localhost:" + mapper.localport); }
if (appId == 3)
{
System.Diagnostics.Process proc = null;
string cmd = System.Environment.GetFolderPath(System.Environment.SpecialFolder.System) + "\\mstsc.exe";
string tfile = Path.Combine(Path.GetTempPath(), "MeshRdpFile.rdp");
string[] f = null;
try { if (File.Exists(tfile)) f = File.ReadAllLines(tfile); } catch (Exception) { }
if (f != null)
{
List<string> f2 = new List<string>();
foreach (string fx in f) { if (!fx.StartsWith("full address")) f2.Add(fx); }
f2.Add(string.Format("full address:s:127.0.0.1:{0}", mapper.localport));
File.WriteAllLines(tfile, f2.ToArray());
}
else
{
File.WriteAllText(tfile, string.Format("full address:s:127.0.0.1:{0}", mapper.localport));
}
string args = "/edit:\"" + tfile + "\"";
// Launch the process
try { proc = System.Diagnostics.Process.Start(cmd, args); }
catch (System.ComponentModel.Win32Exception) { }
}
if (appId == 4)
{
using (AppLaunchForm f = new AppLaunchForm())
{
System.Diagnostics.Process proc = null;
f.SetAppName("PuTTY SSH client");
f.SetAppLink("http://www.chiark.greenend.org.uk/~sgtatham/putty/");
f.SetAppPath(loadFromRegistry("PuttyPath"));
if (f.ShowDialog(this) == DialogResult.OK)
{
saveToRegistry("PuttyPath", f.GetAppPath());
string args = "-ssh 127.0.0.1 -P " + mapper.localport;
// Launch the process
try { proc = System.Diagnostics.Process.Start(f.GetAppPath(), args); }
catch (System.ComponentModel.Win32Exception) { }
}
}
}
if (appId == 5)
{
using (AppLaunchForm f = new AppLaunchForm())
{
System.Diagnostics.Process proc = null;
f.SetAppName("WinSCP client");
f.SetAppLink("http://winscp.net/");
f.SetAppPath(loadFromRegistry("WinSCPPath"));
if (f.ShowDialog(this) == DialogResult.OK)
{
saveToRegistry("WinSCPPath", f.GetAppPath());
string args = "scp://127.0.0.1:" + mapper.localport;
// Launch the process
try { proc = System.Diagnostics.Process.Start(f.GetAppPath(), args); }
catch (System.ComponentModel.Win32Exception) { }
}
}
}
}
private void closeButton_Click(object sender, EventArgs e)
{
if (mapper != null)
{
mapper.stop();
mapper = null;
}
parent.removeMap(this);
}
}
}

586
MapUserControl.resx Normal file
View File

@@ -0,0 +1,586 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="deviceImageList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="deviceImageList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACi
agAAAk1TRnQBSQFMAgEBBgEAAQgBAAEIAQABMgEAATIBAAT/AREBAAj/AUIBTQE2BwABNgMAASgDAAHI
AwABZAMAAQEBAAEQBQABQAGc/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A8wAB3gF7Ab0BdwG9
AXcBvQF3Ad4Be/8AfQAB3gF7Ab0BdwG9AXcBnAFzAVoBawE5AWcBGAFjARgBYwH3AV4BGAFjAXsBbwG9
AXdaAAHeAXsB3gF7Ab0BdwHeAXv/AA8AAd4BewG9AXcBnAFzAXsBbwE5AWcBGAFjAdYBWgGUAVIBlAFS
AbUBVgGUAVIBlAFSAZQBUgEQAUIBcwFOARgBYwGcAXMB3gF7SgAB3gF7Ab0BdwF7AW8BewFvAVoBawFa
AWsBWgFrAVoBawF7AW8BOQFnAVoBawG9AXf/AAMAAd4BewG9AXcBnAFzAXsBbwE5AWcB9wFeAbUBVgGU
AVIBlAFSAXIBTgFzAU4BlAFSAbUBVgH0AVYBswFSAXMBTgFzAU4BlAFSAc4BOQEQAUIBtQFWAVoBawG9
AXc+AAHeAXsBnAFzATkBZwHVAVYBUgFKAe8BPQGMAjEBRgFaAWsBWgFrAVoBawFaAWsBewFvAb0BdwGc
AXMBGAFjAfcBXgEYAWMBnAFz+AAB3gF7Ab0BdwF7AW8BOQFnAfcBXgG1AVYBlAFSAXMBTgGUAVIBtQFW
AbYBVgH3AV4B+AFeAfgBXgH4AV4B9wFeASwBOgFhAQgBpQEUAXMBTgGUAVIBcwFOAe8BPQHOATkBcwFO
ARgBYwGcAXMB3gF7NAABnAFzAfcBXgFSAUoBzgE5AWsBLQEpASUBCAEhAecBHAHGARgBhAEQAe8BPQE5
AWcBGAFjAfcBXgH3AV4B9wFeAXwBbwF7AW8B9gFeAfcBXgH2AV4BtQFWAfcBXgGcAXPsAAHeAXsBvQF3
AZwBcwFaAWsBGAFjAdYBWgGUAVIBkwFSAXMBTgG1AVYB1gFaARkBYwFaAWsBWwFrAVsBawFbAWsBOgFn
ARgBYwH4AV4BlQFWAUcBLgFAAQABIgEEATIBRgFSAUoBcwFOAVIBSgExAUYBzgE5ARABQgHWAloBawG9
AXcsAAGcAW8B1gFaARABQgFrAS0BCAEhAecBHAHGARgBxgEYASkBIQGlARQB5wEYAQoBIgEhAQQBawEt
AZQBUgExAUYBMQFGATEBRgExAUYB1gFaAbUBVgEwAUYBcwFOAbUBVgHWAVoB1QFaAZQBUgH3AV4BvQF3
5gAB3gJ7AW8BGAFjAdYBWgG1AVYBlAFSAbUBVgHWAVoBOQFnAXwBbwGdAXMBvgF3AZ4BcwGdAXMBfAFv
AVsBawE6AWcBOQFnARkBYwH4AWIBlQFSAewBQgFAAQQBIQEEATEBRgFSAUoBUgFKARABQgFSAUoBUgFK
Ae8BPQHOATkBcwFOARgBYwGcAXMB3gF7IgABnAFzAdYBWgHvAT0BSQEpAecBHAHGARgBpQEUAYQBEAEo
AR0BqQEdASIBCAHrASUBwwEMAUIBBAHmARACAAEIASUBUgFKATEBRgExAUYBMQFGATEBRgEYAWMBtQFW
Ac4BOQHvAT0BEAFCAXMBTgHWAVoB9wFeAbUBVgGUAVIBOQFn5AABewFvAfcBXgHWAVoB1gFaAfcBXgE6
AWcBfAFvAb4BdwG/AXcBvgF3Ab4BdwGeAXMBnQFzAZ0BcwF8AW8BWwFrAVsBawE6AWcBGQFjARkBYwGU
AVIB7wFGAQcBHQGEARABUgFKAZQBUgGUAVIBMQFGATEBRgExAUYBUgFKATEBRgHOATkBEAFCAbUBVgFa
AWsBvQF3GgABvQF3AXsBbwEYAWMBSgEpAaUBFAGEARABxgEUAaUBEAEhAQQBIQEEAgABpAEMAQYBFQoA
AQEBAAEqASUBUgFKAVIBSgFSAUoBUgFKAXMBTgFaAWsBlAFSAc0BOQHvAT0BEAFCAe8BQQExAUYBlAFS
AbUBVgHWAVoBcwFOAdYBWgG9AXfeAAHeAXsB9wFeAdYBWgE5AWcBWwFrAXwBbwGdAXMBnQFzAZ4BcwG+
AXcBvgF3Ab4BdwG+AXcBnQFzAZ0BcwF8AW8BXAFrAVsBawE6AWcBGQFjARkBYwG1AVYBLQE6AYwBMQHw
AT0BUgFKARgBYwH3AV4BtQFWAXMBTgExAUYBMQFGAVIBSgFSAUoBEAFCAc4BOQFzAU4BGAFjAZwBcwHe
AXsUAAF7AW8BOQFnAVoBawGUAVIBhAEQASYBFQFBAQQBiQEdAWYBFQoAASIBBAFkAQwBpwEQAQoBGQEr
AR0BTQEhAa8BMQHWAVoB9wFeARgBYwEYAWMBOQFnAXsBbwH3AV4BUgFKARABQgHvAT0BEAFCATABRgEQ
AUIB7wE9AbUBVgEXAWMBlAFSAZQBUgFaAWvcAAGcAXMB1gFaATkBZwFbAWsBWwFrAXwBbwF8AW8BnQFz
AZ0BcwG+AXcBvgF3Ab4BdwG+AXcBngFzAZ0BcwF8AW8BfAFvAVsBawE6AWcBGQFjARkBYwH3AV4BsgFO
AZQBUgFzAU4BcwFOAbwBdwFaAWsBOQFnAfcBXgGUAlIBSgExAUYBMQFGAXMBTgExAUYB7wE9ARABQgHW
AloBawG9AXcQAAF7AW8B9wFeATkBZwE5AWcB7wE9AWQBCAHrASUBQAEEBgABIgEEAYUBDAHpARgBLAEh
AW4BJQGPAS0BrwExAc8BMQHwATkBMQFCAXQBTgE5AWcBOQFnARgBYwEYAWMB+AFeAfcBXgEYAWMBOQFn
ARgBYwHWAVoBUgFKARABQgExAUYB7wE9ARABQgFSAUoBtQFWAdYBWgFzAU4BGAFjAd4Be9gAAXsBbwHW
AVoBOgFnAToBawFbAWsBewFvAXwBbwGdAXMBnQFzAb4BdwG+AXcBvgF3Ab4BdwGeAXMBnQFzAZ0BbwF8
AW8BfAFvAVsBawFbAWsBGQFjAdYBWgGUAVIBcwFOAXMBTgFaAWsBvQF3AZwBcwF7AW8BWgFrARgBYwHW
AVoBlAJSAUoBMQFGAVIBSgFSAUoBEAFCAe8BPQFzAU4BGAFjAZwBcw4AATkBZwFzAU4BcwFOAXMBTgGt
ATUGAAFDAQgBpwEQASsBHQFuASUBjwEtAdABNQERAT4BUgFGAZQBUgHWAVoBGAFjATkBZwE5AWcBOQFn
ARgBYwEYAWMBGAFjARgBYwEYAWMB9wFeAfcBXgH3AV4B9wFeARgBYwE5AWcB9wFeAZQBUgEPAUIBMQFG
ARABQgEQAUIBtQFWAdYBWgGUAVIB9wFeAb0Bd9YAATkBZwH3AV4BOgFnAToBZwFbAWsBWwFrAXwBbwGd
AXMBnQFzAZ4BcwG+AXcBvgF3Ab4BdwG+AXcBvgF3AZ0BcwFbAWsBGAFjAbUBVgFSAUoBMQFGAVIBSgG1
AVYB9wFeATkBZwE5AWcBOQFnAXsBbwG9AXcBnAFzAXsBbwFaAWsBGAFjAbUBVgFzAU4BUgFKAVIBSgFz
AU4BUgFKAe8BPQEQAUIB1gFaAXsBbwHeAXsKAAHWAVoB7wE9ATEBRgFzAU4B7wE9AWMBCAHIARQBLAEh
AY8BKQGvATEB8AE5AVIBRgG1AVYBGAFjAVoBawFbAWsBWwFrAVoBawFaAWsBWgFnATkBZwE5AWcBOQFn
ATkBZwE5AWcBGAFjARgBYwEYAWMBGAFfAfcBXgH3AV4B9wFeAfcBXgH3AV4BOQFnARcBYwGUAVIBMQFG
ARABQgEQAUIBlAFSAdYBWgGUAVIB9wFeAb0Bd9QAATgBZwH4AV4BOgFnAToBZwFaAWsBWwFrAXwBbwGd
AXMBvgF3Ab8BdwG+AXcBnQFzAVsBawEYAWMBtQFSAXMBTgFzAU4BcwFOAbUBVgHWAVoBGAFjATkBZwE5
AWcBGAFjAfcBXgH3AV4BGAFjARgBYwE5AWcBewFvAb0BdwGcAXMBewFvATkBZwH3AV4BtQFWAXMBTgFS
AUoBUgFKAXMBTgExAUYB7wE9AZQBUgE5AWcBvQF3CAAB9wFeATEBRgExAUYBcwFOAbUBVgESAT4BrwEt
AfABOQFzAU4B9wFeAVoBawF7AW8BewFvAXsBawFbAWsBWwFrAVoBawFaAWsBWgFrAVoBawFaAWsBWgFr
AToBZwE5AWcBOQFnATkBZwEYAWMBGAFjARgBYwH4AV4B9wFeAfcBXgH3AV4B9wFeAdYBWgH3AV4BOQFn
AfcBXgFzAU4BEAFCAe8BQQFSAUoB1gFeAbUBVgH3AV4BvQF30gABGAFjAfcBXgFbAWsBWgFrAVsBawFb
AWsBWgFrARkBYwH3AV4BtQFWAZQBUgFzAU4BcwFOAbUBVgH3AV4BOQFnAVoBbwF7AW8BWgFrAVoBawE5
AWcBGAFnARgBYwEYAWMB9wFeAfcBXgEXAWMB9wFeAfcBXgEYAWMBOQFnAZwBcwG9AXcBnAFzAVoBawE5
AWcB9wFeAZQCUgFKAVIBSgFzAU4BUgFKARABQgHWAloBawG9AXcGAAEYAWMBcwFOAfcBXgFaAWsBewFv
AVoBawEYAWMBWgFrAXwBbwF8AW8BewFvAXsBbwF7AW8BewFvAXsBbwF7AW8BewFvAXsBawFbAWsBWwFr
AVoBawFaAWsBWgFrAToBZwE5AWcBOQFnATkBZwEYAWMBGAFjARgBYwEYAWMBGAFjAfcBXgHWAVoB1wFa
AdYBWgHWAVoBGAFjATkBZwG1AVYBUgFKAe8BPQFSAUoBtQFWAdYBWgE5AWcB3gF70AABWgFrAVIBSgHW
AVoBtQFWAbUBVgG1AVYBlAFSAZQBUgHWAVoBGAFjAVkBawGbAXMBvQF3AbwBdwGcAXMBewFvAVoBawFa
AWsBWgFrAVsBawF7AWsBfAFvAXwBbwF8AWsBWwFnATkBYwEYAV8B+AFeAfcBXgHXAVoB1wFeAfcBXgE5
AWcBnAFzAZwBcwF7AW8BWgFrARgBYwHWAVoBlAFSAXMBTgGUAVIBlAFSAdYBWgF7AW8BvQF3BgABvQF3
AZwBcwF7AW8BWgFrAVsBawF7AW8BfAFvAXwBbwF8AW8BfAFvAXwBbwF8AW8BfAFvAXwBbwF8AW8BfAFv
AXsBbwF7AW8BewFvAVsBawFbAWsBWgFrAVoBawFaAWsBWgFrAToBZwE6AWcBGQFjAfcBXgHWAVoBtQFW
AXMBTgFSAUoBlAFSAdYBWgHWAVoB1gFaAdYBWgH3AV4BOQFnARgBYwFzAU4B7wE9ATEBRgHWAVoB9wFe
AXsBb9AAAd4BewFaAWsBOQFrAXsBbwGcAXMBnAFzAb0BewHeAX8B3gF/Ad4BewHeAXsBvQF3AZwBcwFa
AWsBOQFnAToBZwFbAWsBfAFrAZwBbwGdAW8BnQFzAZ0BcwGdAXMBnAFvAXsBawFaAWcBOgFjARkBYwH4
AV4B1wFaAbYBVgGUAVIBlAFOAbUBVgE5AWcBnAFzAZwBcwF7AW8BWgFrARgBYwG1AVYBlAFSAdYBWgH3
AV4BvQF3Ad4BewoAAb0BdwGcAXMBfAFvAXwBbwGcAXMBnAFzAZwBcwGcAXMBnAFzAZwBcwGcAXMBnAFz
AZwBbwF8AW8BfAFvAXwBbwF8AW8BewFvAXsBbwF7AW8BWgFrARgBYwH3AV4B1gFaAXMBTgF0AU4BlAFS
AXQBTgFzAU4BlAFSAZQCUgFKAXMBTgGUAVIB1gFaAdYBWgHWAVoB1gFaARgBYwE5AWcBtQFWARABQgFS
AUoB9wFeAXsBb9QAAd4BewHdAXsBvQF3AXsBbwF7AW8B3gF7Ad4BewHeAXsBvQF7AZwBcwE5AWcBWgFn
AXwBbwGdAXMBvQF3Ab0BdwGcAXMBnAFzAXsBcwF7AW8BewFvAVoBawFaAWsBWgFrAVoBawFaAWsBOQFn
ATkBZwE5AWcBGAFjAdYBWgF0AU4BMgFGAZQBUgFaAWsBnAFzAZwBcwF7AW8BOQFnARgBYwH3AV4BOQFn
EgAB3gF7Ab0BdwGdAXMBnQFzAZ0BcwGdAXMBnQFzAZ0BcwGcAXMBnAFzAZwBcwGcAXMBnAFzAXsBawE5
AWcBGAFjAdYBWgG1AVYBtgFaAZUBUgGUAVIBtQFWAbUBVgGUAVIBlAFSAbUBVgFzAU4BcwFOAZQBUgGU
AVIBcwFOAZQBUgGUAVIBtQFWAdYBWgHWAVoB1gFaAfcBXgE5AWcB1gFaAXMBTgFaAWsBvQF32AAB3gF7
Ab0BewG9AXcBvQF3Ad0BewHeAXsB3gF7Ab0BdwG9AXcB/wF/Af8BfwHeAXsB3gF7Ad4BewG9AXcBvQF3
Ab0BdwGcAXMBnAFzAZwBcwF7AW8BewFvAXsBbwFaAWsBWgFrAVoBawFaAWsBWQFrAVkBawE5AWcB9wFe
AXMBTgHWAVoBOQFnAXsBbwGcAXMBnAFzAXsBbwE5AWcBWgFrFgAB3gF7Ab4BdwG9AXMBnQFzAZ0BcwGd
AXMBnQFzAZwBcwGcAXMB+AFeAZQBUgHWAVoBtQFWAZQBUgHXAV4B9wFeAbUBVgG2AVYB9wFeAZQBUgFz
AU4B1gFaAbUBVgFzAU4BtQFWAbUBVgFzAU4BcwFOAbUBVgGUAlIBSgFzAU4BcwFOAZQBUgG1AVYB1gFa
AdYBWgEYAWMBOQFnAd4Be+AAAd4BewG9AXcBvQF3Ab0BdwHeAXsB/wF/Af8BfwH/AX8B/wF/Af8BfwH/
AX8B3gF7Ad4BewHeAXsB3gF3Ab0BdwG9AXcBvQF3AZwBcwGcAXMBewFzAXsBbwF7AW8BewFvAVoBawFa
AWsBWgFrAVoBawEYAWMBGAFjARgBYwEYAWMBOQFnAXsBbwG9AXcBewFvAZwBcxwAAd4BewG9AXcBnQFz
AZ0BcwGdAXMBnAFzAVsBawFaAWsB1wFaAbUBVgHWAVoBtQFWAbUBVgHWAVoBtQFWAZQBUgHWAVoBtQFW
AZQBUgGUAVIBtQFWAXMBTgFzAU4BlAFSAXMBTgFSAUoBcwFOAXMBTgExAUYBUgFKAXMBTgFzAU4B1gFa
AdYBWgEYAWMBvQF36AAB3gF7Ab0BdwG9AXcBvQF7Ad4BewH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/
AX8B3gF7Ad4BewHeAXsB3gF7Ab0BdwG9AXcBnAFzAZwBcwGcAXMBewFvAXsBbwFaAWsBWgFrATkBZwE5
AWcBGAFjARgBYwH3AWIBGAFjATkBZwF7AW8kAAHeAXcBvQF3AZ0BcwGdAXMBnAFzAVoBawFbAWsBOQFn
AdYBWgG1AVYBtQFWAdYBWgGUAVIBlQFSAdYBWgGUAlIBSgFzAU4BcwFOATEBSgFSAUoBcwFOAVIBSgFz
AU4BtQFWAdYBWgH3AWIBWgFrAXsBbwGcAXMBvQF3Ad4Be/AAAd4BewG9AXcBvQF3Ab0BdwHeAXsB3gF7
Ad4BfwHeAXsBvQF3Ab0BewG9AXcBnAFzAZwBcwG9AXcBvQF3AZwBcwGcAXMBmwFzAXsBbwFaAWsBOQFn
ATkBZwE5AWcBOQFnATkBZwFaAWsBewFvAZwBcwHeAXssAAHeAXcBvQF3AZ0BcwGcAXMBewFvAXwBbwE5
AWcBtQFWAbYBVgG2AVYBcwFOATEBRgFzAU4BcwFOAVIBSgGUAVIB1gFaARgBYwE5AWcBewFvAZwBcwG9
AXf/AAUAAd4BewG9AXcBvAF3Ab0BdwGcAXcB9gFeAe8BPQGtATUBzgE5ATEBRgE5AWcBnAFzAZsBcwF7
AW8BegFvAVoBawF7AW8BewFzAZwBcwG9AXcB3gF7PAAB3gF7Ab0BdwF7AW8BWgFrAVoBZwH3AV4BlAFS
AdYBWgEYAWMBOQFnAXsBbwG9AXcB3gF7Ad4Be/8AFQAB3gF7Ab0BdwG9AXcBewFvAXsBbwGcAXMBnAFz
AZwBcwG9AXcBvQF3Ad4BewHeAXtOAAHeAXsBvQF3AZwBcwHeAXv/AP8A/wD/AP8A/wD/AP8A/wD/AP8A
/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wAuAAHeAXsB3gF7Ab0BdwF7AW8BWgFr
ATkBZwE5AWcBWgFrAb0Bd/8AdQAB3gF7Ab0BdwF8AW8BOgFrARgBYwH3AV4B1gFaAbUBVgF0AU4BUwFK
AbYBVgG2AVoBdAFOATIBRgH3AV4BewFvAZwBcwHeAXv/AGcAAd4BewFaAWsBGAFjAdYBWgG1AVYBlQFS
AXQBTgFTAUoBMgFGATIBQgERAUIB8AE9AdABOQFTAUoBdAFOAbUBVgGUAVIB7wE9AZQBUgEYAWMBWgFr
AZwBc64AAd4BewGcAXMBWgFrAVoBawFaAWsBWgFrAVoBawGcAXMB3gF7UgAB3gJ7AW8B9wFeAfcBXgGc
AXNGAAE5AWcBtQFWAXQBTgEyAUYBEQFCAREBQgERAUIBEQFCATIBRgEyAUYBUwFGAVMBSgEyAUYBMgFG
AXQBTgF0AVIBlQFSAbYBVgFzAU4B8AE9AbUBVgH3AV4BGAFjAXsBbwHeAXtIAAHeAXsBvQF3Ad4Be1YA
Ab0BdwFaAWsBWgFrATkBZwFaAWsBWgFrAVoBawFaAWsBOQFnATkBZwEYAWMB9wFeARgBYwFaAWsB3gF7
RgABvQF3ATkBZwGVAVIBMgFGATMBRgHYAVoBlgFSAc8BOQGUAVIBvQF3PgAB3gF7AdYBWgF0AVIBlQFS
AXQBTgEyAUYBMgFGAVMBSgF0AU4BdAFOAXQBTgF0AU4BlAFOAZQBTgFTAUoBUwFKAbYBVgHXAVoBtgFW
AbYBVgG1AVYBEQFGATIBRgEYAWMBGAFjATkBZwF7AW8B3gF7PgAB3gJ7AW8B9wFaAVMBSgEQAT4BrQE1
AWwBLQGUAVJQAAG9AXcBOQFnARgBYwE5AWcBWgFrAXsBbwF7AW8BewFvAXsBbwFaAWsBOQFnAVoBawF7
AW8BOQFnAdYBWgHWAVoB1gFaATkBZwHeAXsB3gF7Ab0BdwGcAXMBvQF3Ad4BezIAAZwBcwH4AV4BdAFO
ATIBRgFTAUoBlgFSARoBYwF9AWsBfQFnAX0BZwH4AVYBzwE5Ac4COQFnPAAB9wFeAbYBVgHXAVoB1gFa
AdYBWgG1AVYBtQFWAbUBVgF0AU4BUwFKAVIBSgFSAUoBlAFSAZUBUgFTAUoBUwFKARIBQgGWAU4BtgFa
AbYBVgG2AVYBdAFOAe8BPQH3AV4BOQFnATkBZwFaAWsBewFvAd4BezYAAZwBcwEYAWMBlAFOARABQgHv
AT0B7wE9ARABQgHvAT0BjAExAUoBKQEIASEBzgE5AXsBb0oAAb0BdwEYAWMBGAFjARgBYwE5AWcBWgFr
AVoBawF7AW8BewFvAXsBbwFaAWsBOQFnAXsBbwF7AW8B9wFeAfcBXgEYAWMB1gFaAZQBUgHWAVoBGAFj
ARgBYwEYAWMBOQFnAXsBbwG9AXcB3gF7JgAB3gJ7AW8B1gFaAXQBTgEyAUYBlQFSAfgBXgF8AW8BvgFz
Ab4BcwGdAW8BfQFnAVwBYwFcAV8BXAFfAVwBXwF1AUoBjQExAXMBTgHeAXs2AAFaAWsB1gFaARkBYwH3
AV4B+AFeARkBZwEYAWMB9wFeAZQBUgFTAUoBlAFSAZQBUgG1AVYBtQFWAZUBUgF0AU4BdAFOAVMBSgEy
AUYBtgFWAbYBVgG2AVYBtQFWAc8BOQG2AVYBWgFrAVoBawFaAWsBewFvAZwBcwHeAXssAAG9AXcBOQFn
AbUBVgExAUIB7wE9Ae8BPQEQAUIBMQFGAe8BPQGMATEBCAEhAcYBGAHGARgBxgEYAQgBIQEIASEBSgEp
AdYBWkgAARgBYwH3AV4B9wFeARgBYwE5AWcBWgFrAVoBawF7AW8BewFvAXsBbwFaAWsBOQFnAXsBbwE5
AWcB9wFeARgBYwHWAVoBtQFWAZQBUgFzAU4BlAFSAZQBUgHWAVoB9wFeATkBZwF7AW8BnAFzAb0Bdx4A
Ab0BdwE5AWcBtQFWAXQBTgF0AU4B1wFaARkBYwG9AXcB/wF/Af8BewHeAXcBvgFzAZ0BbwF9AWsBfAFn
AVwBYwFcAV8BOwFbATsBWwFcAVsB+gFWAfEBPQHvAT0BOQFnMgAB3gF7AfcBXgE5AWcBOQFnAbUBVgES
AT4BtgFSAVoBawE5AWcBGAFjATkBZwE6AWcBWgFrAZwBcwEYAWMBlQFSAZQBUgGWAVIB1gFaAbUBVgG2
AVYBtgFWAbYBWgHWAVoB8AE9AVMBSgF7AW8BWgFrAXsBbwF7AW8BnAFzAZ0BcwHeAXskAAFaAWsB1gFW
AVIBRgHvAT0B7wE9ARABPgExAUYBEAFCAa0BNQEpASUBxgEYAaUBFAHGARgBKQElAWsBLQHOATkBlAFS
ATEBRgEIASEBKQElAQgBIQEQAUIBvQF3JgABvQF3AXsBbwG9AXcBvQF3Ab0BdwG9AXcBvQF3Ad4BewwA
Ad4BewHWAVoB1gFaAfcBXgEYAWMBGAFjATkBZwFaAWsBewFvAXsBbwFaAWsBOQFnARgBYwE5AWcBGAFj
ARgBYwHWAVoBtQFWAZQBUgFzAU4BcwFOAZQBUgG1AVYB1gFaAfcBXgEYAWMBWgFrAXsBbwGcAXMB3gF7
FAAB3gJ7AW8B+AFeAbUBVgF0AU4BtgFWARgBYwF7AW8BnQFzAb0BdwF7AW8BvQF3Af8BfwHfAXcBvgFz
AZ4BbwGdAW8BfQFrAX0BZwF8AWMBXQFjAVwBXwE7AVsB+QFSAdgBTgF0AUoBjAExAQgBIQGUAVIwAAGc
AXMB9wFeAVoBawFaAWsBGAFjAbUBVgH3AV4BewFvAXsBbwFaAWsBnAFzAb0BdwG9AXcBWgFrAfcBXgH3
AV4BdAFSARIBPgFUAUoB1wFeAbYBWgG2AVYB1gFaAdcBWgERAUIBMQFGAXsBbwF7AW8BnAFzAZwBcwGc
AXMBvQF3Ab0BdwHeAXsgAAFaAWsBzgE5Ae8BPQExAUYBEAFCAc4BOQFKASkB5wEcAaUBFAHGARgBCAEh
AWsBLQHvAT0BUgFKAXMBTgHWAVoBGAFjAfcBXgE5AWcBUgJKASkBCAEhAQgBIQFrAS0BGAFjIgAB9wFe
Ae8BPQHOATkBEAFCAXMBTgG1AVYBUgFKATEBRgG1AVYBOQFnAZwBcwHeAXsGAAHeAXsB1gFaAdYBWgH3
AV4B9wFeARgBYwEYAWMBOQFnAVoBawFaAWsBWgFrATkBZwEYAWMB9wFeAfcBXgHWAVoBtQFWAXMBTgFS
AUoBUgFKAXMBTgGUAVIB1gFaAfcBXgEYAWMBOQFnAVoBawF7AW8BnAFzAb0Bdw4AAb0BdwFaAWsB1gFa
AbUBVgGUAVIB1wFaAToBZwGdAXMBvQF3Ab0BdwFaAWsBGAFjAbUBVgExAUYBEAFCAfcBWgG+AXcB3gF3
Ab4BcwG+AW8BngFvAX0BZwE6AV8BtwFSATIBPgGOAS0BSwElASoBJQHnARwB6AEcAQkBIQHGARgBrQE1
AXsBbywAAVoBawEYAWMBWgFrAVoBawFaAWsBGAFjAVMBSgF1AUoBewFvAZsBcwFaAWsBWgFrAVoBawFa
AWcBOgFnARkBYwHXAVoBlAFSAZUBUgHXAVoB1gFaAdYBWgHXAVoB1wFeAVIBSgHvAT0BewFvAZwBcwGc
AXMBvQF3Ab0BdwG9AXcBvQF3Ad4BewHeAXseAAE5AWcBUgFKAa0BNQHnARwBpQEUAaUBFAHnARwBSgEp
Ac4BOQFSAUoBtQFWARgBYwFaAWsBnAFzAfcBXgEYAWMBOQFnAfcBXgH/AX8BnAFzAbUBVgGMATEBCAEh
ASkBJQEpASEBcwFOHgABnAFzARABQgFTAUoBEAFCAc4BOQHvAT0BjAExASkBJQGMATEBcwFOAZQBUgGU
AVIBGAFjAXsBbwG9AXcEAAE5AWcBtQFWAdYBWgH3AV4B9wFeAfcBXgEYAWMBGAFjATkBZwEYAWMB9wFe
AfcBXgHWAVoBlAJSAUoBEAFCARABQgFSAUoBUgFKAXMBTgHWAVoBGAFjATkBZwE5AWcBWgFrAXsBbwGc
AXMBvQF3CgABnAFzATkBZwHWAVoBtQFWAbYBVgEZAWMBWwFrAb0BcwG+AXcBnAFzATkBZwHWAVoBlAJS
AUoBEAFCAc4BOQGtATUBjAExAWsBLQExAUYBfAFvAZ0BbwH4AVoBUwFKAa4BNQErASUByAEYAacBFAGH
ARABhwEQAacBFAHoARwB6AEcAccBGAHoARwBpQEUAecBHAHWAVoqAAFaAWsBOQFnATkBZwE5AWcBOQFn
ATkBZwG1AVYBdAFOATkBZwF7AW8BnQFzAZ0BdwGcAXMBewFvAVoBawEZAWcBGAFjAfgBXgH3AV4B9wFe
AfgBXgEYAWMB+AFiAfcBXgF0AVIBzgE5AXsBbwGcAXMBvQF3Ab0BdwG9AXcB3gF7Ad4BewHeAXsB3gF7
IAABWgFrAUoCKQElAa0BNQExAUYBtQFWARgBYwFaAWsBewFvAZwBcwGcAXMBnAFzAZwBcwH3AV4B9wFe
ATkBZwEYAWMB/wF/Af8BfwHeAXsBGAFjAe8BPQEpASUBKQElAQgBIQG1AVYcAAFaAWsBUgFKAZUBUgEx
AUYB7wE9ATEBRgFSAUoBMQFGAe8BPQHvAT0BcwFOAbUBVgGUAVIBtQFWAfcBXgF7AW8BvQF3Ad4BewEY
AWMBtQFWAdYBWgHWAVoB1gFaAdYBWgHWAVoBtQFWAbUBVgFzAU4BUgFKARABQgHOATkBjAExAa0BNQEQ
AUIBUgFKAdYBWgH3AV4BGAFjATkBZwE5AWcBewFvAZwBcwG9AXcB3gF7CgABOQFnAbUBVgH4AV4BOQFj
AXwBbwF8AW8BnQFzAZ0BcwG9AXcB3gF7Ab4BdwEYAWMBMQFGAc4BOQHOATkBzgE5Ac4BOQHvAT0BMAFC
ARABQgEQAUIBzwE5AWwBLQHoARwByAEYAacBFAHIARQBpwEQAcgBFAGnARQBpwEQAYYBEAGnARAB6QEc
AegBHAHHARgB5wEYAaUBFAFjAQwBMQFGAd4BeyQAAd4BewE5AWcBOQFnATkBZwE5AWcBOQFnAVoBZwE5
AWcBOQFnAVoBawFaAWsBewFvAXsBbwF7AW8BewFvAXsBbwF7AW8BWgFrAVoBawFaAWsBWgFrATkBawEY
AWMB9wFeAfgBXgGVAVYBrQE1AXsBbwG9AXcBvQF3Ab0BdwHeAXsB3gF7Ad4BewHeAXsB3gF7IAABOQFn
AXMBTgHWAVoBewFvAZwBcwGcAXMBnAFzAZwBcwGcAXMBnAFzAZwBcwGcAXMBnAFzAfcBXgEYAWMBOQFn
ARgBYwH/AX8B3gF7Ad4BewH/AX8BewFvAVICSgEpAWsBMQG1AVIBWgFrAb0BdxgAATkBZwFTAUoB+AFe
AXMBTgHvAT0BEAFCATEBRgFzAU4BlAFSAXMBTgExAUYBMQFGAXMBTgGUAVIBtQFWAbUBVgE5AWcBewFv
AVoBawHWAVoBlAFSAZQBUgFzAU4BcwFOAXMBTgFSAUoBEAE+Ae8BPQHvAT0BzgE5Ae8BPQFSAUoBtQFW
AdYBWgHWAVoB9wFeAfcBXgH3AV4B9wFeAdYCWgFrDgABvgF3AToBZwFbAWsBWwFrAVsBawFbAWsBfAFv
AZwBcwGdAXMBvQF3Ab4BdwHeAXsB/wF/Ab0BdwG2AVYBMQFGATEBRgExAUYBEAFCAY0BMQEqASUBCQEh
AcgBGAHoARgByAEYAegBGAGnARQByAEUAacBFAHIARQBpwEUAagBFAGnARQBpwEUAYcBEAHIARgBCQEh
AccBGAHHARgBhQEQAaUBFAFzAU4BnAFzIgAB3gF7ARgBYwEYAWMBGAFjARgBYwE5AWcBOQFnAVoBawFb
AW8BewFvAXsBbwGbAXMBnAFzAZwBdwGbAXMBegFvAVkBZwEYAWMBtgFWATMBRgHyATkBkQEtAS8BHQGy
ATEBOQFnAbYBVgHOATkBnAFzAd4BewHeAXsB3gF7Ad4BeygAAVoBawGcAXMBewFvAb0BdwG9AXcBnAFz
AZwBcwG9AXcBnAFzAZwBcwGcAXMBnAFzAZwBcwEYAV8BGAFjAVoBawEYAWMB3gF7Ad4BewG9AXcBvQF3
Ab0BdwGcAXMBtQFWATEBRgE5AWcBWgFrAVoBawGcAXMWAAEYAWMBlAFSARoBYwF0AU4BDwFCARABQgEQ
AUIBMQFGAVIBSgGUAVIB1gFaAbUBVgFSAUoBzgE5AZQBUgG1AVYB1gFaAdYBWgHWAVoB1gFaAdYBWgHW
AVoB1gFaAbUBVgFzAU4BMQFGATEBSgExAUoBcwFOAZQBUgG1AVYB1gFaAdUBWgHVAVoB9gFeARcBYwH4
AV4BGQFjARgBYwHWAVoBGAFjEAABfAFvAToBZwE6AWcBWwFrAVsBawF8AW8BnAFzAZ0BcwG+AXcBvgF3
AZ0BcwFaAWsB1gFaAVIBSgGuATUBSwEpAQkBIQHoARwBCQEhAegBHAHoARwByAEYAQkBHQHoARgB6QEY
AcgBFAHJARgByAEUAacBFAGnARABhgEQAacBFAGnARQByAEYAekBHAFMASEBCQEdAaYBFAHGARgBrQE1
AVIBSgG1AVYBnAFzIAABvQF3AfcBXgEYAWMBOQFnATkBZwFaAWsBewFvAXsBcwF6AW8BWQFrATkBZwEY
AV8BtgFSAVUBRgEUAT4BsgEtAVEBIQHvARQBzwEMAa4BCAGOAQQBjgEEAY8BAAFzASUBOQFnAdYBWgHO
ATkBvgF3MAABWgFrAb0BdwF7AW8BvQF3Ab0BdwG9AXcBvQF3Ab0BdwG9AXcBnAFzAZwBcwGcAXMBnAFz
ARgBYwEYAWMBWgFrARgBYwHeAXsBvQF3Ab0BdwGcAXMBnAFzAXsBbwF7AW8BUgFKATkBZwF7AW8BewFv
AXsBbwGcAXMUAAEYAWMBtgFWATsBZwF0AU4BEAFCATEBRgExAUYBMQFGATEBRgExAUYBcwFOAbUBVgH3
AV4BtQFWAXMBTgGUAVIB1gFaAdYBWgH3AV4B9wFeAdYBWgHWAVoBtQFaAZQCUgFOAVIBSgFSAUoBMQFK
ATEBSgGSAVIBtAFaAbYBWgG3AVYBeAFKARkBPgG5AS0BGAEZAfcBFAH4AV4B9gFeARgBYxIAAd4BewF8
AW8BWwFrAVsBawF8AW8BewFvATkBZwHWAVoBUgFKAe8BPQFrAS0BSgEpAQkBIQEqASUBCQEhAQkBIQHo
ARwBCQEhAegBHAHpARwB6AEYAekBHAHpARgByAEYAcgBFAHIARQByAEYAcgBGAEKASEBKgElAWwBLQFs
AS0BSwEpAW8BIQFvARUBCgEZAWsBLQFSAUoB9wFeATkBZwE5AWcBWgFrAb0Bdx4AAb0BdwH3AV4BGAFj
ATkBZwEYAV8BtgFWAXYBSgFWAUYBFQE6AbMBLQFyASEBMwEZARIBFQHyARAB8gEQAfIBEAHRAQwBsAEI
AbABCAGvAQgBrwEIAa8BCAGvAQQBcwElATkBZwH3AV4B7wE9Ad4BezAAAVoBawG9AXcBewFvAb0BdwG9
AXcBvQF3Ab0BdwG9AXcBvQF3Ab0BdwGcAXMBnAFzAb0BdwEYAWMBGAFjAVoBawEYAWMBvQF3Ab0BdwGc
AXMBewFvAXsBbwFaAWsBWgFrAVIBSgE5AWcBnAFzAZwBcwGcAXMBnAFzAb0BdwHeAXsQAAEYAWMBtwFW
AVwBawF0AU4BEAFCATEBRgFSAUoBUgFKAVIBSgFSAUoBUgFKAXMBTgGUAVIB1gFaAdYBWgGUAVIBtQFW
AdYBWgG1AVYBlAFSAXMBTgFSAUoBMQFKATABSgFRAU4BUQFOATIBSgFTAUoBFAFCAbYBMQGYASkBFwEZ
AbYBCAF2AQQBVQEAATQBAAFUAQABlAEIAdgBWgEXAWMB9wFeFgAB3gF7AZwBcwH4AV4BMgFGAa0BNQFK
AikBJQFLASkBKgElASoBKQEJASEBCQElAQkBIQEqASUBCQEhAQkBIQHpARwB6QEcAekBHAHoARgB6QEc
AQkBHQFLASkBSwEpAa4BNQGtATUBjQExAYwBMQFsAS0BSgIpASUBSwEpAc8BPQG1AVYBOQFnAVoBawFa
AWsB9wFeAVoBawHeAXsgAAGcAXMBFwFjAbgBUgG1ASkBlgElAZYBIQF2AR0BVQEZATUBGQE1ARkBNAEV
ARQBFQETARUBEwEVATMBGQESARUB8QEQAdABDAHQAQgBsAEIAbABCAGwAQgBrwEEAXMBJQE5AWcB9wFe
Ac8BOQHeAXswAAFaAWsBvQF3AXsBbwHeAXsBvQF3Ab0BdwG9AXcBvQF3Ab0BdwG9AXcBvQF3Ab0BdwG9
AXcBGAFjARgBYwFaAWsB9wFeAb0BdwGcAXMBewFvAXsBbwFaAWsBOQFnATkBZwFSAUoBWgFrAb0BdwG9
AXcBvQF3Ab0BdwHeAXsB3gF7Ad4Bew4AARgBYwG3AVYBXAFrAXQBTgExAUYBUgFKAXMBTgFzAU4BcwFO
AXMBTgFzAU4BcwFOAVIBTgFSAUoBUgFKAVIBTgFzAU4BcwFSAZMBUgGTAVYBkwFSAXMBTgEyAUYB8wE5
AbQBMQFUASUB1AEQAZQBCAF0AQQBVAEAAVQBAAF0AQQBdAEEAXUBBAGVAQgBlQEIAZYBCAG2AQwBuAFW
ATgBZwHWAVoB3gF7GAABnAFzAdcBWgEyAUYBrgE1AWwBLQEqAikBJQEqASUBKgElASoBJQEJASEB6AEc
AQkBIQEJASEBCgEhASoBJQFsAS0BjQExAa4BNQGtATUBjQExAYwBMQFLASkBSgEpASoBJQEpASUBKQEl
AWwBLQHvAT0BUgFKAVIBSgEQAUIBrQE1AUoBKQHnASABxgEcAWsBLQG9AXcgAAF7AXMBGAFnAZkBTgGZ
ASEBmAElAZgBIQF3ASEBdgEdAVYBHQFVARkBNAEZATQBFQETARUBMwEZATMBGQESARUBEgEVAdEBDAHQ
AQwB0AEMAdABDAHQAQwBsAEIAXMBJQE5AWcBGAFjAe8BPQHeAXswAAFaAWsBvQF3AXsBbwHeAXsBvQF3
Ab0BdwG9AXcBvQF3Ab0BdwG9AXcBvQF3Ab0BdwG9AXcBGAFjARgBYwFaAWsB9wFeAZwBcwF7AW8BWgFr
AVoBawE5AWcBGAFjARgBYwFSAUoBewFvAd4BewHeAXsB3gF7Ad4BewHeAXsSAAH4AV4BtwFWAVwBawF0
AU4BUQFKAXMBTgFzAU4BlAFSAZQBUgGUAlIBSgExAUYBMQFGAW8BRgFRAU4BcgFOAZQBUgGVAVIBEwFC
AZMBMQFUASkBsQEQAVIBBAFSAQABEgEAARIBAAEyAQABMgEAAXQBBAG1AQwBtQEMAbYBDAG2AQwBtgEM
AbYBDAHXAQwB1wEMAdcBDAF4AU4BOAFnAbUBVgG9AXccAAG9AXcB+AFeATMBRgHPATkBawEtASkBJQEJ
ASEBCQEhAUsBKQEqASUBawEpAY0BMQGuATUBrgE1Aa4BNQGMATEBSwIpASUB6AEcAcYBGAGlARQBxgEY
AecBHAEIASEBKQElAUkCKQElAecBHAHmARwB5gEgAQgBJQFsAS0BjwEpARMBOgG1AVYBWwFrIAABewFv
ARcBYwGZAU4BmAEhAbgBJQGYASUBlwEhAXYBIQF2AR0BVQEdAVUBGQE0ARkBNAEVAVQBGQEzARkBEgEV
ARIBFQHxARAB0QEMAdEBDAHQAQwB0AEMAbABCAFzASUBOQFnARgBYwHvATkB3QF3MAABWgFrAb0BdwF7
AW8B3gF7Ad4BewG9AXcBvQF3Ab0BdwG9AXcBvQF3Ab0BdwG9AXcBvQF3ARgBYwEYAWMBWgFrAfcBXgF7
AW8BWgFrATkBZwE5AWcBGAFjARgBYwH3AV4BMQFGAZwBcxwAAfcBXgG2AVYBOwFnAVMBSgFSAUoBlAFS
AZQBUgGUAVIBtQFWAbUBVgFzAU4BMgFKATIBRgHyATkBkgExAREBHQGxARABcQEIATABAAEQAQABEAEA
ARABAAExAQABMQEAATIBAAEyAQABUwEAAVQBAAG1AQwB1gEQAdYBEAH3ARAB9wEQAfgBFAH4ARQB+AEU
ARkBFQHZARABOQFCAVkBawG1AVYBnAFzIAABvgF3ARkBYwFTAUoBrgE1AY0BMQGuATUBjQExAWwBLQFs
AS0BbAEtAW0BLQGNATEBbAEtASkBJQHGARgBxgEYAcYBGAHnARwBCAEhAQgBIQEIASEBBwElASgBJQEp
ASUBbAEtAbABMQGSASkBtgElAbkBIQF6AREBOwEFAboBHQFbAWsBnAFvIAABWgFrAfcBYgGZAUoBmQEl
AbgBJQGYASUBlwEhAXcBIQF2AR0BVgEdAVUBGQE0ARkBNAEZAVQBHQE0ARkBEwEVATMBGQHyARAB8QEM
AfEBDAHxAQwB0QEMAdEBCAFzASUBOQFnATkBZwHvAT0BvQF3MAABWgFrAb0BdwF7AW8B3gF7Ad4BewHe
AXsBvQF3Ab0BdwG9AXcBvQF3Ab0BdwG9AXcBvQF3ARgBYwEYAWMBWgFrAfcBXgF7AW8BOQFnATkBZwEY
AWMB9wFeAfcBXgH3AV4BMQFGAZwBcxwAAfcBXgGVAVIBGgFjAVMBSgFzAU4BtQFWAbUBVgG1AVYBtQFW
AdYBWgGTAVIBMwFGAXABCAEwAQABEAEAARABAAEQAQABEAEAARABAAEwAQABMAEAATEBAAExAQABMgEA
ATMBAAFTAQABVAEAAXUBBAH2ARQBFwEZARgBGQEYARkBOQEZATkBGQE5ARkBOgEdAToBHQEaARUBGQE6
AVkBawG1AVYBewFvJAAB3gF7AToBZwHXAVoBtgFWAZUBUgGVAVIBtgFWAbUBVgF0AU4B8AE9AYwBMQFK
AikBJQEpASUBSQEpAWoBLQFqAS0BawEtAa8BMQGzASkBlgElAZgBHQF6AREBOgEJARoBAQHZAQAB+QEA
ARkBAQH5AQABOQEJARkBXwFbAWsgAAFaAWsB9gFeAXkBSgG5ASUBuQElAZgBJQGYASUBdwEhAXYBIQF2
AR0BVQEdAVUBGQFVARkBdQEdATQBGQEzARUBMwEZARIBFQHyARAB8QEQAfEBEAHxARAB0QEMAZQBJQE5
AWcBOQFnAe8BPQG9AXcwAAFaAWsBvQF3AXsBbwHeAXsB3gF7Ad4BewHeAXsB3gF7Ab0BdwG9AXcBvQF3
Ab0BdwG9AXcBGAFjARgBYwFaAWsB9wFeAVoBawEYAWMBGAFjAfcBXgH3AV4B1gFaAdYBWgExAUYBvQF3
HAAB9wFeAXQBTgEZAWMBUwFKAZQBUgG1AVYBtQFWAdYBWgHWAVoB9wFeAbUBVgFTAUoBUAEEATABAAFx
AQgBUQEEAVABBAFQAQQBMAEAATABAAExAQABMQEAATIBAAFTAQABUwEAAVQBAAFUAQABlgEEATgBHQFZ
ASEBWQEhAVoBIQF6ASEBegEhAXsBIQF7ASEBewElAVsBHQH6ATUBWQFrAdYCWgFrLgABnAFzAfcBXgEx
AUYBrAE1AWoBLQFqAS0BiwExAa0BNQHPATUBsQEtAbQBKQGXASEBWAEVATkBCQEaAQUB+QEAAfkBAAH5
AQAB+AEAAfgBAAH4AQABGQEBATkBBQE5AQUBOQEJAdkBVgFaAWsgAAE5AWcB1gFeAXkBRgG5ASUBuQEp
AbgBJQGYASUBlwEhAXcBIQF2AR0BVgEdAVUBHQFVAR0BdQEhATQBGQE0ARkBVAEdARMBFQESAREB8gEQ
AfIBEAHyARAB8gEMAZQBJQEYAWMBWQFrAe8BPQG9AXcwAAFaAWsBvQF3AXsBbwHeAXsB3gF7Ad4BewHe
AXsB3gF7Ad4BewHeAXsBvQF3Ab0BdwHeAXsBGAFjARgBYwFaAWsB9wFeATkBZwH3AV4B9wFeAdYBWgHW
AVoBtQFWAdYBWgExAUYBvQF3HAAB9wFeAXMBTgH4AV4BUwFKAbUBVgHWAVoB1gFaAdYBWgHWAVoB9wFe
AdYBWgG1AVYBsAEQAXEBCAGSAQwBcQEIAXEBCAFRAQgBUQEEATEBAAExAQABMgEAAVMBAAFUAQABVAEA
AVUBAAFVAQABtwEMAXkBJQGaASkBmgEpAZsBKQGbASkBmwEpAbwBKQG8ASkBvAEpAZwBJQH7ATUBWgFr
AdYBWgEYAWMqAAEYAWMBMQFGAawBNQGLATEBjAExAc8BOQHRATUBtAEtAbYBKQF3AR0BGAENARgBCQH4
AQQB2AEAAfgBBAH4AQQB+AEEARkBCQEZAQkBGQEFARkBBQH4AQQB+QEEARkBBQE6AQkBOgEJAToBCQGZ
AUoBWgFrAd4Bex4AATkBZwHVAVoBeQFGAboBJQG5ASkBuQElAbgBJQGYASUBlwEhAXcBIQF2AR0BVgEd
AXYBIQF2ASEBVAEZATQBGQFVAR0BNAEZARMBFQETARUBEwEVARMBFQHyARABlAElARgBYwFaAWsB8AE9
Ab0BdzAAAVoBawG9AXcBfAFvAf8BfwHeAXsB3gF7Ad4BewHeAXsB3gF7Ad4BewHeAXsB3gF7Ad4BewEY
AWMBGAFjAVoBawH3AV4BOQFnAfcBXgHWAVoB1gFaAbUBVgG1AVYBtQFWATEBRgG9AXccAAH3AV4BUwFK
AdcBWgFSAUoBtQFWAdYBWgHWAVoB1gFaAfcBXgH3AV4B9wFeAdUBWgESASEBcQEIAbIBEAGyARABkgEM
AZIBDAFyAQgBMQEAATIBAAFTAQABVAEAAVQBAAFVAQABVQEAAVYBAAH4ARABuwEtAdsBLQHbAS0B3AEt
AdwBMQHcATEB3AExAf0BMQH9ATEB3QExAfwBNQFaAWsB9wFeAfcBXigAAd4BewExAUYB0QE1AdQBMQG1
ASkBdgEdARcBEQH3AQwB1wEEAbYBAAHWAQQB1gEEAfcBCAH3AQgBFwENARgBDQEYAQ0BOQENAVkBEQFZ
AREBWQERATkBDQE5AQ0BOQENAVoBDQE6AQ0BOgENARoBBQFZAT4BWgFrAd4Bex4AARgBZwHVAVoBWQFC
AboBKQHaASkBuQEpAbkBJQGYASUBmAEhAZcBIQF2ASEBdgEhAZYBJQF2ASEBVQEZAVUBHQF1ASEBVAEZ
ATMBFQETARUBEwEVARMBFQETAREBlAEpAfcBXgFaAWsB8AE9Ab0BdzAAAVoBawG9AXcBnAFvAf8BfwHe
AXsB3gF7Ad4BewHeAXsB3gF7Ad4BewHeAXsB3gF7Ad4BewEYAWMBGAFjAVoBawH3AV4BGAFjAdYBWgHW
AVoBtQFWAbUBVgG1AVYBtQFWATEBRgG9AXccAAH3AV4BMgFGAbYBVgFSAUoB1gFaAdYBWgHWAVoB9wFe
AfcBXgH3AV4B9wFeAfYBXgFzAS0BcgEIAdMBGAHTARQBsgEUAbMBEAFyAQQBMgEAATIBAAFTAQABVAEA
AVUBAAFVAQABVgEAAVcBAAE5ARkB+wE1AfwBNQH8ATUBHAE2AR0BNgEdAToBHQE6AR0BOgE+AToBHgE6
Af0BNQE6AWcBGAFjAdYBWioAATsBZwEXAREBtgEEAbUBAAG1AQQBtQEEAbUBBAHVAQgB1QEIAfYBDAH3
AQwBFwENARcBDQEYAREBGAERATgBEQE5AREBWQEVAXoBGQF6ARkBWQEVAVoBFQFaARUBWgEVAVoBFQFa
ARUBOwENAfkBLQE5AWcBvQF3HgABGAFjAbQBVgFZAUIB2gEpAdoBKQG5ASkBuQEpAbgBJQGYASUBlwEh
AXcBIQGXASUBtwElAZYBIQFVAR0BdQEdAXYBIQFVAR0BNAEZATQBGQE0ARkBNAEZARQBFQGVASkB1gFa
AVkBawHvAT0BvQF3MAABWgFrAb0BcwGcAXMB/wF/Af8BfwHeAXsB3gF7Ad4BewHeAXsB3gF7Ad4BewHe
AXsB3gF7ARkBYwEYAWMBWgFrAfcBXgH3AV4BtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBMQFGAb0BdxwA
AfcBXgEyAUYBtgFWAVIBSgHWAVoB9wFeAfcBXgH3AV4B9wFeAfcBXgH3AV4B9wFiAZMBMQGSAQwBFAEd
AfMBGAHzARgB0wEUAVIBAAEyAQABUwEAAVQBAAFVAQABVQEAAVYBAAFXAQABeAEAAXsBJQE8AT4BPQE+
AT0BPgE9AT4BPQE+AV4BPgFeAT4BXgFCAV4BQgFeAUIBHgE2ARoBYwE5AWcBtQFWKgABewFvAhUBtQEE
AfUBDAH1AQwB9QEMAdUBDAHVAQwB1QEIAdYBCAH2AQwB9wEMAfcBDAEXAQ0BGAENAfgBDAEYAREBeQEZ
AZoBHQF6AR0BegEdAXoBGQGbAR0BmwEdAZsBGQGbARkBewEVAboBIQE5AWMBfAFvHgABGAFjAZQBVgFZ
AUIB2wEpAdoBKQHaASkB2QEpAbkBKQG4ASUBmAElAZcBJQG4ASUBtwEpAZcBIQF2AR0BdgEhAZYBJQF1
AR0BVQEZAVUBGQFVARkBNAEZATQBFQGVASkBtQFWAVoBawHvAT0BvQFzMAABWgFrAb0BcwGcAXMB/wF/
Af8BfwH/AX8B/wF/Ad4BewHeAXsB3gF7Ad4BewHeAXsB3gF7ATkBYwEYAWMBWgFrAdYBWgH3AV4BtQFW
AbUBVgG1AVYBtQFWAbUBVgG1AVYBMQFGAb0BdxwAAfcBXgEwAUIBcQFGATIBRgHWAVoB9wFeAfcBXgH3
AV4B9wFeARgBYwEYAWMBFwFjAdMBOQGSARABNAEhATQBIQE0ASEBswEQATIBAAEzAQABVAEAAVUBAAFV
AQABVgEAAVcBAAF4AQABmQEEAdwBLQF9AUYBXQFGAX0BRgF+AUYBfgFGAX4BRgF+AUYBfwFGAZ8BRgGf
AUoBPwE+AfsCWgFrAbUBVgHeAXsoAAG8AXcBlgElAdYBCAEWAREBFgERARYBEQEWAREB9gEQAfYBDAH2
AQwB9gEMAfcBDAH3AQwB+AEMAfgBDAH4AQwBOQEVAZoBIQG7ASUBuwEhAbsBIQG7ASEBuwElAbwBIQG8
ASEBvAEhAbwBHQG7ASEBGQFfAVoBax4AARcBYwGUAVIBWQE+AdsBLQH6AS0B2gEtAdoBKQG5ASkBuQEl
AbgBJQG4ASUBuAEpAbgBKQGXASEBdgEhAZcBJQGXASUBdgEhAVUBHQFVAR0BVQEdAVUBHQFVARkBtQEp
AbUBVgFaAWsB7wE9AZ0BczAAAVoBawG9AXcBnAFzAf8BfwH/AX8B/wF/Af8BfwH/AX8B3gF7Ad4BewHe
AXsB3gF7Ad4BewE5AWcBGAFjAVoBawHWAVoB9wFeAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWATEBRgG9
AXccAAEYAWMBZwEhAagBJQExAUYB9wFeAfcBXgH3AV4B9wFeARgBYwEYAWMBOQFnARgBYwFUAUoBsgEQ
AVUBJQFVASUBVQElAXMBCAEyAQABUwEAAVQBAAFVAQABVgEAAVcBAAF3AQABeAEAAboBCAE9AToBngFK
AZ4BSgGeAUoBngFKAZ8BTgG/AU4BvwFOAb8BTgG/AU4BvwFOAX8BQgHcAVYBegFvAbUBVgG9AXcoAAHe
AX8BFwE6AfYBDAE2ARUBNgEVATYBFQE2ARUBFgEVAfYBEAH2ARABFwERARcBEQEYAREBGAERARgBEQEZ
AREBWgEZAdsBJQHbASkB2wEpAdsBKQHcASkB/AEpAfwBKQHcASkB3AElAdwBJQG7ASEB2QFWAVoBax4A
AfcBXgGUAVIBWQE+AfwBLQH7AS0B+gEtAdoBLQHaASkB2QEpAbkBKQHZASkB2QEtAbgBKQGXASEBlwEh
AZcBJQG3ASkBdwEhAXYBHQF2AR0BdgEdAXYBHQFWAR0BtgEpAZQBUgFaAWsB8AE9Ab0BczAAAVoBawG9
AXcBnAFzAf8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwHeAXsB3gF7Af8BfwE5AWcBGAFjAVoBawHW
AVoB9wFeAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWATEBRgG9AXccAAE5AWcB6AEcASsBJQExAUYB9wFe
AfcBXgH3AV4BGAFjARgBYwEYAWMBOQFnARgBYwHWAVoB0gEUAXUBKQGWAS0BNQEdATIBAAEzAQABVAEA
AVUBAAFVAQABVgEAAXcBAAF4AQABeQEAAfsBEAF9AUYBvgFSAb4BUgG+AVIB3wFSAd8BUgHfAVIB3wFS
Ad8BUgHfAVYB/wFWAZ8BSgHcAVYBegFvAbUBVgF7AW8oAAH/AX8BeAFKARYBEQFXARkBVwEdAVcBHQFX
AR0BNwEVARYBEQEXAREBFwEVARgBFQE4ARUBOAEVATkBFQE5ARUBegEdAfsBLQEcATIB/AEtAfwBLQEc
ATIBHAEyARwBMgEcAS4BHQEuAR0BLgHcASUBmQFOAVoBax4AAfcBXgGUAVIBOQE+AfwBLQH7AS0B+wEt
AdoBLQHaASkB2gEpAdkBKQH5AS0B+QEtAbkBKQGYASUBmAElAbgBKQG4ASkBlwEhAXcBIQF2ASEBdgEh
AXYBIQF2AR0BtgEpAZQBUgFZAWsBEAE+AZwBczAAAVoBawG9AXMBnAFzAf8BfwH/AX8B/wF/Af8BfwH/
AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwE5AWcB+AFeAVoBawHWAVoB9wFeAbUBVgG1AVYBtQFWAbUBVgG1
AVYBtQFWATEBRgG9AXccAAE5AWcBCAEhAWsBLQEQAUIBGAFjAfcBXgH3AV4BGAFjARgBYwE5AWcBOQFn
ATgBZwH4AWIB8gEcAXYBLQG3ATEB1AEQATIBAAFTAQABVAEAAVUBAAFWAQABdwEAAXkBAAF6AQABewEA
AV0BHQHfAVIB/wFWAf8BVgH/AVYB/wFWAR8BVwEfAVsBHwFbAR8BWwEfAVsBPwFbAf8BUgH9AVYBewFz
AdYCWgFrKgAB2AFWATYBGQF3AR0BdwEhAXcBIQF3ASEBNwEZARcBFQE3ARUBOAEVATgBFQE4ARUBOQEV
ATkBFQFaARkBuwElARwBNgE8ATYBPAE2ATwBNgFdAToBXQE6AT0BNgE9ATYBPQE2AT0BMgH9ASkBegFG
ATgBZwHeAXscAAH3AV4BlAFSAVoBQgE8ATYBHAE2AfsBMQH7AS0B+gEtAdoBLQH6AS0B+gExAfoBLQHZ
ASkBuAElAbgBJQHZASkB2AEpAZgBJQGXASEBlwEhAXcBIQGXASEBdwEhAdYBLQGUAVIBWQFrARABQgGd
AXMwAAFaAWsBnAFzAZwBcwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8BOQFn
AfcBXgFaAWsB1gFaAfcBXgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgExAUYBvQF3HAABnAFzAa0BNQHv
AT0B9gFeAXsBbwE5AWcBGAFjARgBYwEYAWMBOQFnATkBZwE5AWcBGAFjATIBIQGWAS0BlgEtAXMBBAEz
AQABVQEAAVYBAAF3AQABeAEAAXoBAAF7AQABnAEAAZ0BAAHeAS0BHwFbAR8BXwEfAVsBHwFfAT8BXwE/
AV8BPwFfAT8BXwE/BV8BPwFXAf0BUgF7AXMB1gFaARgBYyoAAToBYwFWAR0BeAEhAZgBJQGYASUBeAEh
ATcBGQE3ARkBOAEZATgBGQFYARkBWQEZAVkBGQFaARkBegEdAdsBLQFcAT4BXAE+AV0BPgF9AT4BfQE+
AX0BPgFdAToBXQE6AV0BOgFdAToBPQEyAXsBPgH4AV4BvQF3HAAB1gFaAZQBUgF6AUIBXQE6AVwBOgE8
AToBPAE2ARsBNgEbATIBGwE2ARsBNgH6ATEB2QEpAbkBKQHZASkB2QEtAdkBLQG4ASUBmAElAZgBJQG4
ASUBuAElAbgBJQHXATEBlAFOATkBawERAUIBnAFzMAABWgFrAZwBcwGcAXMB/wF/Af8BfwH/AX8B/wF/
Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/ATkBZwH3AV4BWgFrAdYBWgH3AV4BtQFWAbUBVgG1AVYBtQFW
AbUBVgG1AVYBMQFGAb0Bdx4AAd4BewHeAXsCAAHdAXsBvQF3AZwBdwF7AXMBegFvAVoBawE5AWcBOQFn
ATgBZwFzAS0BlgEtATYBIQEzAQABVAEAAVUBAAFXAQABeAEAAXkBAAF6AQABmwEAAZwBAAG9AQABXwE+
AT8BYwE/AWMBPwFjAV8BYwFfAWMBXwFjAV8BYwFfAWMBXwFjAX8BZwF/AWcBXwFjAd0BUgF8AW8B9wFe
AfcBXioAAXsBbwGWASUBmAElAdgBLQG4AS0BeAEhATcBGQE4ARkBWAEZAVgBHQFZAR0BWQEdAXoBHQF6
AR0BewEhARwBNgF9AUIBfQFCAX0BQgGdAUYBnQFGAZ0BQgGdAUIBfgFCAX4BPgF9AT4BfgE6AVsBOgEY
AWMBfAFvHAAB1gFaAbUBVgF7AUIBXQE+AV0BPgFcAT4BXAE6ATwBOgFcAT4BXAE+AVsBPgE7ATYBGgEy
AfoBMQEaATIBGgE2ARoBNgH5AS0B2QEtAdkBLQHZAS0B2QEtAdkBKQH3ATEBlAFSATkBawExAUIBnAFz
MAABWgFrAZwBcwGcAXMB/wF/Af8BfwH/AX8B3gF7AVsBawG+AXcB/wF/Af8BfwH/AX8B/wF/ATkBZwH3
AV4BWgFrAdYBWgH3AV4BtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBMQFGAb0BdyoAAd4BewHdAXsBvQF3
AZwBcwF7AW8BWQFrAdQBNQFWASUBtAEQATMBAAFVAQABVgEAAXcBAAF4AQABeQEAAXoBAAGbAQABnQEA
Af4BCAG/AU4BfwFnAV8BZwFfAWcBfwFnAX8BZwF/AWcBfwFnAX8BZwF/AWsBfwFrAZ8BawF/AWcB/gFS
AXwBbwE4AWcB9wFeKgABvAF3AdYBMQGYASkB+QExAdkBLQFXASEBWAEdAVgBHQFYAR0BeQEdAXkBHQF6
AR0BewEhAXsBHQG8ASUBXQE+AZ0BSgG+AUoBvgFKAb4BSgG+AUoBvgFGAb4BRgG+AUYBvgFGAb4BQgGe
AUIBXAE6ARkBXwFaAWscAAHWAVoBtQFWAXsBRgFdAT4BXQE+AV0BPgFcAT4BXAE+AXwBQgF8AUIBXAE+
ATsBOgEbATYBGwE2ATsBOgE7AToBGgE2AfoBMQH6AS0B+gEtAfkBLQHZAS0B2gEtAfgBNQGUAVIBOQFr
ATEBRgGcAXMwAAFaAWsBnQFzAZwBcwH/AX8B/wF/Ad4BewEvAToBaQEuAbABRgHeAXsB/wF/Af8BfwHe
AXsBGAFjARgBYwFaAWsB1gFaAfcBXgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgExAUYBvQF3MgAB3gF7
AXoBbwEVAUIB1AEUAVMBAAFUAQABVQEAAVYBAAF3AQABeAEAAXoBAAGbAQABnAEAAX0BAAFeARkBHwFf
AX8BawF/AWsBfwFrAX8BawF/AWsBnwFrAZ8BawGfAWsBnwFvAZ8BbwGfAW8BnwFvAR8BVwF8AW8BWgFr
AbUBVioAAd0BewE3AUIBuAEpARkBNgG4ASkBVwEdAVgBHQF5ASEBeQEhAXoBIQGaASEBmwEhAZwBIQGc
ASEB3QEpAZ4BRgHeAU4B3gFOAd4BUgHeAU4B3gFOAd4BTgHeAUoB3gFKAd4BSgHeAUoBvgFGAX0BOgH5
AVYBOQFnHAAB1gFaAdYBWgF7AUYBfgFCAX0BQgF9AUIBfQFCAX0BQgF9AUYBfQFCAVwBPgE8AToBOwE6
ATsBOgE7AToBOwE6ARsBNgEaATIB+gExAfoBMQH6ATEB+gExAfoBLQH4ATUBlQFSATkBZwExAUYBnAFz
MAABWgFrAb0BdwGcAXMB/wF/Af8BfwE5AWcBCQEmAZABVwEOAU8B1gFWAXwBbwFaAWsBOQFnATkBZwE5
AWcBWgFrAdYBWgH3AV4BtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBMQFGAb0BdzQAAZsBcwF2AU4BUgEA
ATMBAAFUAQABVQEAAVcBAAF4AQABeQEAAXoBAAGbAQABnAEAAZ0BAAG/ASkBfwFrAZ8BbwGfAW8BnwFv
AZ8BbwGfAW8BnwFvAZ8BbwGfAW8BvwFvAb8BcwG/AXMBvwFzAT8BXwF8AWsBnAFzAZQBUgHeAXsoAAH+
AX8BdwFKAbgBLQEaATYBmAEpAXgBIQF5ASEBeQEhAZoBIQGaASEBmwElAbwBJQG8ASUBvQElAR0BMgG+
AU4B/gFWAf4BVgH+AVYB/gFSAd4BTgHeAVIB/gFSAf4BTgHeAU4B3gFOAd4BSgGdAT4B2QFSATkBZxoA
Ad4BewHVAVoB1gFaAZwBRgF+AUIBnQFGAZ0BRgGdAUYBnQFKAZ0BSgGdAUYBfAFCAVwBPgFcAToBXAE+
AVwBPgFcAT4BOwE6ARsBNgEbATIBGwEyARoBMgH6ATEB+wExARgBNgG1AVYBOQFnATEBRgGcAXMwAAFa
AWsB3gF7Ab0BdwGcAXMBnAFzARkBZwFOAToBcgFbAawBPgH3AV4BWgFrAVoBawFaAWsBWgFrAVoBawF7
AW8B1gFaAfcBXgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgFSAUoBvQF3NAABmwFzAbcBVgFSAQABMwEA
AVQBAAFVAQABdwEAAXgBAAF5AQABegEAAZsBAAGdAQABngEAAV8BPgGfAXMBnwFzAZ8BbwG/AXMBvwFz
Ab8BcwG/AXMBvwFzAb8BcwG/AXMBvwFzAb8BcwG/AW8BPwFbAV0BZwG9AXcBlAFSAb0BdyoAAbgBVgHY
AS0B+QExAZgBJQF4ASEBmQElAZoBJQGaASUBuwElAbsBKQG8ASkBvAElAb0BJQFeAToB/gFWAR4BWwEe
AVsBHgFXAf4BVgH+AVIB/gFSAf4BUgH+AVIB/gFSAf4BUgH+AU4BvgFGAdoBTgEXAWMB3gF7GAAB3gF7
AbUBVgH3AV4BnAFKAZ4BRgGdAUYBvgFKAb4BSgG+AU4BvgFKAZ0BSgF9AUIBfAFCAVwBPgF8AT4BfAFC
AVwBPgE8AToBGwE2ARsBNgEbATYBGwE2ARsBMgEbATIBGAE6AbUBVgE5AWcBUgFGAZwBczAAAVoBawHe
AXsB3gF7Ad4BewHeAXsB3gF7ATkBZwFxAUIB1QFWAZwBcwF7AW8BewFvAXsBbwF7AW8BewFvAXsBbwHW
AVoB9wFeAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAVIBSgG9AXc0AAGcAXMB9wFeAZIBCAEzAQABVQEA
AVYBAAF3AQABeAEAAXkBAAF7AQABnAEAAZ0BAAHeAQQB3wFSAb8BdwG/AXMBvwFzAZ8BbwGfAW8BfwFr
AX8BZwFfAWMBPwFfAT8BWwEeAVcB/gFWAf0BVgHcAU4BXAFnAd4BfwGUAVIBnAFzKgABGQFjAdcBMQG5
AS0BeAElAZkBJQGZASUBmgElAbsBKQG7ASkB3AEtAdwBKQHdASkB3QEtAZ4BRgE/AV8BPgFfAT4BXwEe
AVsBHgFbAR4BVwEeAVcBHgFXAR4BVwEeAVcBHgFXAf4BUgHeAUoBuwFKAfcBXgG9AXcYAAHeAXsBlAFW
AfgBXgG9AUoBngFGAb4BSgHeAU4B3gFSAd4BUgHeAU4BvQFKAZ0BRgGdAUYBfQFCAX0BQgF9AUIBXAE+
ATwBOgE8AToBPAE2ATwBNgEcATYBHAE2ARwBNgEZAToBtQFWATkBZwFSAUoBnAFzMAABewFvAd4BewH/
AX8B/wF/Ad4BewHeAXsB3gF7Ab4BewG+AXsBnAFzAXsBbwF7AW8BewFvAXsBbwF7AW8BnAFzAbUBVgEY
AWMBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBUgFKAb0BdzQAAb0BdwEYAWMB0gEUATQBAAFVAQABVgEA
AXcBAAF4AQABegEAAXsBAAF8AQABfQEAAd8BBAGfAUYBHwFbAf8BVgHfAU4BvgFKAbwBSgG7AU4B2wFS
AfsBVgH7AVYBGgFfAToBZwF7AWsBnAFzAb0BdwHeAXsCAAFaAWsB3gF7KgABewFvAdcBMQGYASUBmAEl
AZkBJQG6ASkBugEpAdsBLQHcAS0B3AEtAd0BLQHdAS0BHgE2Ad8BUgFfAWcBXwFjAT4BYwE+AV8BPgFf
AT4BWwEeAVsBHgFbAR4BWwEeAVsBHgFXAR4BVwH+AVIBuwFGAfcBXgGcAXMYAAHeAXsBlAFWARgBXwG9
AU4BvgFKAd4BTgH+AVIB/gFWAf4BVgHeAVIB3gFOAb0BSgGdAUoBnQFGAZ0BRgGdAUYBfQFCAVwBOgE8
AToBPAE6ATwBNgE8ATYBPAE2ATwBNgEZAToBtQFWATkBZwFSAUoBnAFzMAABewFvAb0BdwG9AXcBvQF3
Ab0BdwGcAXMBnAFzAZwBcwG9AXcBvQF3Ab0BdwHeAXsB3gF7Ad4BewH/AX8B/wF/AdYBWgH3AV4BGAFj
AfcBXgHWAVoBtQFWAbUBVgG1AVYBUgFKAb0BdzQAAd4BewE4AWcBMwEhARQBAAE1AQABNgEAAVYBAAF3
AQABmAEEAbgBCAEZARUBWgEdAboBLQF6AUYBuQFSAdkBWgEaAV8BGgFjAToBZwFaAWsBewFvAZwBdwG8
AXcBvQF3Ad4BewHeAXs2AAGcAXMB9gE1AXgBJQGZASkBuQEpAboBKQHbAS0B2wExAfwBMQH8ATEB/QEx
Af0BMQFeAT4BHwFfAX8BawFfAWcBXgFjAV4BYwFeAWMBPgFfAT4BXwE+AVsBHgFbAR4BVwH+AVYB/QFS
Ad0BSgF7AT4B+AJaAWsYAAG9AXcBtAFWAfgBXgHdAU4B3gFOAf4BVgH+AVYBHgFbAf4BVgH+AVYB3gFS
Ad4BTgG+AU4BvgFKAb0BSgGdAUYBfQFCAV0BPgFdAToBPAE6ATwBOgE8AToBPAE6AT0BNgE5AToB1gFa
ATkBZwFSAUoBnAFzMAABnAFzAd4BewHeAXsB3gF7Ad4BewHeAXsB/wF/Af8BfwH/AX8B3gF7Ad4BewG9
AXcBvQF3AZwBcwF7AW8BnAFvAVoBawHWAVoBtQFWAbUBVgHWAVoB9wFiAfcBXgH3AV4BUgFKAb0BdzYA
ATkBZwHTATkB8QEYAXQBKQG1ATEB9QE5ATQBRgGVAVIB9wFeATgBZwFZAWsBeQFvAXoBcwGcAXMBvAF3
Ab0BdwG9AXcB3gF7RAAB3QF7ATYBQgGYASUBmQEpAbkBKQHaAS0B2wExAfsBMQH8ATEB/QExAR0BNgEe
ATYBfwFGAV8BYwF/AWsBfwFnAV8BZwE/AV8BPgFbAR4BVwH9AVIB3AFSAbsBTgG6AU4B2gFSAdkBVgHY
AVYB+AFaATkBYwEYAWMYAAG9AXcBtAFWAfgBXgHdAVIB/gFSAf4BVgEeAVsBHgFbAR4BWwH+AVYB/gFW
Ad4BUgHeAVIB3gFOAb4BSgGdAUYBfQFCAV0BPgFdAT4BXQE6AV0BOgFdAToBPQE6AT0BOgE5AToBtgFW
ARgBYwFSAUoBnAFzMAABvQF3Ab0BdwHeAXsB3gF7Ad4BewG9AXcBnAFzAZwBcwF7AW8BWgFnARgBYwH3
AV4B1wFaAdYBWgG2AVYB1gFWAdcBWgH4AV4BGAFjAfcBXgHWAVYBlAFSAXMBTgGUAlIBSgG9AXc2AAE5
AWcB9wFeAfYBYgE4AWsBegFvAZsBcwGcAXMBvAF3Ab0BewHeAXtUAAH+AX8BdgFKAZgBKQG5ASkB2gEt
AdoBMQH7ATEB/AE1ARwBNgEdATYBHgE2AR4BNgGeAUYBPgFfAT4BXwEcAVsB+wFWAfsBWgH7AVoB+gFa
AfkBXgE6AWcBWgFrAVoBawFaAW8BmwFzAbwBdwG8AXcBnAFzAd4BexgAAb0BdwG1AVYB+AFeAd0BUgH+
AVYBHgFbAR4BWwEeAVsBHgFbAR4BWwEeAVcB/gFWAf4BUgHeAVIBvgFOAZ4BRgF9AUIBfQE+AV0BPgFd
AT4BXgE6AV4BOgE9AToBPgE2ARkBOgG1AVYBGAFjAVIBSgGcAXMwAAHeAXsBnAFzAZwBcwF8AW8BewFv
AXsBbwE5AWcB9wFeAbUBVgG1AVIBlAFSAZQBUgGUAVIBlAFSAZUBUgGVAVIBtQFSAbUBVgHWAVYB9wFa
ARgBYwEYAWMB9wFeAZQBUgHWAVoB3gF7NgAB3gF7Ad4Be2YAAbcBUgG4ASkBuQEtAdoBLQHaATEB+wE1
ARsBOgEbAToBOwE+AXsBRgG7AU4B+wFaARoBYwFbAWcBewFrAXsBbwF7AW8BnAFzAb0BdwG9AXsB3QF7
Ad4BeyYAAb0BdwG1AVYB+AFaAf4BUgH+AVYBHgFbAR8BXwE/AV8BPwFfAR8BXwEfAVsB/gFWAf4BUgHe
AU4BvQFOAZ0BRgF8AUIBXAFCAVsBPgE6AT4BOAE6ATgBPgFYAUIBNwFCATQBQgGUAVIB9wFiAVIBSgGc
AXM4AAHeAXsBvQF3AXwBbwFaAWcB9wFeAbYBVgG1AVYBtQFWAbYBVgHWAVoB1gFaAdcBWgH3AV4BOQFj
ATkBZwFaAWsBewFvAZwBcwG9AXcB3gF7pAAB+AFeAdYBNQEXAT4BWAFGAZkBTgHZAVYBGgFjAVsBawF7
AW8BnAFzAb0BdwHdAXsB3QF7Ad4BewHeAXs0AAG9AXcBtQFWAfkBWgH+AVIB/QFWAdwBVgHbAVIB2wFW
AdoBVgHaAVYB2QFSAbgBUgGXAU4BdgFOAXUBSgF0AUoBdAFOAXQBTgGUAVIBlAFSAZQBUgGTAVIBkwFS
AZMBUgGUAVIBlAFSAfcBXgFSAUoBnAFzQgAB3gF7AZwBcwF7AW8BnAFzAb0BdwHeAXu2AAGcAXMBWgFr
AZwBcwG9AXcB3gF7Af4BfwH+AX9EAAGcAXcBtQFWAXQBTgF0AU4BdAFOAXMBTgFTAUoBUgFKAVIBSgFS
AUoBUgFKAVIBSgFyAU4BkwFSAZQBUgGUAVIBtAFWAbUBVgG1AVYB1gFaAdYBWgHWAVoB1gFaAdYBWgHW
AVoBlAFSAdYBWgHvAT0BvQF3/wBXAAG9AXcBtQFWAVIBSgFSAUoBUgFKAVIBSgFzAU4BcwFOAZQBUgGU
AVIBlAFSAZQBUgG1AVYBtQFWAbUBVgG1AVYB1gFWAdYBWgHWAVoB1gFaAdYBWgH3AV4B9wFeAfcBXgH3
AVoBtQFWAfABPQHwAT3/AFkAAb0BdwH3AV4B1gFaAbUBVgGUAVIBlAFSAZQBUgG1AVIBlQFSAZQBUgHW
AVYBlAFOAe8BPQHvAT0BlAFSARgBYwH3AVoB1gFaAfcBWgH3AVoB9wFeAfgBXgH4AVoB1wFaAdcBVgHX
AVoBtgFWAZ0Bc/8AWwABewFrAVsBZwFbAWcBOgFjATkBYwEZAWMBGQFjARkBYwEYAV8BewFrAZQBTgGM
ATEBzgE5ATIBRgFaAWcBGQFfAfgBXgH4AV4B+AFaAdcBWgEZAV8BGQFjAVoBZwGcAXMB3gF7/wBhAAG9
AXcBfAFvAXsBawFbAWsBWwFrAVoBZwE6AWcBOgFjARoBYwEZAV8B+AFaAfgBXgEZAWMBOgFnAVoBZwFb
AWsBfAFvAb0BdwHeAXsB3gF7/wB1AAHeAXsB3gF7Ad4BewHeAXv/AP8ALgABQgFNAT4HAAE+AwABKAMA
AcgDAAFkAwABAQEAAQEFAAHwAQoWAAP/AQAM/wHwDwAM/wHwDwAM/wHwDwAM/wHwDwAM/wHwDwAM/wHw
DwAM/wHwDwAM/wHwDwAM/wHwDwAM/wHwDwAD/wGDCP8B8A8AAv8B8AEABf8B+AF/Af8B8A8AAv8CAAE/
A/8B/gEAAR8B/wHwDwAB/wHwAgABHwP/AcABAAEHAf8B8A8AAf8BgAIAAQcC/wH+AgABAQH/AfAPAAH4
AwABAwL/AfADAAF/AfAPAAHwBAAC/wGAAwABPwHwDwAB8AQAAX8B/AQAAQ8B8A8AAeAEAAEfAfgEAAEH
AfAPAAHgBAABDwHwBAABAQHwDwAB4AQAAQcB8AUAAfAPAAHgBAABAQHwBQABcA8AAeAFAAHwBQABMA8A
AeAFAAFwBQABEA8AAeAFAAFwBQABEA8AAeAFAAF8BQABEA8AAfgEAAEBAf8FAAEQDwAB/gQAAQEB/wHA
BAABMA8AAf8BwAMAAQEB/wH4BAABcA8AAf8B+AMAAQMC/wQAAfAPAAL/AwABBwL/AeACAAF/AfAPAAL/
AeACAAP/AfwBAAEPAf8B8A8AAv8B/AEAAT8E/wGHAv8B8A8ADP8B8A8ADP8B8A8ADP8B8A8ADP8B8A8A
DP8B8A8ADP8B8A8ADP8B8A8ADP8B8A8ADP8B8A8ADP8B8A8ADP8B8A8ADP8B8A8ADP8B8A8ADP8B8A8A
DP8B8A8ADP8B8A8ADP8B8A8AGf8DAA//AfgBAwj/AwAP/wIAAT8H/wMADv8B+AIAAR8H/wMAA/8BwAEf
BP8B8AF/A/8B8AIAAQcE/wGPAv8DAAL/Af4BAAEDBP8BgAEfA/8BwAIAAQMD/wH4AQcC/wMAAv8B+AIA
AQcC/wH8AQABDwP/AcACAAEBA/8BwAEBAv8DAAL/AfACAAEBAv8BwAEAAQMD/wGAAwAC/wH8AgAC/wMA
Av8B8AMAAf8B/gIAAQED/wQAAX8B/wHgAgABPwH/AwAB+AEHAeADAAF/AeADAAP/BAABPwH/AcACAAEf
Af8DAAHwAQAB4AMAAX8EAAE/Av8EAAEfAf8BwAIAAQ8B/wMAAeABAAEwAwAB+AQAAR8C/wQAAR8B/wHg
AgABBwH/AwAB4AQAAQEB8AQAAQcB/wH+BAABHwH/AeACAAEBAf8DAAHgBAABDwHgBAABAwH/Af4DAAEB
Av8B4AMAAf8DAAHgBAABDwHwBAABAQH/Af4DAAEfAv8B4AMAAX8DAAHgBAABDwH4BQAB/wH+AwABHwL/
AeADAAEfAwAB4AQAAQ8B/gQAAQEB/wH+AwABHwL/AeADAAEPAwAB4AQAAQcB/wGAAwABAQH/Af4DAAEf
Av8B4AMAAT8DAAHgBAABBwH/AeADAAEBAf8B/gMAAR8C/wHgAgABBwH/AwAB4AQAAQcB/wH4AwABAQH/
Af4DAAEfAv8B4AIAAQcB/wMAAeAEAAEHAf8B/gMAAQEB/wH+AwABHwL/AeACAAEHAf8DAAHgBAABBwL/
AfACAAEBAf8B/gMAAR8C/wHgAgABBwH/AwAB4AQAAQcC/wHAAwAB/wH+AwABHwL/AeACAAEHAf8DAAHg
BAABBwL/AYADAAH/Af4DAAEfAv8B4AIAAQcB/wMAAeAEAAEHAv8BwAMAAf8B/gMAAR8C/wHgAgABBwH/
AwAB4AQAAQcC/wHAAwAB/wH+AwABHwL/AeACAAEHAf8DAAHgBAABAwL/AcADAAH/Af4DAAEfAv8B4AIA
AQcB/wMAAeAEAAEDAv8BwAMAAf8B/gMAAR8C/wHgAgABBwH/AwAB4AQAAQMC/wHAAwAB/wH+AwABHwL/
AeACAAEHAf8DAAHgBAABAwL/AeADAAF/Af4DAAEfAv8B4AIAAQcB/wMAAeAEAAEDAv8B4AMAAX8B/gMA
AR8C/wHgAgABBwH/AwAB8gQAAQMC/wHgAwABfwH+AwABHwL/AeACAAEHAf8DAAH/AcADAAEDAv8B4AMA
AX8B/gMAAR8C/wHgAgABBwH/AwAB/wH8AwABAwL/AeADAAF/Af4DAAEfAv8B4AIAAQcB/wMAAf8B/gMA
AQEC/wHgAwABfwH8AwABHwL/AeACAAEHAf8DAAH/Af4DAAEBAv8B8AMAAT8B/AMAAR8C/wHgAgABBwH/
AwAB/wH+AwABAQL/AfADAAE/AfwDAAEfAv8B4AIAAQcB/wMAAf8B/gMAAQkC/wHwAwABPwH8AwABHwL/
AeACAAEHAf8DAAH/Af4DAAF/Av8B8AMAAT8B/AMAAR8C/wHgAgABBwH/AwAC/wIAAT8D/wHwAwABPwH8
AwABHwL/AeACAAEHAf8DAAL/AQABPwT/AfADAAE/AfwDAAEfAv8B4AIAAQcB/wMAAv8BPwX/AfgCAAEf
Af8B/AMAAR8C/wH+AgABHwH/AwAI/wH4AQABDwL/AfwDAAEfA/8B8AE/Av8DAAj/AfgBDwP/AfwDAAEf
B/8DAA3/AfwDAAE/B/8DAA3/AfwDAAE/B/8DAA3/Af4DAAj/AwAO/wIAAQ8I/wMADv8B/AE/Cf8DABn/
AwAL
</value>
</data>
</root>

67
MappingHelpForm.Designer.cs generated Normal file
View File

@@ -0,0 +1,67 @@
namespace MeshCentralRouter
{
partial class MappingHelpForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MappingHelpForm));
this.helpPictureBox = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.helpPictureBox)).BeginInit();
this.SuspendLayout();
//
// helpPictureBox
//
this.helpPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.helpPictureBox.Image = global::MeshCentralRouter.Properties.Resources.HelpRelayMap;
this.helpPictureBox.Location = new System.Drawing.Point(0, 0);
this.helpPictureBox.Name = "helpPictureBox";
this.helpPictureBox.Size = new System.Drawing.Size(325, 435);
this.helpPictureBox.TabIndex = 0;
this.helpPictureBox.TabStop = false;
//
// MappingHelpForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(325, 435);
this.Controls.Add(this.helpPictureBox);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "MappingHelpForm";
this.Text = "Port Mapping Help";
((System.ComponentModel.ISupportInitialize)(this.helpPictureBox)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PictureBox helpPictureBox;
}
}

20
MappingHelpForm.cs Normal file
View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MeshCentralRouter
{
public partial class MappingHelpForm : Form
{
public MappingHelpForm()
{
InitializeComponent();
}
}
}

1815
MappingHelpForm.resx Normal file

File diff suppressed because it is too large Load Diff

BIN
MeshCentral.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

231
MeshCentralRouter.csproj Normal file
View File

@@ -0,0 +1,231 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{14404E31-A185-4CD8-8DC3-6A2F5FE216FF}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MeshCentralRouter</RootNamespace>
<AssemblyName>MeshCentralRouter</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<StartupObject>MeshCentralRouter.Program</StartupObject>
<ApplicationIcon>MeshServer.ico</ApplicationIcon>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Messaging" />
<Reference Include="System.Security" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AddPortMapForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AddPortMapForm.Designer.cs">
<DependentUpon>AddPortMapForm.cs</DependentUpon>
</Compile>
<Compile Include="AddRelayMapForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AddRelayMapForm.designer.cs">
<DependentUpon>AddRelayMapForm.cs</DependentUpon>
</Compile>
<Compile Include="AppLaunchForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AppLaunchForm.Designer.cs">
<DependentUpon>AppLaunchForm.cs</DependentUpon>
</Compile>
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="MappingHelpForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MappingHelpForm.Designer.cs">
<DependentUpon>MappingHelpForm.cs</DependentUpon>
</Compile>
<Compile Include="MapUserControl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="MapUserControl.Designer.cs">
<DependentUpon>MapUserControl.cs</DependentUpon>
</Compile>
<Compile Include="MeshCentralServer.cs" />
<Compile Include="MeshDiscovery.cs" />
<Compile Include="MeshMapper.cs" />
<Compile Include="NodeClass.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="ServerUserControl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="ServerUserControl.Designer.cs">
<DependentUpon>ServerUserControl.cs</DependentUpon>
</Compile>
<Compile Include="SettingsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="SettingsForm.Designer.cs">
<DependentUpon>SettingsForm.cs</DependentUpon>
</Compile>
<Compile Include="Win32Api.cs" />
<EmbeddedResource Include="AddPortMapForm.resx">
<DependentUpon>AddPortMapForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="AddRelayMapForm.resx">
<DependentUpon>AddRelayMapForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="AppLaunchForm.resx">
<DependentUpon>AppLaunchForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="MappingHelpForm.resx">
<DependentUpon>MappingHelpForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MapUserControl.resx">
<DependentUpon>MapUserControl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="ServerUserControl.resx">
<DependentUpon>ServerUserControl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="SettingsForm.resx">
<DependentUpon>SettingsForm.cs</DependentUpon>
</EmbeddedResource>
<None Include="app.manifest">
<SubType>Designer</SubType>
</None>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<None Include="warning-small.png" />
<None Include="MeshServerLogo.png" />
<None Include="MC2-Banner.png" />
<None Include="Empty-Banner.png" />
<None Include="MC2-Logo.png" />
<None Include="MeshCentral.png" />
<None Include="icons01.png" />
<None Include="MeshIcon50T.png" />
<None Include="Folder36.png" />
<None Include="Help20.png" />
<None Include="HelpImages\HelpRelayMap.png" />
<Content Include="MeshServer.ico" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

22
MeshCentralRouter.sln Normal file
View File

@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MeshCentralRouter", "MeshCentralRouter.csproj", "{14404E31-A185-4CD8-8DC3-6A2F5FE216FF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{14404E31-A185-4CD8-8DC3-6A2F5FE216FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14404E31-A185-4CD8-8DC3-6A2F5FE216FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14404E31-A185-4CD8-8DC3-6A2F5FE216FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14404E31-A185-4CD8-8DC3-6A2F5FE216FF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

663
MeshCentralServer.cs Normal file
View File

@@ -0,0 +1,663 @@
/*
Copyright 2009-2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using System;
using System.IO;
using System.Net;
using System.Web;
using System.Text;
using System.Collections;
using System.Net.Sockets;
using System.Net.Security;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Deployment.Application;
using System.Collections.Specialized;
using System.Web.Script.Serialization;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32;
namespace MeshCentralRouter
{
public class MeshCentralServer
{
private Uri wsurl = null;
private string user = null;
private string pass = null;
private string token = null;
private xwebclient wc = null;
//private System.Timers.Timer procTimer = new System.Timers.Timer(5000);
private int constate = 0;
public Dictionary<string, NodeClass> nodes = null;
public Dictionary<string, MeshClass> meshes = null;
public string disconnectCause = null;
public string disconnectMsg = null;
public X509Certificate2 disconnectCert;
public string authCookie = null;
public string loginCookie = null;
public string wshash = null;
public string okCertHash = null;
public bool debug = false;
public bool ignoreCert = false;
public static void saveToRegistry(string name, string value)
{
try { Registry.SetValue(@"HKEY_CURRENT_USER\SOFTWARE\OpenSource\MeshRouter", name, value); } catch (Exception) { }
}
public static string loadFromRegistry(string name)
{
try { return Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\OpenSource\MeshRouter", name, "").ToString(); } catch (Exception) { return ""; }
}
public static string GetProxyForUrlUsingPac(string DestinationUrl, string PacUri)
{
IntPtr WinHttpSession = Win32Api.WinHttpOpen("User", Win32Api.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, IntPtr.Zero, IntPtr.Zero, 0);
Win32Api.WINHTTP_AUTOPROXY_OPTIONS ProxyOptions = new Win32Api.WINHTTP_AUTOPROXY_OPTIONS();
Win32Api.WINHTTP_PROXY_INFO ProxyInfo = new Win32Api.WINHTTP_PROXY_INFO();
ProxyOptions.dwFlags = Win32Api.WINHTTP_AUTOPROXY_CONFIG_URL;
ProxyOptions.dwAutoDetectFlags = (Win32Api.WINHTTP_AUTO_DETECT_TYPE_DHCP | Win32Api.WINHTTP_AUTO_DETECT_TYPE_DNS_A);
ProxyOptions.lpszAutoConfigUrl = PacUri;
// Get Proxy
bool IsSuccess = Win32Api.WinHttpGetProxyForUrl(WinHttpSession, DestinationUrl, ref ProxyOptions, ref ProxyInfo);
Win32Api.WinHttpCloseHandle(WinHttpSession);
if (IsSuccess)
{
return ProxyInfo.lpszProxy;
}
else
{
Console.WriteLine("Error: {0}", Win32Api.GetLastError());
return null;
}
}
// Parse the URL query parameters and returns a collection
public static NameValueCollection GetQueryStringParameters()
{
NameValueCollection nameValueTable = new NameValueCollection();
if (ApplicationDeployment.IsNetworkDeployed)
{
string queryString = ApplicationDeployment.CurrentDeployment.ActivationUri.Query;
nameValueTable = HttpUtility.ParseQueryString(queryString);
}
return (nameValueTable);
}
// Starts the routing server, called when the start button is pressed
public void connect(Uri wsurl, string user, string pass, string token)
{
this.user = user;
this.pass = pass;
this.token = token;
this.wsurl = wsurl;
wc = new xwebclient();
//Debug("#" + counter + ": Connecting web socket to: " + wsurl.ToString());
wc.Start(this, wsurl, user, pass, token, wshash);
if (debug) { File.AppendAllText("debug.log", "Connect-" + wsurl + "\r\n"); }
wc.xdebug = debug;
wc.xignoreCert = ignoreCert;
}
public void disconnect()
{
if (wc != null)
{
wc.Dispose();
wc = null;
if (debug) { File.AppendAllText("debug.log", "Disconnect\r\n"); }
}
}
public void refreshCookies()
{
if (wc != null) {
if (debug) { File.AppendAllText("debug.log", "RefreshCookies\r\n"); }
wc.WriteStringWebSocket("{\"action\":\"authcookie\"}");
wc.WriteStringWebSocket("{\"action\":\"logincookie\"}");
}
}
public void processServerData(string data)
{
if (debug) { File.AppendAllText("debug.log", "ServerData-" + data + "\r\n"); }
// Parse the received JSON
Dictionary<string, object> jsonAction = new Dictionary<string, object>();
jsonAction = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(data);
if (jsonAction == null || jsonAction["action"].GetType() != typeof(string)) return;
string action = jsonAction["action"].ToString();
switch (action)
{
case "close":
{
disconnectCause = jsonAction["cause"].ToString();
disconnectMsg = jsonAction["msg"].ToString();
break;
}
case "serverinfo":
{
wc.WriteStringWebSocket("{\"action\":\"meshes\"}");
wc.WriteStringWebSocket("{\"action\":\"nodes\"}");
wc.WriteStringWebSocket("{\"action\":\"authcookie\"}");
wc.WriteStringWebSocket("{\"action\":\"logincookie\"}");
break;
}
case "authcookie":
{
authCookie = jsonAction["cookie"].ToString();
changeState(2);
break;
}
case "logincookie":
{
loginCookie = jsonAction["cookie"].ToString();
if (onLoginTokenChanged != null) { onLoginTokenChanged(); }
break;
}
case "userinfo":
{
break;
}
case "event":
{
Dictionary<string, object> ev = (Dictionary<string, object>)jsonAction["event"];
string action2 = ev["action"].ToString();
switch (action2)
{
case "changenode":
{
Dictionary<string, object> node = (Dictionary<string, object>)ev["node"];
string nodeid = (string)node["_id"];
if (nodes.ContainsKey(nodeid))
{
NodeClass n = (NodeClass)nodes[nodeid];
n.nodeid = (string)node["_id"];
n.name = (string)node["name"];
if (node.ContainsKey("conn")) { n.conn = (int)node["conn"]; }
n.icon = (int)node["icon"];
nodes[n.nodeid] = n;
if (onNodesChanged != null) onNodesChanged();
}
break;
}
case "nodeconnect":
{
string nodeid = (string)ev["nodeid"];
if (nodes.ContainsKey(nodeid))
{
NodeClass n = (NodeClass)nodes[nodeid];
if (ev.ContainsKey("conn")) { n.conn = (int)ev["conn"]; }
nodes[n.nodeid] = n;
if (onNodesChanged != null) onNodesChanged();
}
break;
}
}
break;
}
case "meshes":
{
meshes = new Dictionary<string, MeshClass>();
ArrayList meshList = (ArrayList)jsonAction["meshes"];
for (int i = 0; i < meshList.Count; i++)
{
Dictionary<string, object> mesh = (Dictionary<string, object>)meshList[i];
MeshClass m = new MeshClass();
m.meshid = (string)mesh["_id"];
m.name = (string)mesh["name"];
m.desc = (string)mesh["desc"];
if (mesh["mtype"].GetType() == typeof(string)) { m.type = int.Parse((string)mesh["mtype"]); }
if (mesh["mtype"].GetType() == typeof(int)) { m.type = (int)mesh["mtype"]; }
meshes[m.meshid] = m;
}
break;
}
case "nodes":
{
nodes = new Dictionary<string, NodeClass>();
Dictionary<string, object> groups = (Dictionary<string, object>)jsonAction["nodes"];
foreach (string meshid in groups.Keys)
{
ArrayList nodesinMesh = (ArrayList)groups[meshid];
for (int i = 0; i < nodesinMesh.Count; i++)
{
Dictionary<string, object> node = (Dictionary<string, object>)nodesinMesh[i];
NodeClass n = new NodeClass();
n.nodeid = (string)node["_id"];
n.name = (string)node["name"];
n.meshid = meshid;
if (node.ContainsKey("conn")) { n.conn = (int)node["conn"]; } else { n.conn = 0; }
n.icon = (int)node["icon"];
nodes[n.nodeid] = n;
}
}
if (onNodesChanged != null) onNodesChanged();
break;
}
default:
{
break;
}
}
}
public delegate void onStateChangedHandler(int state);
public event onStateChangedHandler onStateChanged;
public void changeState(int newState) { if (constate != newState) { constate = newState; if (onStateChanged != null) { onStateChanged(constate); } } }
public delegate void onNodeListChangedHandler();
public event onNodeListChangedHandler onNodesChanged;
public delegate void onLoginTokenChangedHandler();
public event onLoginTokenChangedHandler onLoginTokenChanged;
private class xwebclient : IDisposable
{
private MeshCentralServer parent = null;
private TcpClient wsclient = null;
private SslStream wsstream = null;
private NetworkStream wsrawstream = null;
private int state = 0;
private Uri url = null;
private byte[] readBuffer = new Byte[500];
private int readBufferLen = 0;
private int accopcodes = 0;
private bool accmask = false;
private int acclen = 0;
private bool proxyInUse = false;
private string user = null;
private string pass = null;
private string token = null;
public bool xdebug = false;
public bool xignoreCert = false;
public void Dispose() {
try { wsstream.Close(); } catch (Exception) { }
try { wsstream.Dispose(); } catch (Exception) { }
wsstream = null;
wsclient = null;
state = -1;
parent.changeState(0);
parent.wshash = null;
}
public void Debug(string msg) { if (xdebug) { try { File.AppendAllText("debug.log", "Debug-" + msg + "\r\n"); } catch (Exception) { } } }
public bool Start(MeshCentralServer parent, Uri url, string user, string pass, string token, string fingerprint)
{
if (state != 0) return false;
parent.changeState(1);
state = 1;
this.parent = parent;
this.url = url;
this.user = user;
this.pass = pass;
this.token = token;
Uri proxyUri = null;
// Check if we need to use a HTTP proxy (Auto-proxy way)
try {
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
Object x = registryKey.GetValue("AutoConfigURL", null);
if ((x != null) && (x.GetType() == typeof(string))) {
string proxyStr = GetProxyForUrlUsingPac("http" + ((url.Port == 80) ? "" : "s") + "://" + url.Host + ":" + url.Port, x.ToString());
if (proxyStr != null) { proxyUri = new Uri("http://" + proxyStr); }
}
} catch (Exception) { proxyUri = null; }
// Check if we need to use a HTTP proxy (Normal way)
if (proxyUri == null) {
var proxy = System.Net.HttpWebRequest.GetSystemWebProxy();
proxyUri = proxy.GetProxy(url);
if ((url.Host.ToLower() == proxyUri.Host.ToLower()) && (url.Port == proxyUri.Port)) { proxyUri = null; }
}
if (proxyUri != null)
{
// Proxy in use
proxyInUse = true;
wsclient = new TcpClient();
wsclient.BeginConnect(proxyUri.Host, proxyUri.Port, new AsyncCallback(OnConnectSink), this);
}
else
{
// No proxy in use
proxyInUse = false;
wsclient = new TcpClient();
wsclient.BeginConnect(url.Host, url.Port, new AsyncCallback(OnConnectSink), this);
}
return true;
}
private void OnConnectSink(IAsyncResult ar)
{
if (wsclient == null) return;
// Accept the connection
try
{
wsclient.EndConnect(ar);
} catch (Exception ex) {
Debug("Websocket TCP failed to connect: " + ex.ToString());
Dispose();
return;
}
if (proxyInUse == true)
{
// Send proxy connection request
wsrawstream = wsclient.GetStream();
byte[] proxyRequestBuf = UTF8Encoding.UTF8.GetBytes("CONNECT " + url.Host + ":" + url.Port + " HTTP/1.1\r\nHost: " + url.Host + ":" + url.Port + "\r\n\r\n");
wsrawstream.Write(proxyRequestBuf, 0, proxyRequestBuf.Length);
wsrawstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnProxyResponseSink), this);
}
else
{
// Start TLS connection
Debug("Websocket TCP connected, doing TLS...");
wsstream = new SslStream(wsclient.GetStream(), false, VerifyServerCertificate, null);
wsstream.BeginAuthenticateAsClient(url.Host, null, System.Security.Authentication.SslProtocols.Tls12, false, new AsyncCallback(OnTlsSetupSink), this);
}
}
private void OnProxyResponseSink(IAsyncResult ar)
{
if (wsrawstream == null) return;
int len = 0;
try { len = wsrawstream.EndRead(ar); } catch (Exception) { }
if (len == 0)
{
// Disconnect
Debug("Websocket proxy disconnected, length = 0.");
Dispose();
return;
}
readBufferLen += len;
string proxyResponse = UTF8Encoding.UTF8.GetString(readBuffer, 0, readBufferLen);
if (proxyResponse.IndexOf("\r\n\r\n") >= 0)
{
// We get a full proxy response, we should get something like "HTTP/1.1 200 Connection established\r\n\r\n"
if (proxyResponse.StartsWith("HTTP/1.1 200 "))
{
// All good, start TLS setup.
readBufferLen = 0;
Debug("Websocket TCP connected, doing TLS...");
wsstream = new SslStream(wsrawstream, false, VerifyServerCertificate, null);
wsstream.BeginAuthenticateAsClient(url.Host, null, System.Security.Authentication.SslProtocols.Tls12, false, new AsyncCallback(OnTlsSetupSink), this);
}
else
{
// Invalid response
Debug("Proxy connection failed: " + proxyResponse);
Dispose();
}
} else {
if (readBufferLen == readBuffer.Length)
{
// Buffer overflow
Debug("Proxy connection failed");
Dispose();
}
else
{
// Read more proxy data
wsrawstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnProxyResponseSink), this);
}
}
}
public string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
public string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
private void OnTlsSetupSink(IAsyncResult ar)
{
if (wsstream == null) return;
// Accept the connection
try
{
wsstream.EndAuthenticateAsClient(ar);
}
catch (Exception ex)
{
// Disconnect
MessageBox.Show(ex.Message, "MeshRouter");
Debug("Websocket TLS failed: " + ex.ToString());
Dispose();
return;
}
// Fetch remote certificate
parent.wshash = wsstream.RemoteCertificate.GetCertHashString();
// Setup extra headers if needed
string extraHeaders = "";
if (user != null && pass != null && token != null) { extraHeaders = "x-meshauth: " + Base64Encode(user) + "," + Base64Encode(pass) + "," + Base64Encode(token) + "\r\n"; }
else if (user != null && pass != null) { extraHeaders = "x-meshauth: " + Base64Encode(user) + "," + Base64Encode(pass) + "\r\n"; }
// Send the HTTP headers
Debug("Websocket TLS setup, sending HTTP header...");
string header = "GET " + url.PathAndQuery + " HTTP/1.1\r\nHost: " + url.Host + "\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n" + extraHeaders + "\r\n";
wsstream.Write(UTF8Encoding.UTF8.GetBytes(header));
// Start receiving data
wsstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnTlsDataSink), this);
}
private void OnTlsDataSink(IAsyncResult ar)
{
if (wsstream == null) return;
int len = 0;
try { len = wsstream.EndRead(ar); } catch (Exception) { }
if (len == 0)
{
// Disconnect
Debug("Websocket disconnected, length = 0.");
Dispose();
return;
}
//parent.Debug("#" + counter + ": Websocket got new data: " + len);
readBufferLen += len;
// Consume all of the data
int consumed = 0;
int ptr = 0;
do
{
consumed = ProcessBuffer(readBuffer, ptr, readBufferLen - ptr);
if (consumed < 0) { Dispose(); return; } // Error, close the connection
ptr += consumed;
} while ((consumed > 0) && ((readBufferLen - consumed) > 0));
// Move the data forward
if ((ptr > 0) && (readBufferLen - ptr) > 0) {
//Console.Write("MOVE FORWARD\r\n");
Array.Copy(readBuffer, ptr, readBuffer, 0, (readBufferLen - ptr));
}
readBufferLen = (readBufferLen - ptr);
// If the buffer is too small, double the size here.
if (readBuffer.Length - readBufferLen == 0)
{
Debug("Increasing the read buffer size from " + readBuffer.Length + " to " + (readBuffer.Length * 2) + ".");
byte[] readBuffer2 = new byte[readBuffer.Length * 2];
Array.Copy(readBuffer, 0, readBuffer2, 0, readBuffer.Length);
readBuffer = readBuffer2;
}
// Receive more data
try { wsstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnTlsDataSink), this); } catch (Exception) { }
}
private int ProcessBuffer(byte[] buffer, int offset, int len)
{
string ss = UTF8Encoding.UTF8.GetString(buffer, offset, len);
if (state == 1)
{
// Look for the end of the http header
string header = UTF8Encoding.UTF8.GetString(buffer, offset, len);
int i = header.IndexOf("\r\n\r\n");
if (i == -1) return 0;
Dictionary<string, string> parsedHeader = ParseHttpHeader(header.Substring(0, i));
if ((parsedHeader == null) || (parsedHeader["_Path"] != "101")) { Debug("Websocket bad header."); return -1; } // Bad header, close the connection
Debug("Websocket got setup upgrade header.");
state = 2;
return len; // TODO: Technically we need to return the header length before UTF8 convert.
} else if (state == 2) {
// Parse a websocket fragment header
if (len < 2) return 0;
int headsize = 2;
accopcodes = buffer[offset];
accmask = ((buffer[offset + 1] & 0x80) != 0);
acclen = (buffer[offset + 1] & 0x7F);
if ((accopcodes & 0x0F) == 8)
{
// Close the websocket
Debug("Websocket got closed fragment.");
return -1;
}
if (acclen == 126)
{
if (len < 4) return 0;
headsize = 4;
acclen = (buffer[offset + 2] << 8) + (buffer[offset + 3]);
}
else if (acclen == 127)
{
if (len < 10) return 0;
headsize = 10;
acclen = (buffer[offset + 6] << 24) + (buffer[offset + 7] << 16) + (buffer[offset + 8] << 8) + (buffer[offset + 9]);
Debug("Websocket receive large fragment: " + acclen);
}
if (accmask == true)
{
// TODO: Do unmasking here.
headsize += 4;
}
//parent.Debug("#" + counter + ": Websocket frag header - FIN: " + ((accopcodes & 0x80) != 0) + ", OP: " + (accopcodes & 0x0F) + ", LEN: " + acclen + ", MASK: " + accmask);
state = 3;
return headsize;
}
else if (state == 3)
{
// Parse a websocket fragment data
if (len < acclen) return 0;
//Console.Write("WSREAD: " + acclen + "\r\n");
ProcessWsBuffer(buffer, offset, acclen, accopcodes);
state = 2;
return acclen;
}
return 0;
}
private void ProcessWsBuffer(byte[] data, int offset, int len, int op)
{
Debug("Websocket got data.");
try { parent.processServerData(UTF8Encoding.UTF8.GetString(data, offset, len)); } catch (Exception) { }
}
private Dictionary<string, string> ParseHttpHeader(string header)
{
string[] lines = header.Replace("\r\n", "\r").Split('\r');
if (lines.Length < 2) { return null; }
string[] directive = lines[0].Split(' ');
Dictionary<string, string> values = new Dictionary<string, string>();
values["_Action"] = directive[0];
values["_Path"] = directive[1];
values["_Protocol"] = directive[2];
for (int i = 1; i < lines.Length; i++)
{
var j = lines[i].IndexOf(":");
values[lines[i].Substring(0, j).ToLower()] = lines[i].Substring(j + 1).Trim();
}
return values;
}
private bool VerifyServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (xignoreCert) return true;
if (chain.Build(new X509Certificate2(certificate)) == true) return true;
// Check that the remote certificate is the expected one
if ((parent.okCertHash != null) && (parent.okCertHash == certificate.GetCertHashString())) return true;
parent.disconnectMsg = "cert";
parent.disconnectCert = new X509Certificate2(certificate);
return false;
}
public void WriteStringWebSocket(string data)
{
// Convert the string into a buffer with 4 byte of header space.
int len = UTF8Encoding.UTF8.GetByteCount(data);
byte[] buf = new byte[4 + len];
UTF8Encoding.UTF8.GetBytes(data, 0, data.Length, buf, 4);
len = buf.Length - 4;
// Check that everything is ok
if ((state < 2) || (len < 1) || (len > 65535)) { Dispose(); return; }
//Console.Write("Length: " + len + "\r\n");
//System.Threading.Thread.Sleep(0);
if (len < 126)
{
// Small fragment
buf[2] = 130; // Fragment op code (129 = text, 130 = binary)
buf[3] = (byte)(len & 0x7F);
//try { wsstream.BeginWrite(buf, 2, len + 2, new AsyncCallback(WriteWebSocketAsyncDone), args); } catch (Exception) { Dispose(); return; }
wsstream.Write(buf, 2, len + 2);
}
else
{
// Large fragment
buf[0] = 130; // Fragment op code (129 = text, 130 = binary)
buf[1] = 126;
buf[2] = (byte)((len >> 8) & 0xFF);
buf[3] = (byte)(len & 0xFF);
//try { wsstream.BeginWrite(buf, 0, len + 4, new AsyncCallback(WriteWebSocketAsyncDone), args); } catch (Exception) { Dispose(); return; }
wsstream.Write(buf, 0, len + 4);
}
}
}
}
}

352
MeshDiscovery.cs Normal file
View File

@@ -0,0 +1,352 @@
/*
Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Security;
using System.Security.Cryptography;
using System.Net.Sockets;
using System.Collections;
using System.Net.NetworkInformation;
namespace MeshCentralRouter
{
/// <summary>
/// This class is used to perform mesh node discovery on the local network. It is used to listen of node advertizements and to multicast a "PING" to find mesh
/// nodes on the network. This class works with both IPv4 and IPv6 and must work regardless of the number of network interfaces on this computer.
/// This class also monitors local adapter changes and events them. This is useful to immidiately remove nodes that are not long accessible.
/// </summary>
public sealed class MeshDiscovery
{
private static IPAddress MulticastV4Addr = IPAddress.Parse("239.255.255.235");
private static IPAddress MulticastV6Addr = IPAddress.Parse("FF02:0:0:0:0:0:0:FE");
private static byte[] PingPacket = UTF8Encoding.UTF8.GetBytes("MeshServerScan");
public delegate void NotifyHandler(MeshDiscovery sender, IPEndPoint source, IPEndPoint local, string agentCertHash, string url, string name, string info);
public event NotifyHandler OnNotify;
public delegate void InterfaceChangedHandler(MeshDiscovery sender, bool added, IPAddress localaddress);
public event InterfaceChangedHandler OnInterfaceChanged;
private Hashtable sessions = new Hashtable();
private Hashtable xsessions = new Hashtable();
private ArrayList localinterfaces = new ArrayList();
private IPEndPoint MulticastV4EndPoint;
private IPEndPoint MulticastV6EndPoint;
private UdpClient GeneralSessionV4 = null; // Used for other things like node messages, etc.
private UdpClient GeneralSessionV6 = null; // Used for other things like node messages, etc.
private const int SIO_UDP_CONNRESET = -1744830452;
private byte[] inValue = new byte[] { 0, 0, 0, 0 }; // == false
private byte[] outValue = new byte[] { 0, 0, 0, 0 }; // initialize to 0
public MeshDiscovery()
{
MulticastV4EndPoint = new IPEndPoint(MulticastV4Addr, 16989);
MulticastV6EndPoint = new IPEndPoint(MulticastV6Addr, 16989);
SetupSessions();
NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(AddressChangedSink);
GeneralSessionV4 = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
GeneralSessionV4.Client.IOControl(SIO_UDP_CONNRESET, inValue, outValue);
GeneralSessionV4.BeginReceive(new AsyncCallback(OnReceiveSink), GeneralSessionV4);
try
{
GeneralSessionV6 = new UdpClient(new IPEndPoint(IPAddress.IPv6Any, 0));
GeneralSessionV6.Client.IOControl(SIO_UDP_CONNRESET, inValue, outValue);
GeneralSessionV6.BeginReceive(new AsyncCallback(OnReceiveSink), GeneralSessionV6);
}
catch (SocketException) { GeneralSessionV6 = null; } // This section will fail on Windows XP because it does not support IPv6
}
public void Dispose()
{
NetworkChange.NetworkAddressChanged -= new NetworkAddressChangedEventHandler(AddressChangedSink);
CloseSessions();
GeneralSessionV4.Close();
GeneralSessionV4 = null;
if (GeneralSessionV6 != null)
{
GeneralSessionV6.Close();
GeneralSessionV6 = null;
}
}
/// <summary>
/// Called then the list of local network adapters has changed.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AddressChangedSink(object sender, EventArgs e)
{
//DebugEventViewerForm.LogEvent(this, DebugEventViewerForm.EventType.Warning, "Network interface change detected.");
SetupSessions();
}
/// <summary>
/// Creates all of the UDP client sessions for each local IP address. This method should be called when the list of local network adapters changes on the
/// local computer.
/// </summary>
private void SetupSessions()
{
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
if (adapters == null) CloseSessions();
ArrayList tif = new ArrayList(sessions.Keys);
foreach (NetworkInterface adapter in adapters)
{
// We first filter out the local adapters that are not interesting
if (adapter.SupportsMulticast == false) continue;
if (adapter.OperationalStatus != OperationalStatus.Up) continue;
if (adapter.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;
// Out of each remaining adapter, we look at their IP addresses and create a UDP client for each one.
foreach (System.Net.NetworkInformation.UnicastIPAddressInformation uif in adapter.GetIPProperties().UnicastAddresses)
{
IPAddress addr = uif.Address;
if (addr.AddressFamily == AddressFamily.InterNetwork || addr.ScopeId != 0)
{
tif.Remove(addr);
if (sessions.ContainsKey(addr) == false)
{
// Event this new interface
if (OnInterfaceChanged != null) OnInterfaceChanged(this, true, addr);
// If this local address is IPv4, setup an IPv4 UDP client.
if (addr.AddressFamily == AddressFamily.InterNetwork)
{
UdpClient session = new UdpClient(AddressFamily.InterNetwork);
session.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
session.ExclusiveAddressUse = false;
session.Client.Bind(new IPEndPoint(addr, 0));
session.EnableBroadcast = true;
session.JoinMulticastGroup(MulticastV4Addr, addr);
session.Client.IOControl(SIO_UDP_CONNRESET, inValue, outValue);
session.BeginReceive(new AsyncCallback(OnReceiveSink), session);
sessions[addr] = session;
session = new UdpClient(AddressFamily.InterNetwork);
session.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
session.ExclusiveAddressUse = false;
session.Client.Bind(new IPEndPoint(addr, 16990));
session.EnableBroadcast = true;
session.JoinMulticastGroup(MulticastV4Addr, addr);
session.Client.IOControl(SIO_UDP_CONNRESET, inValue, outValue);
session.BeginReceive(new AsyncCallback(OnReceiveSink), session);
xsessions[addr] = session;
}
// If this local address is IPv6, setup an IPv6 UDP client.
if (addr.AddressFamily == AddressFamily.InterNetworkV6)
{
UdpClient session = new UdpClient(AddressFamily.InterNetworkV6);
session.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
session.ExclusiveAddressUse = false;
session.Client.Bind(new IPEndPoint(addr, 0));
session.EnableBroadcast = true;
session.JoinMulticastGroup((int)addr.ScopeId, MulticastV6Addr);
session.Client.IOControl(SIO_UDP_CONNRESET, inValue, outValue);
session.BeginReceive(new AsyncCallback(OnReceiveSink), session);
sessions[addr] = session;
session = new UdpClient(AddressFamily.InterNetworkV6);
session.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
session.ExclusiveAddressUse = false;
session.Client.Bind(new IPEndPoint(addr, 16990));
session.EnableBroadcast = true;
session.JoinMulticastGroup((int)addr.ScopeId, MulticastV6Addr);
session.Client.IOControl(SIO_UDP_CONNRESET, inValue, outValue);
session.BeginReceive(new AsyncCallback(OnReceiveSink), session);
xsessions[addr] = session;
}
}
}
}
}
// Remove old sessions
if (tif.Count > 0)
{
foreach (IPAddress a in tif)
{
UdpClient c = (UdpClient)sessions[a];
c.Close();
sessions.Remove(a);
if (OnInterfaceChanged != null) OnInterfaceChanged(this, false, a);
}
}
}
/// <summary>
/// Closes all of the UDP client sessions.
/// </summary>
private void CloseSessions()
{
ArrayList l = new ArrayList(sessions.Values);
foreach (UdpClient session in l)
{
IPAddress a = ((IPEndPoint)session.Client.LocalEndPoint).Address;
session.Close();
sessions.Remove(a);
if (OnInterfaceChanged != null) OnInterfaceChanged(this, false, a);
}
sessions.Clear();
l = new ArrayList(xsessions.Values);
foreach (UdpClient session in l)
{
IPAddress a = ((IPEndPoint)session.Client.LocalEndPoint).Address;
session.Close();
sessions.Remove(a);
if (OnInterfaceChanged != null) OnInterfaceChanged(this, false, a);
}
xsessions.Clear();
}
/// <summary>
/// Called by the UDP clients when data is received or when the client is closed.
/// </summary>
/// <param name="result">AsyncResult parameter</param>
private void OnReceiveSink(IAsyncResult result)
{
byte[] buffer;
IPEndPoint ep = null;
UdpClient session = (UdpClient)result.AsyncState;
try
{
buffer = session.EndReceive(result, ref ep);
try
{
// We received some data, decode it
string[] values = UTF8Encoding.UTF8.GetString(buffer).Split('|');
if ((values.Length >= 3) && (values[0] == "MeshCentral2"))
{
Uri url = new Uri(values[2].Replace("%s", ep.Address.ToString()).Replace("wss://", "https://").Replace("ws://", "http://").Replace("/agent.ashx", "/"));
string agentCertHash = values[1];
string serverName = null;
string serverInfo = null;
if (values.Length >= 4) { serverName = values[3]; }
if (values.Length >= 5) { serverInfo = values[4]; }
OnNotify(this, ep, (IPEndPoint)(session.Client.LocalEndPoint), agentCertHash, url.ToString(), serverName, serverInfo);
// Send a targeted scan to this server to get more information
if (values.Length == 3) { session.Send(PingPacket, PingPacket.Length, ep); session.Send(PingPacket, PingPacket.Length, ep); }
}
}
catch (Exception) { }
session.BeginReceive(new AsyncCallback(OnReceiveSink), session);
}
catch (Exception)
{
// If the client is disposed, it will throw another exception.
try
{
if (session != null && session.Client != null)
{
IPAddress a = ((IPEndPoint)session.Client.LocalEndPoint).Address;
sessions.Remove(a);
if (OnInterfaceChanged != null) OnInterfaceChanged(this, false, a);
}
}
catch (Exception) { }
}
}
/*
internal void SendBlockRequest(TargetTrak tt, string[] requests)
{
// PB_SYNCREQUEST
MemoryStream mem = new MemoryStream();
mem.Write(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)12)), 0, 2); // Write PB_SYNCREQUEST
mem.Write(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)(4 + (32 * requests.Length)))), 0, 2); // Write length of header + (32 * requests)
foreach (string s in requests)
{
byte[] buf = MeshUtils.HexToBytes(s);
mem.Write(buf, 0, buf.Length);
}
byte[] packet = MeshDiscovery.util_cipher(tt.UdpSessionKey, 0, MeshUtils.HexToBytes(tt.Node.NodeIdHex), mem.ToArray(), true, tt.ConsoleId);
GeneralUnicast(packet, new IPEndPoint(tt.Target, 16990));
}
*/
/// <summary>
/// This method sends out a multicast "PING" on all local adapters in both IPv4 and IPv6.
/// </summary>
public void MulticastPing()
{
//DebugEventViewerForm.LogEvent(this, DebugEventViewerForm.EventType.Information, "Performing full multicast ping.");
foreach (UdpClient session in sessions.Values) MulticastPing(session);
}
/// <summary>
/// Performs a multicast ping on a single UDP session.
/// </summary>
/// <param name="session">The UDP client on which to perform the multicast</param>
private void MulticastPing(UdpClient session)
{
try
{
IPAddress address = ((IPEndPoint)session.Client.LocalEndPoint).Address;
if (session.Client.AddressFamily == AddressFamily.InterNetwork)
{
session.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, address.GetAddressBytes());
session.Send(PingPacket, PingPacket.Length, MulticastV4EndPoint);
}
else if (session.Client.AddressFamily == AddressFamily.InterNetworkV6 && address.ScopeId != 0)
{
session.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastInterface, BitConverter.GetBytes((int)address.ScopeId));
session.Send(PingPacket, PingPacket.Length, MulticastV6EndPoint);
}
}
catch (SocketException) { }
}
/// <summary>
/// This method is used to send out unicast UDP packets.
/// </summary>
/// <param name="buffer">The buffer to send out as unicast</param>
/// <param name="local">The local IP address to use</param>
/// <param name="remote">The remote IP address that this packet will be sent to</param>
public void UnicastData(byte[] buffer, IPAddress local, IPEndPoint remote)
{
UdpClient session = (UdpClient)sessions[local];
if (session == null) return;
try
{
session.Send(buffer, buffer.Length, remote);
}
catch (SocketException) { }
}
public void GeneralUnicast(byte[] buffer, IPEndPoint remote)
{
try
{
if (remote.AddressFamily == AddressFamily.InterNetwork && GeneralSessionV4 != null) GeneralSessionV4.Send(buffer, buffer.Length, remote);
if (remote.AddressFamily == AddressFamily.InterNetworkV6 && GeneralSessionV6 != null) GeneralSessionV6.Send(buffer, buffer.Length, remote);
}
catch (SocketException) { }
}
}
}

BIN
MeshIcon50.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
MeshIcon50T.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

717
MeshMapper.cs Normal file
View File

@@ -0,0 +1,717 @@
using System;
using System.IO;
using System.Net;
using System.Web;
using System.Text;
using System.Net.Sockets;
using System.Net.Security;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Deployment.Application;
using System.Collections.Specialized;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32;
namespace MeshCentralRouter
{
public class MeshMapper
{
public int state = 0;
Uri wsurl = null;
public int protocol = 1; // 1 = TCP, 2 = UDP
public int localport = 0;
public int remoteport = 0;
public string remoteip = null;
public string certhash = null;
public int connectCounter = 0;
public int totalConnectCounter = 0;
public bool exit = false;
public bool xdebug = false;
public bool inaddrany = false;
TcpListener listener = null;
public delegate void onStateMsgChangedHandler(string statemsg);
public event onStateMsgChangedHandler onStateMsgChanged;
public static string GetProxyForUrlUsingPac(string DestinationUrl, string PacUri)
{
IntPtr WinHttpSession = Win32Api.WinHttpOpen("User", Win32Api.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, IntPtr.Zero, IntPtr.Zero, 0);
Win32Api.WINHTTP_AUTOPROXY_OPTIONS ProxyOptions = new Win32Api.WINHTTP_AUTOPROXY_OPTIONS();
Win32Api.WINHTTP_PROXY_INFO ProxyInfo = new Win32Api.WINHTTP_PROXY_INFO();
ProxyOptions.dwFlags = Win32Api.WINHTTP_AUTOPROXY_CONFIG_URL;
ProxyOptions.dwAutoDetectFlags = (Win32Api.WINHTTP_AUTO_DETECT_TYPE_DHCP | Win32Api.WINHTTP_AUTO_DETECT_TYPE_DNS_A);
ProxyOptions.lpszAutoConfigUrl = PacUri;
// Get Proxy
bool IsSuccess = Win32Api.WinHttpGetProxyForUrl(WinHttpSession, DestinationUrl, ref ProxyOptions, ref ProxyInfo);
Win32Api.WinHttpCloseHandle(WinHttpSession);
if (IsSuccess)
{
return ProxyInfo.lpszProxy;
}
else
{
Console.WriteLine("Error: {0}", Win32Api.GetLastError());
return null;
}
}
// Starts the routing server, called when the start button is pressed
public void start(int protocol, int localPort, string url, int remotePort, string remoteIP)
{
this.protocol = protocol;
this.remoteport = remotePort;
this.remoteip = remoteIP;
wsurl = new Uri(url);
//wshash = serverHashTextBox.Text;
if (protocol == 1)
{
// Start the TCP listener
try
{
if (listener != null) return;
listener = new TcpListener(inaddrany ? IPAddress.Any : IPAddress.Loopback, localPort);
try { listener.Start(); } catch (Exception) { listener = null; }
if (listener != null)
{
listener.BeginAcceptTcpClient(new AsyncCallback(AcceptTcpClientSink), null);
localport = ((IPEndPoint)listener.LocalEndpoint).Port;
state = 1;
UpdateInfo();
}
else
{
state = -1;
UpdateInfo();
}
}
catch (Exception ex) {
Debug(ex.ToString());
stop();
}
} else if (protocol == 2) {
// Start websocket connection
try
{
IPEndPoint udpEndPoint = new IPEndPoint(inaddrany ? IPAddress.Any : IPAddress.Loopback, localPort);
UdpClient client = new UdpClient(udpEndPoint);
localport = ((IPEndPoint)client.Client.LocalEndPoint).Port;
state = 1;
UpdateInfo();
ConnectWS(client, ++connectCounter);
}
catch (Exception ex) {
Debug(ex.ToString());
stop();
}
}
}
public void Debug(string msg) { if (xdebug) { try { File.AppendAllText("debug.log", "Debug-MeshMapper-" + msg + "\r\n"); } catch (Exception) { } } }
private void UpdateInfo() {
string msg = "";
if (state == -1) { msg = "Unable to bind to local port"; }
else if (state == 0) { msg = "Stopped"; }
else if (state == 1) {
if (remoteip == null)
{
msg = "Port " + localport + " to port " + remoteport;
} else {
msg = "Port " + localport + " to " + remoteip + ":" + remoteport;
}
if (totalConnectCounter == 1) { msg += ", 1 connection."; }
if (totalConnectCounter > 1) { msg += ", " + totalConnectCounter + " connections."; }
}
if (onStateMsgChanged != null) { onStateMsgChanged(msg); }
}
public void stop()
{
Debug("stopButton_Click()");
exit = true;
if (listener != null)
{
listener.Stop();
listener = null;
}
localport = 0;
state = 0;
UpdateInfo();
}
private void ShutdownClients(TcpClient c1, UdpClient c2, xwebclient c3, int counter)
{
Debug("#" + counter + ": ShutdownWebClients()");
if (c1 != null)
{
try
{
if (c1.Client.Connected)
{
try { c1.Client.Disconnect(false); } catch (Exception) { }
try { c1.Client.Close(); } catch (Exception) { }
try { c1.Close(); } catch (Exception) { }
}
}
catch (Exception) { }
}
if (c2 != null)
{
try { c2.Close(); } catch (Exception) { }
}
try { c3.Dispose(); } catch (Exception) { }
}
private void AcceptTcpClientSink(IAsyncResult ar)
{
TcpClient client = null;
try
{
client = listener.EndAcceptTcpClient(ar);
}
catch (Exception) { exit = true; }
if (client != null)
{
// Connect using websocket
ConnectWS(client, ++connectCounter);
}
try
{
listener.BeginAcceptTcpClient(new AsyncCallback(AcceptTcpClientSink), null);
}
catch (Exception) { exit = true; }
}
private void ConnectWS(TcpClient client, int counter)
{
xwebclient wc = new xwebclient();
Debug("#" + counter + ": Connecting web socket to: " + wsurl.ToString());
wc.Start(this, wsurl, certhash, client, counter);
}
private void ConnectWS(UdpClient client, int counter)
{
xwebclient wc = new xwebclient();
Debug("#" + counter + ": Connecting web socket to: " + wsurl.ToString());
wc.Start(this, wsurl, certhash, client, counter);
}
private class xwebclient : IDisposable
{
private TcpClient client = null;
private UdpClient uclient = null;
private NetworkStream stream = null;
private TcpClient wsclient = null;
private SslStream wsstream = null;
private NetworkStream wsrawstream = null;
private int state = 0;
private Uri url = null;
private byte[] readBuffer = new Byte[65000];
private int readBufferLen = 0;
private int accopcodes = 0;
private bool accmask = false;
private int acclen = 0;
private bool tunneling = false;
private MeshMapper parent = null;
private bool proxyInUse = false;
public int counter = 0;
private string certhash;
private IPEndPoint uendpoint = null;
public void Dispose()
{
if (state == 0) return;
state = 0;
try { wsstream.Close(); } catch (Exception) { }
try { wsstream.Dispose(); } catch (Exception) { }
try { client.Close(); } catch (Exception) { }
try { stream.Close(); } catch (Exception) { }
stream = null;
client = null;
wsstream = null;
wsclient = null;
--parent.totalConnectCounter;
parent.UpdateInfo();
}
public bool Start(MeshMapper parent, Uri url, string certhash, TcpClient client, int counter)
{
this.client = client;
return StartEx(parent, url, certhash, counter);
}
public bool Start(MeshMapper parent, Uri url, string certhash, UdpClient client, int counter)
{
this.uclient = client;
return StartEx(parent, url, certhash, counter);
}
public bool StartEx(MeshMapper parent, Uri url, string certhash, int counter)
{
if (state != 0) return false;
state = 1;
this.parent = parent;
this.url = url;
this.counter = counter;
this.certhash = certhash;
if (client != null) { this.stream = client.GetStream(); }
Uri proxyUri = null;
++parent.totalConnectCounter;
parent.UpdateInfo();
// Check if we need to use a HTTP proxy (Auto-proxy way)
try
{
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
Object x = registryKey.GetValue("AutoConfigURL", null);
if ((x != null) && (x.GetType() == typeof(string)))
{
string proxyStr = GetProxyForUrlUsingPac("http" + ((url.Port == 80) ? "" : "s") + "://" + url.Host + ":" + url.Port, x.ToString());
if (proxyStr != null) { proxyUri = new Uri("http://" + proxyStr); }
}
}
catch (Exception) { proxyUri = null; }
// Check if we need to use a HTTP proxy (Normal way)
if (proxyUri == null)
{
var proxy = System.Net.HttpWebRequest.GetSystemWebProxy();
proxyUri = proxy.GetProxy(url);
if ((url.Host.ToLower() == proxyUri.Host.ToLower()) && (url.Port == proxyUri.Port)) { proxyUri = null; }
}
if (proxyUri != null)
{
// Proxy in use
proxyInUse = true;
wsclient = new TcpClient();
wsclient.BeginConnect(proxyUri.Host, proxyUri.Port, new AsyncCallback(OnConnectSink), this);
}
else
{
// No proxy in use
proxyInUse = false;
wsclient = new TcpClient();
wsclient.BeginConnect(url.Host, url.Port, new AsyncCallback(OnConnectSink), this);
}
return true;
}
private void OnConnectSink(IAsyncResult ar)
{
if (wsclient == null) return;
// Accept the connection
try
{
wsclient.EndConnect(ar);
}
catch (Exception ex)
{
parent.Debug("#" + counter + ": Websocket TCP failed to connect: " + ex.ToString());
parent.ShutdownClients(client, uclient, this, this.counter);
return;
}
if (proxyInUse == true)
{
// Send proxy connection request
wsrawstream = wsclient.GetStream();
byte[] proxyRequestBuf = UTF8Encoding.UTF8.GetBytes("CONNECT " + url.Host + ":" + url.Port + " HTTP/1.1\r\nHost: " + url.Host + ":" + url.Port + "\r\n\r\n");
wsrawstream.Write(proxyRequestBuf, 0, proxyRequestBuf.Length);
wsrawstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnProxyResponseSink), this);
}
else
{
// Start TLS connection
parent.Debug("#" + counter + ": Websocket TCP connected, doing TLS...");
wsstream = new SslStream(wsclient.GetStream(), false, VerifyServerCertificate, null);
wsstream.BeginAuthenticateAsClient(url.Host, null, System.Security.Authentication.SslProtocols.Tls12, false, new AsyncCallback(OnTlsSetupSink), this);
}
}
private void OnProxyResponseSink(IAsyncResult ar)
{
if (wsrawstream == null) return;
int len = 0;
try { len = wsrawstream.EndRead(ar); } catch (Exception) { }
if (len == 0)
{
// Disconnect
parent.Debug("#" + counter + ": Websocket proxy disconnected, length = 0.");
parent.ShutdownClients(client, uclient, this, this.counter);
return;
}
readBufferLen += len;
string proxyResponse = UTF8Encoding.UTF8.GetString(readBuffer, 0, readBufferLen);
if (proxyResponse.IndexOf("\r\n\r\n") >= 0)
{
// We get a full proxy response, we should get something like "HTTP/1.1 200 Connection established\r\n\r\n"
if (proxyResponse.StartsWith("HTTP/1.1 200 "))
{
// All good, start TLS setup.
readBufferLen = 0;
parent.Debug("#" + counter + ": Websocket TCP connected, doing TLS...");
wsstream = new SslStream(wsrawstream, false, VerifyServerCertificate, null);
wsstream.BeginAuthenticateAsClient(url.Host, null, System.Security.Authentication.SslProtocols.Tls12, false, new AsyncCallback(OnTlsSetupSink), this);
}
else
{
// Invalid response
parent.Debug("#" + counter + ": Proxy connection failed: " + proxyResponse);
parent.ShutdownClients(client, uclient, this, this.counter);
}
}
else
{
if (readBufferLen == readBuffer.Length)
{
// Buffer overflow
parent.Debug("#" + counter + ": Proxy connection failed");
parent.ShutdownClients(client, uclient, this, this.counter);
}
else
{
// Read more proxy data
wsrawstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnProxyResponseSink), this);
}
}
}
private void OnTlsSetupSink(IAsyncResult ar)
{
if (wsstream == null) return;
// Accept the connection
try
{
wsstream.EndAuthenticateAsClient(ar);
}
catch (Exception ex)
{
// Disconnect
MessageBox.Show(ex.Message, "MeshRouter");
parent.Debug("#" + counter + ": Websocket TLS failed: " + ex.ToString());
parent.ShutdownClients(client, uclient, this, this.counter);
return;
}
// Send the HTTP header
parent.Debug("#" + counter + ": Websocket TLS setup, sending HTTP header...");
string header = "GET " + url.PathAndQuery + " HTTP/1.1\r\nHost: " + url.Host + "\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n";
wsstream.Write(UTF8Encoding.UTF8.GetBytes(header));
// Start receiving data
wsstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnTlsDataSink), this);
}
private void OnTlsDataSink(IAsyncResult ar)
{
if (wsstream == null) return;
int len = 0;
try { len = wsstream.EndRead(ar); } catch (Exception) { }
if (len == 0)
{
// Disconnect
parent.Debug("#" + counter + ": Websocket disconnected, length = 0.");
parent.ShutdownClients(client, uclient, this, this.counter);
return;
}
//parent.Debug("#" + counter + ": Websocket got new data: " + len);
readBufferLen += len;
// Consume all of the data
int consumed = 0;
int ptr = 0;
do
{
consumed = ProcessBuffer(readBuffer, ptr, readBufferLen - ptr);
if (consumed < 0) { parent.ShutdownClients(client, uclient, this, this.counter); return; } // Error, close the connection
ptr += consumed;
} while ((consumed > 0) && ((readBufferLen - consumed) > 0));
// Move the data forward
if ((ptr > 0) && (readBufferLen - ptr) > 0)
{
//Console.Write("MOVE FORWARD\r\n");
Array.Copy(readBuffer, ptr, readBuffer, 0, (readBufferLen - ptr));
}
readBufferLen = (readBufferLen - ptr);
// Receive more data
try { wsstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnTlsDataSink), this); } catch (Exception) { }
}
private int ProcessBuffer(byte[] buffer, int offset, int len)
{
string ss = UTF8Encoding.UTF8.GetString(buffer, offset, len);
if (state == 1)
{
// Look for the end of the http header
string header = UTF8Encoding.UTF8.GetString(buffer, offset, len);
int i = header.IndexOf("\r\n\r\n");
if (i == -1) return 0;
Dictionary<string, string> parsedHeader = ParseHttpHeader(header.Substring(0, i));
if ((parsedHeader == null) || (parsedHeader["_Path"] != "101")) { parent.Debug("#" + counter + ": Websocket bad header."); return -1; } // Bad header, close the connection
parent.Debug("#" + counter + ": Websocket got setup upgrade header.");
state = 2;
return len; // TODO: Technically we need to return the header length before UTF8 convert.
}
else if (state == 2)
{
// Parse a websocket fragment header
if (len < 2) return 0;
int headsize = 2;
accopcodes = buffer[offset];
accmask = ((buffer[offset + 1] & 0x80) != 0);
acclen = (buffer[offset + 1] & 0x7F);
if ((accopcodes & 0x0F) == 8)
{
// Close the websocket
parent.Debug("#" + counter + ": Websocket got closed fragment.");
return -1;
}
if (acclen == 126)
{
if (len < 4) return 0;
headsize = 4;
acclen = (buffer[offset + 2] << 8) + (buffer[offset + 3]);
}
else if (acclen == 127)
{
if (len < 10) return 0;
headsize = 10;
acclen = (buffer[offset + 6] << 24) + (buffer[offset + 7] << 16) + (buffer[offset + 8] << 8) + (buffer[offset + 9]);
parent.Debug("#" + counter + ": Websocket receive large fragment: " + acclen);
}
if (accmask == true)
{
// TODO: Do unmasking here.
headsize += 4;
}
//parent.Debug("#" + counter + ": Websocket frag header - FIN: " + ((accopcodes & 0x80) != 0) + ", OP: " + (accopcodes & 0x0F) + ", LEN: " + acclen + ", MASK: " + accmask);
state = 3;
return headsize;
}
else if (state == 3)
{
// Parse a websocket fragment data
if (len < acclen) return 0;
//Console.Write("WSREAD: " + acclen + "\r\n");
ProcessWsBuffer(buffer, offset, acclen, accopcodes);
state = 2;
return acclen;
}
return 0;
}
private void ProcessWsBuffer(byte[] data, int offset, int len, int op)
{
//parent.Debug("#" + counter + ": Websocket frag data: " + acclen);
if ((tunneling == false) && (data[offset] == 'c'))
{
parent.Debug("#" + counter + ": Websocket get server 'c' confirmation.");
// Server confirmed connection, start reading the TCP stream
//Console.Write("WS-Relay Connect\r\n");
if (client != null)
{
byte[] buf1 = new byte[65000];
try { client.GetStream().BeginRead(buf1, 4, buf1.Length - 4, new AsyncCallback(ClientEndReadWS), new object[] { this, client, buf1, counter }); } catch (Exception) { }
tunneling = true;
}
else if (uclient != null)
{
try { uclient.BeginReceive(new AsyncCallback(UClientEndReadWS), new object[] { this, uclient, counter }); } catch (Exception) { }
tunneling = true;
}
}
else
{
if (client != null)
{
// Write: WS --> TCP
// TODO: Async write?
if (stream != null) { try { stream.Write(data, offset, len); } catch (Exception) { } }
}
else if (uclient != null)
{
// Write: WS --> UDP
if (uendpoint != null) {
if (offset == 0) {
try { uclient.Send(data, len, uendpoint); } catch (Exception) { }
} else {
byte[] data2 = new byte[len];
Array.Copy(data, offset, data2, 0, len);
try { uclient.Send(data2, len, uendpoint); } catch (Exception) { }
}
}
}
}
}
private Dictionary<string, string> ParseHttpHeader(string header)
{
string[] lines = header.Replace("\r\n", "\r").Split('\r');
if (lines.Length < 2) { return null; }
string[] directive = lines[0].Split(' ');
Dictionary<string, string> values = new Dictionary<string, string>();
values["_Action"] = directive[0];
values["_Path"] = directive[1];
values["_Protocol"] = directive[2];
for (int i = 1; i < lines.Length; i++)
{
var j = lines[i].IndexOf(":");
values[lines[i].Substring(0, j).ToLower()] = lines[i].Substring(j + 1).Trim();
}
return values;
}
private bool VerifyServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
// Check that the remote certificate is the expected one
return (certificate.GetCertHashString() == certhash);
}
public void WriteWebSocketAsync(byte[] buf, int offset, int len, object[] args)
{
// Fetch the state
xwebclient wc = (xwebclient)args[0];
// Check that everything is ok
if ((state < 2) || (len < 1) || (len > 65535)) { parent.ShutdownClients(client, uclient, wc, counter); return; }
//Console.Write("Length: " + len + "\r\n");
//System.Threading.Thread.Sleep(0);
if (len < 126)
{
// Small fragment
buf[2] = 130; // Fragment op code (129 = text, 130 = binary)
buf[3] = (byte)(len & 0x7F);
try { wsstream.BeginWrite(buf, 2, len + 2, new AsyncCallback(WriteWebSocketAsyncDone), args); } catch (Exception ex) {
parent.ShutdownClients(client, uclient, wc, counter); return; }
}
else
{
// Large fragment
buf[0] = 130; // Fragment op code (129 = text, 130 = binary)
buf[1] = 126;
buf[2] = (byte)((len >> 8) & 0xFF);
buf[3] = (byte)(len & 0xFF);
try { wsstream.BeginWrite(buf, 0, len + 4, new AsyncCallback(WriteWebSocketAsyncDone), args); } catch (Exception) { parent.ShutdownClients(client, uclient, wc, counter); return; }
}
}
private void WriteWebSocketAsyncDone(IAsyncResult ar)
{
// Fetch the state
object[] args = (object[])ar.AsyncState;
xwebclient wc = (xwebclient)args[0];
object oclient;
TcpClient client = null;
UdpClient uclient = null;
byte[] buf = null;
int counter;
if (args.Length == 4) {
oclient = client = (TcpClient)args[1];
buf = (byte[])args[2];
counter = (int)args[3];
} else {
oclient = uclient = (UdpClient)args[1];
counter = (int)args[2];
}
try { wsstream.EndWrite(ar); } catch (Exception) { parent.ShutdownClients(client, uclient, wc, counter); return; }
if (client != null) {
// Receive more TCP data
try { client.GetStream().BeginRead(buf, 4, buf.Length - 4, new AsyncCallback(ClientEndReadWS), args); } catch (Exception) { parent.ShutdownClients(client, uclient, wc, counter); return; }
} else if (uclient != null) {
// Receive more UDP data
try { uclient.BeginReceive(new AsyncCallback(UClientEndReadWS), args); } catch (Exception) { parent.ShutdownClients(client, uclient, wc, counter); return; }
}
}
// Read from the local client
private void ClientEndReadWS(IAsyncResult ar)
{
// Fetch the state
object[] args = (object[])ar.AsyncState;
xwebclient wc = (xwebclient)args[0];
TcpClient client = (TcpClient)args[1];
byte[] buf = (byte[])args[2];
int counter = (int)args[3];
int len = 0;
try
{
// Read the data
if (client != null && client.Connected == true) { len = client.GetStream().EndRead(ar); }
}
catch (Exception) { parent.ShutdownClients(client, uclient, wc, counter); return; }
//Debug("#" + counter + ": ClientEndRead(" + len + ") - Local Read");
if (len > 0)
{
// Forward the data & read again
try
{
wc.WriteWebSocketAsync(buf, 4, len, args);
}
catch (Exception)
{
parent.ShutdownClients(client, uclient, wc, counter);
return;
}
}
else
{
parent.ShutdownClients(client, uclient, wc, counter);
return;
}
}
private void UClientEndReadWS(IAsyncResult ar)
{
// Fetch the state
object[] args = (object[])ar.AsyncState;
xwebclient wc = (xwebclient)args[0];
UdpClient uclient = (UdpClient)args[1];
int counter = (int)args[2];
byte[] buf = null;
try
{
// Read the data
if (uclient != null) { buf = uclient.EndReceive(ar, ref uendpoint); }
}
catch (Exception) { parent.ShutdownClients(client, uclient, wc, counter); return; }
byte[] buf2 = new byte[4 + buf.Length];
Array.Copy(buf, 0, buf2, 4, buf.Length);
if (buf != null) { wc.WriteWebSocketAsync(buf2, 4, buf.Length, args); }
}
}
}
}

BIN
MeshServer.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
MeshServerLogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

399
MeshUtils.cs Normal file
View File

@@ -0,0 +1,399 @@
/*
Copyright 2009-2017 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Collections;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Security.Cryptography;
namespace MeshMiniRouterTool
{
class MeshUtils
{
public static RNGCryptoServiceProvider CryptoRandom = new RNGCryptoServiceProvider();
public static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
if (a1 == null && a2 == null) return true;
if (a1 != null && a2 == null) return false;
if (a1 == null && a2 != null) return false;
if (a1.Length != a2.Length) return false;
for (int i = 0; i < a1.Length; i++) if (a1[i] != a2[i]) return false;
return true;
}
private static char[] hexlookup = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
public static string BytesToHex(byte[] data)
{
if (data == null) return "";
int i = 0, p = 0, l = data.Length;
char[] c = new char[l * 2];
byte d;
while (i < l)
{
d = data[i++];
c[p++] = hexlookup[d / 0x10];
c[p++] = hexlookup[d % 0x10];
}
return new string(c, 0, c.Length);
}
public static string BytesToHex(byte[] data, int spacing)
{
int i = 0, p = 0, l = data.Length;
char[] c = new char[(l * 2) + (l / spacing)];
byte d;
while (i < l)
{
d = data[i++];
c[p++] = hexlookup[d / 0x10];
c[p++] = hexlookup[d % 0x10];
if ((i % spacing) == 0) c[p++] = ' ';
}
return new string(c, 0, c.Length);
}
public static byte[] HexToBytes(string hex)
{
if (hex == null) return null;
hex = hex.ToUpper();
bool firstbyte = true;
byte v = 0;
ArrayList output = new ArrayList();
foreach (char c in hex)
{
if (c >= '0' && c <= '9') v += (byte)(c - '0');
else if (c >= 'A' && c <= 'F') v += (byte)((c - 'A') + 10);
else continue;
if (firstbyte)
{
v = (byte)(v * 16);
firstbyte = false;
}
else
{
output.Add(v);
v = 0;
firstbyte = true;
}
}
return (byte[])output.ToArray(typeof(byte));
}
public class HttpRoutingCookie
{
public byte version;
public string username;
public byte[] nodeid;
public IPAddress address;
public ushort port;
public bool tls;
public bool oob;
public string hostname;
public long ticks;
public HttpRoutingCookie() { version = 1; }
public override string ToString() { return string.Format("{0}:{1}:{2}:{3}", version, username, hostname, port.ToString()); }
public string ToLongString()
{
DateTime t1 = new DateTime(ticks);
DateTime t2 = DateTime.UtcNow;
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Version: {0}\r\n", version);
sb.AppendFormat("Username: {0}\r\n", username);
sb.AppendFormat("NodeId: {0}\r\n", MeshUtils.BytesToHex(nodeid));
if (address != null) sb.AppendFormat("Address: {0}\r\n", address.ToString()); else sb.AppendFormat("Address: NULL\r\n");
sb.AppendFormat("Port: {0}\r\n", port);
sb.AppendFormat("TLS: {0}\r\n", tls);
sb.AppendFormat("OOB: {0}\r\n", oob);
sb.AppendFormat("Hostname: {0}\r\n", hostname);
sb.AppendFormat("Time: {0}\r\n", t1.ToString());
sb.AppendFormat("Now: {0}\r\n", t2.ToString());
return sb.ToString();
}
}
public static string EncodeHttpRoutingCookie(byte[] key, HttpRoutingCookie cookie)
{
if (key == null || key.Length != 50 || cookie.username == null || cookie.nodeid == null || cookie.nodeid.Length != 32 || cookie.hostname == null) return null;
byte[] user = UTF8Encoding.UTF8.GetBytes(cookie.username);
byte[] host = UTF8Encoding.UTF8.GetBytes(cookie.hostname);
if (user.Length > 250 || host.Length > 250) return null;
byte[] ticks = BitConverter.GetBytes(DateTime.UtcNow.Ticks);
byte flags = 0;
if (cookie.tls) flags += 1;
if (cookie.oob) flags += 2;
BinaryWriter bw = MeshUtils.GetBinaryWriter();
if (cookie.version == 1) // Automatic routing cookie
{
bw.Write((byte)1); // Cookie version
bw.Write(cookie.nodeid, 0, 32); // Target nodeid
bw.Write(IPAddress.HostToNetworkOrder((short)(cookie.port))); // Target port
bw.Write(flags); // Flags (Use TLS/OOB)
bw.Write(ticks, 0, 8); // Current time
bw.Write((byte)user.Length); // Username length
bw.Write(user, 0, user.Length); // Username
bw.Write((byte)host.Length); // Hostname length
bw.Write(host, 0, host.Length); // Hostname
}
else if (cookie.version == 2 && cookie.address != null && cookie.address.AddressFamily == AddressFamily.InterNetwork) // IPv4 Direct routing cookie
{
bw.Write((byte)2); // Cookie version
bw.Write(cookie.nodeid, 0, 32); // Relay nodeid
bw.Write(cookie.address.GetAddressBytes(), 0, 4); // Target IPv4 address
bw.Write(IPAddress.HostToNetworkOrder((short)(cookie.port))); // Target port
bw.Write(flags); // Flags (Use TLS/OOB)
bw.Write(ticks, 0, 8); // Current time
bw.Write((byte)user.Length); // Username length
bw.Write(user, 0, user.Length); // Username
bw.Write((byte)host.Length); // Hostname length
bw.Write(host, 0, host.Length); // Hostname
}
string r = EncodeHttpRoutingCookieEx(key, ((MemoryStream)bw.BaseStream).ToArray());
MeshUtils.RecycleBinaryWriter(bw);
return r;
}
public static HttpRoutingCookie DecodeHttpRoutingCookie(byte[] key, string msg)
{
byte[] data = DecodeHttpRoutingCookieEx(key, msg);
if (data == null) return null;
HttpRoutingCookie cookie = new HttpRoutingCookie();
try
{
if (data[0] == 1) // Automatic routing cookie
{
cookie.version = 1;
cookie.nodeid = new byte[32];
Array.Copy(data, 1, cookie.nodeid, 0, 32); // Target nodeid
cookie.port = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(data, 33)); // Target port
cookie.tls = ((data[35] & 0x01) != 0); // Use TLS
cookie.oob = ((data[35] & 0x02) != 0); // Use OOB
cookie.ticks = BitConverter.ToInt64(data, 36); // Time Ticks
byte[] user = new byte[data[44]]; // Username length
Array.Copy(data, 45, user, 0, user.Length); // Username
cookie.username = UTF8Encoding.UTF8.GetString(user);
byte[] host = new byte[data[45 + user.Length]]; // Hostname length
Array.Copy(data, 46 + user.Length, host, 0, host.Length); // Hostname
cookie.hostname = UTF8Encoding.UTF8.GetString(host);
}
else if (data[0] == 2) // IPv4 Direct routing cookie
{
cookie.version = 2;
cookie.nodeid = new byte[32];
Array.Copy(data, 1, cookie.nodeid, 0, 32); // Relay nodeid
byte[] addr = new byte[4];
Array.Copy(data, 33, addr, 0, 4); // Target address
cookie.address = new IPAddress(addr);
cookie.port = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(data, 37)); // Target port
cookie.tls = ((data[39] & 0x01) != 0); // Use TLS
cookie.oob = ((data[39] & 0x02) != 0); // Use OOB
cookie.ticks = BitConverter.ToInt64(data, 40); // Time Ticks
byte[] user = new byte[data[48]]; // Username length
Array.Copy(data, 49, user, 0, user.Length); // Username
cookie.username = UTF8Encoding.UTF8.GetString(user);
byte[] host = new byte[data[49 + user.Length]]; // Hostname length
Array.Copy(data, 50 + user.Length, host, 0, host.Length); // Hostname
cookie.hostname = UTF8Encoding.UTF8.GetString(host);
}
// Check clock
DateTime t1 = new DateTime(cookie.ticks);
DateTime t2 = DateTime.UtcNow;
if (t1 > t2.AddMinutes(3) || t1.AddMinutes(60) < t2) return null;
}
catch (Exception) { return null; }
return cookie;
}
private static string EncodeHttpRoutingCookieEx(byte[] key, byte[] msg)
{
if (key == null || key.Length != 50 || msg == null) return null;
MemoryStream mem2 = MeshUtils.GetMemoryStream();
// Split the key
//ushort KeyId = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(key, 0));
byte[] key1 = new byte[32]; // HMAC
byte[] key2 = new byte[16]; // AES
Array.Copy(key, 2, key1, 0, 32);
Array.Copy(key, 34, key2, 0, 16);
// Select an IV
byte[] iv = new byte[16];
CryptoRandom.GetBytes(iv);
// Setup and perform HMAC-SHA256
using (HMACSHA256 hmac = new HMACSHA256(key1))
{
byte[] hmacresult = hmac.ComputeHash(msg);
mem2.Write(hmacresult, 0, hmacresult.Length);
mem2.Write(msg, 0, msg.Length);
msg = mem2.ToArray();
mem2.SetLength(0);
}
// Setup AES128-CBC
byte[] buf;
using (Rijndael rij = new RijndaelManaged())
{
rij.KeySize = 128;
rij.Mode = CipherMode.CBC;
rij.Padding = PaddingMode.PKCS7;
rij.Key = key2;
rij.IV = iv;
// Perform AES128 encrypt
using (MemoryStream mem = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(mem, rij.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(msg, 0, msg.Length);
cs.FlushFinalBlock();
buf = mem.ToArray();
}
}
}
// Perform formatting
mem2.Write(key, 0, 2); // Write the key identifier
mem2.Write(iv, 0, 16);
mem2.Write(buf, 0, buf.Length);
string r = "MRC" + UrlEscapeBase64(Convert.ToBase64String(mem2.ToArray()));
MeshUtils.RecycleMemoryStream(mem2);
return r;
}
private static byte[] DecodeHttpRoutingCookieEx(byte[] key, string msg)
{
byte[] resulting_msg = null;
try
{
if (key == null || key.Length != 50 || msg == null || msg.Length < 5 || msg.StartsWith("MRC") == false) return null;
msg = UrlUnEscapeBase64(msg);
// Split the key
ushort KeyId = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(key, 0));
byte[] key1 = new byte[32]; // HMAC
byte[] key2 = new byte[16]; // AES
Array.Copy(key, 2, key1, 0, 32);
Array.Copy(key, 34, key2, 0, 16);
// Decode IV
byte[] buf2 = null;
try { buf2 = Convert.FromBase64String(msg.Substring(3)); }
catch (Exception) { }
if (buf2 == null || buf2.Length < 20) return null;
ushort KeyId2 = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buf2, 0));
if (KeyId != KeyId2) return null;
byte[] iv = new byte[16];
Array.Copy(buf2, 2, iv, 0, 16);
byte[] buf = new byte[buf2.Length - 18];
Array.Copy(buf2, 18, buf, 0, buf.Length);
// Setup and perform AES128-CBC
byte[] decoded_msg = null;
using (Rijndael rij = new RijndaelManaged())
{
rij.KeySize = 128;
rij.Mode = CipherMode.CBC;
rij.Padding = PaddingMode.PKCS7;
rij.Key = key2;
rij.IV = iv;
// Perform decrypt
using (CryptoStream cs = new CryptoStream(new MemoryStream(buf), rij.CreateDecryptor(), CryptoStreamMode.Read))
{
byte[] cleanmem = new byte[msg.Length]; // Worst case possible
int clearlen = cs.Read(cleanmem, 0, msg.Length);
if (clearlen < 16) return null;
decoded_msg = new byte[clearlen];
Array.Copy(cleanmem, 0, decoded_msg, 0, clearlen);
}
}
// Setup and perform HMAC-SHA256
using (HMACSHA256 hmac = new HMACSHA256(key1))
{
byte[] hmacresult = hmac.ComputeHash(decoded_msg, 32, decoded_msg.Length - 32);
byte[] hmacexpected = new byte[32];
Array.Copy(decoded_msg, 0, hmacexpected, 0, 32);
if (MeshUtils.ByteArrayCompare(hmacresult, hmacexpected) == false) return null;
resulting_msg = new byte[decoded_msg.Length - 32];
Array.Copy(decoded_msg, 32, resulting_msg, 0, decoded_msg.Length - 32);
}
}
catch (Exception) { return null; }
return resulting_msg;
}
public static string UrlEscapeBase64(string base64str)
{
char[] t = base64str.ToCharArray();
for (int i = 0; i < t.Length; i++)
{
switch (t[i])
{
case '+': t[i] = '@'; break;
case '/': t[i] = '$'; break;
}
}
return new string(t);
}
public static string UrlUnEscapeBase64(string base64str)
{
char[] t = base64str.ToCharArray();
for (int i = 0; i < t.Length; i++)
{
switch (t[i])
{
case '@': t[i] = '+'; break;
case '$': t[i] = '/'; break;
}
}
return new string(t);
}
// BinaryWriter Object Recycling System
private static Stack<BinaryWriter> BinaryWriteRecycleList = new Stack<BinaryWriter>();
public static BinaryWriter GetBinaryWriter() { lock (BinaryWriteRecycleList) { return (BinaryWriteRecycleList.Count == 0) ? new BinaryWriter(new MemoryStream(32000), Encoding.UTF8) : BinaryWriteRecycleList.Pop(); } }
public static void RecycleBinaryWriter(BinaryWriter obj) { lock (BinaryWriteRecycleList) { ((MemoryStream)obj.BaseStream).SetLength(0); BinaryWriteRecycleList.Push(obj); } }
// MemoryStream Object Recycling System
private static Stack<MemoryStream> MemoryStreamRecycleList = new Stack<MemoryStream>();
public static MemoryStream GetMemoryStream() { lock (MemoryStreamRecycleList) { return (MemoryStreamRecycleList.Count == 0) ? new MemoryStream(32000) : MemoryStreamRecycleList.Pop(); } }
public static void RecycleMemoryStream(MemoryStream obj) { lock (MemoryStreamRecycleList) { obj.SetLength(0); MemoryStreamRecycleList.Push(obj); } }
// StringBuilder Object Recycling System
private static Stack<StringBuilder> StringBuilderRecycleList = new Stack<StringBuilder>();
public static StringBuilder GetStringBuilder() { lock (StringBuilderRecycleList) { return (StringBuilderRecycleList.Count == 0) ? new StringBuilder(16000) : StringBuilderRecycleList.Pop(); } }
public static void RecycleStringBuilder(StringBuilder obj) { lock (StringBuilderRecycleList) { obj.Length = 0; StringBuilderRecycleList.Push(obj); } }
}
}

29
NodeClass.cs Normal file
View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MeshCentralRouter
{
public class NodeClass
{
public string name;
public int icon;
public string nodeid;
public string meshid;
public int conn;
public override string ToString() { return name; }
}
public class MeshClass
{
public string name;
public string meshid;
public string desc;
public int type;
public override string ToString() { return name; }
}
}

38
Program.cs Normal file
View File

@@ -0,0 +1,38 @@
/*
Copyright 2009-2017 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using System;
using System.Windows.Forms;
namespace MeshCentralRouter
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
// Setup settings & visual style
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Properties.Settings.Default.Upgrade();
Application.Run(new MainForm(args));
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MeshCentral Router")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Open Source")]
[assembly: AssemblyProduct("MeshCentral Router")]
[assembly: AssemblyCopyright("Apache 2.0 license")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("D8A68056-F2F9-4F81-A9BE-9348879C62AD")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]

199
Properties/Resources.Designer.cs generated Normal file
View File

@@ -0,0 +1,199 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MeshCentralRouter.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MeshCentralRouter.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Confirm Delete.
/// </summary>
internal static string CertMgrForm_Del {
get {
return ResourceManager.GetString("CertMgrForm_Del", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Delete Selected Certificate?.
/// </summary>
internal static string CertMgrForm_DelStr {
get {
return ResourceManager.GetString("CertMgrForm_DelStr", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Empty_Banner {
get {
object obj = ResourceManager.GetObject("Empty-Banner", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Folder36 {
get {
object obj = ResourceManager.GetObject("Folder36", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Help20 {
get {
object obj = ResourceManager.GetObject("Help20", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap HelpRelayMap {
get {
object obj = ResourceManager.GetObject("HelpRelayMap", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons01 {
get {
object obj = ResourceManager.GetObject("icons01", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap MC2_Banner {
get {
object obj = ResourceManager.GetObject("MC2-Banner", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap MC2_Logo {
get {
object obj = ResourceManager.GetObject("MC2-Logo", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap MeshCentral {
get {
object obj = ResourceManager.GetObject("MeshCentral", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap MeshIcon50T {
get {
object obj = ResourceManager.GetObject("MeshIcon50T", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap MeshServerLogo {
get {
object obj = ResourceManager.GetObject("MeshServerLogo", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized string similar to Cert Import.
/// </summary>
internal static string MsgBox_Import_Cert {
get {
return ResourceManager.GetString("MsgBox_Import_Cert", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Incorrect file or password.
/// </summary>
internal static string MsgBox_Import_Error {
get {
return ResourceManager.GetString("MsgBox_Import_Error", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="MsgBox_Import_Cert" xml:space="preserve">
<value>Cert Import</value>
</data>
<data name="CertMgrForm_DelStr" xml:space="preserve">
<value>Effacer le certificat sélectionné?</value>
</data>
<data name="MsgBox_Import_Error" xml:space="preserve">
<value>Incorrect file or password</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="logo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\logo.gif;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CertMgrForm_Del" xml:space="preserve">
<value>Confirmation d'effacement</value>
</data>
<data name="Padlock" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Padlock.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Padlock2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Padlock2.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="MsgBox_Import_Cert" xml:space="preserve">
<value>証明書をインポート</value>
</data>
<data name="CertMgrForm_DelStr" xml:space="preserve">
<value>選択した証明書を削除しますか?</value>
</data>
<data name="MsgBox_Import_Error" xml:space="preserve">
<value>ファイルまたはパスワードが違います</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="logo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\logo.gif;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CertMgrForm_Del" xml:space="preserve">
<value>削除の確認</value>
</data>
<data name="Padlock" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Padlock.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Padlock2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Padlock2.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="MsgBox_Import_Cert" xml:space="preserve">
<value>Cert Import</value>
</data>
<data name="CertMgrForm_DelStr" xml:space="preserve">
<value>선택된 인증서 지우기?</value>
</data>
<data name="MsgBox_Import_Error" xml:space="preserve">
<value>Incorrect file or password</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="logo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\logo.gif;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CertMgrForm_Del" xml:space="preserve">
<value>지우기 확인</value>
</data>
<data name="Padlock" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Padlock.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Padlock2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Padlock2.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

163
Properties/Resources.resx Normal file
View File

@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Empty-Banner" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Empty-Banner.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="MeshCentral" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\MeshCentral.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Folder36" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Folder36.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="MC2-Logo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\MC2-Logo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CertMgrForm_Del" xml:space="preserve">
<value>Confirm Delete</value>
</data>
<data name="MC2-Banner" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\MC2-Banner.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="MsgBox_Import_Error" xml:space="preserve">
<value>Incorrect file or password</value>
</data>
<data name="CertMgrForm_DelStr" xml:space="preserve">
<value>Delete Selected Certificate?</value>
</data>
<data name="icons01" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\icons01.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="MeshServerLogo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\MeshServerLogo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Help20" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Help20.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="MsgBox_Import_Cert" xml:space="preserve">
<value>Cert Import</value>
</data>
<data name="MeshIcon50T" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\MeshIcon50T.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="HelpRelayMap" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\HelpImages\HelpRelayMap.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="MsgBox_Import_Cert" xml:space="preserve">
<value>Cert Import</value>
</data>
<data name="CertMgrForm_DelStr" xml:space="preserve">
<value>删除选中的证书?</value>
</data>
<data name="MsgBox_Import_Error" xml:space="preserve">
<value>Incorrect file or password</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="logo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\logo.gif;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CertMgrForm_Del" xml:space="preserve">
<value>确认删除</value>
</data>
<data name="Padlock" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Padlock.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Padlock2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Padlock2.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

98
Properties/Settings.Designer.cs generated Normal file
View File

@@ -0,0 +1,98 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MeshCentralRouter.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int ViewType {
get {
return ((int)(this["ViewType"]));
}
set {
this["ViewType"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("1")]
public int GraphType {
get {
return ((int)(this["GraphType"]));
}
set {
this["GraphType"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool ShowHiddenNodes {
get {
return ((bool)(this["ShowHiddenNodes"]));
}
set {
this["ShowHiddenNodes"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string ServerCertHash {
get {
return ((string)(this["ServerCertHash"]));
}
set {
this["ServerCertHash"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool AllowsAgentDownloads {
get {
return ((bool)(this["AllowsAgentDownloads"]));
}
set {
this["AllowsAgentDownloads"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool AllowsAgentUploads {
get {
return ((bool)(this["AllowsAgentUploads"]));
}
set {
this["AllowsAgentUploads"] = value;
}
}
}
}

View File

@@ -0,0 +1,24 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="MeshServer.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="ViewType" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="GraphType" Type="System.Int32" Scope="User">
<Value Profile="(Default)">1</Value>
</Setting>
<Setting Name="ShowHiddenNodes" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="ServerCertHash" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="AllowsAgentDownloads" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="AllowsAgentUploads" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>

BIN
Resources/50-Computer.xpng Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
Resources/Padlock.xpng Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
Resources/Padlock2.xpng Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
Resources/Thumbs.db Normal file

Binary file not shown.

BIN
Resources/logo.xgif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1002 B

126
ServerUserControl.Designer.cs generated Normal file
View File

@@ -0,0 +1,126 @@
namespace MeshCentralRouter
{
partial class ServerUserControl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.serverInfoLabel = new System.Windows.Forms.Label();
this.serverNameLabel = new System.Windows.Forms.Label();
this.serverPictureBox = new System.Windows.Forms.PictureBox();
this.serverContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.infoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.backTimer = new System.Windows.Forms.Timer(this.components);
((System.ComponentModel.ISupportInitialize)(this.serverPictureBox)).BeginInit();
this.serverContextMenuStrip.SuspendLayout();
this.SuspendLayout();
//
// serverInfoLabel
//
this.serverInfoLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.serverInfoLabel.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.serverInfoLabel.Location = new System.Drawing.Point(65, 30);
this.serverInfoLabel.Name = "serverInfoLabel";
this.serverInfoLabel.Size = new System.Drawing.Size(420, 18);
this.serverInfoLabel.TabIndex = 11;
this.serverInfoLabel.Text = "Server information";
this.serverInfoLabel.Click += new System.EventHandler(this.serverButton_Click);
//
// serverNameLabel
//
this.serverNameLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.serverNameLabel.Font = new System.Drawing.Font("Arial", 11.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.serverNameLabel.Location = new System.Drawing.Point(65, 10);
this.serverNameLabel.Name = "serverNameLabel";
this.serverNameLabel.Size = new System.Drawing.Size(420, 18);
this.serverNameLabel.TabIndex = 10;
this.serverNameLabel.Text = "ServerName";
this.serverNameLabel.Click += new System.EventHandler(this.serverButton_Click);
//
// serverPictureBox
//
this.serverPictureBox.Image = global::MeshCentralRouter.Properties.Resources.MeshCentral;
this.serverPictureBox.Location = new System.Drawing.Point(0, 0);
this.serverPictureBox.Name = "serverPictureBox";
this.serverPictureBox.Size = new System.Drawing.Size(59, 59);
this.serverPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.serverPictureBox.TabIndex = 9;
this.serverPictureBox.TabStop = false;
this.serverPictureBox.Click += new System.EventHandler(this.serverButton_Click);
//
// serverContextMenuStrip
//
this.serverContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.infoToolStripMenuItem});
this.serverContextMenuStrip.Name = "serverContextMenuStrip";
this.serverContextMenuStrip.Size = new System.Drawing.Size(153, 48);
//
// infoToolStripMenuItem
//
this.infoToolStripMenuItem.Name = "infoToolStripMenuItem";
this.infoToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.infoToolStripMenuItem.Text = "&Info...";
this.infoToolStripMenuItem.Click += new System.EventHandler(this.infoToolStripMenuItem_Click);
//
// backTimer
//
this.backTimer.Interval = 2000;
this.backTimer.Tick += new System.EventHandler(this.backTime_Tick);
//
// ServerUserControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.ContextMenuStrip = this.serverContextMenuStrip;
this.Controls.Add(this.serverInfoLabel);
this.Controls.Add(this.serverNameLabel);
this.Controls.Add(this.serverPictureBox);
this.Cursor = System.Windows.Forms.Cursors.Hand;
this.Name = "ServerUserControl";
this.Size = new System.Drawing.Size(485, 57);
this.Load += new System.EventHandler(this.ServerUserControl_Load);
this.Click += new System.EventHandler(this.serverButton_Click);
((System.ComponentModel.ISupportInitialize)(this.serverPictureBox)).EndInit();
this.serverContextMenuStrip.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Label serverInfoLabel;
private System.Windows.Forms.Label serverNameLabel;
private System.Windows.Forms.PictureBox serverPictureBox;
private System.Windows.Forms.ContextMenuStrip serverContextMenuStrip;
private System.Windows.Forms.ToolStripMenuItem infoToolStripMenuItem;
private System.Windows.Forms.Timer backTimer;
}
}

88
ServerUserControl.cs Normal file
View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MeshCentralRouter
{
public partial class ServerUserControl : UserControl
{
private MainForm parent;
public string key;
public string name;
public string info;
public string url;
public DateTime lastUpdate;
private Color xbackColor;
public ServerUserControl(MainForm parent, string key, string name, string info, string url)
{
this.parent = parent;
this.key = key;
this.name = name;
this.info = info;
this.url = url;
this.lastUpdate = DateTime.Now;
InitializeComponent();
}
private void ServerUserControl_Load(object sender, EventArgs e)
{
serverNameLabel.Text = this.name;
serverInfoLabel.Text = this.info;
xbackColor = BackColor;
BackColor = Color.Wheat;
backTimer.Enabled = true;
}
public bool Update(string name, string info, string url)
{
this.lastUpdate = DateTime.Now;
// Fix the name
if (name == null) { name = this.name; }
if (name == null) { name = "MeshCentral"; }
// Don't replace a IPv4 address with a IPv6 one, or remove information
if ((this.url.IndexOf("://[") == -1) && (url.IndexOf("://[") >= 0)) return false;
if ((this.info != null) && (info == null)) return false;
// If any changes need to be made, make them now
if ((this.name != name) || (this.info != info) || (this.url != url))
{
this.name = name;
this.info = info;
this.url = url;
serverNameLabel.Text = this.name;
if (this.info != null) { serverInfoLabel.Text = this.info; } else { serverInfoLabel.Text = url; }
BackColor = Color.Wheat;
backTimer.Enabled = true;
return true;
}
return false;
}
private void serverButton_Click(object sender, EventArgs e)
{
//MouseEventArgs me = (MouseEventArgs)e;
//if (me.Button == MouseButtons.Left) { parent.serverClick(this); }
}
private void infoToolStripMenuItem_Click(object sender, EventArgs e)
{
//ServerInfoForm form = new ServerInfoForm(name, url, info, key);
//form.ShowDialog(this);
}
private void backTime_Tick(object sender, EventArgs e)
{
BackColor = xbackColor;
backTimer.Enabled = false;
}
}
}

126
ServerUserControl.resx Normal file
View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="serverContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="backTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>200, 17</value>
</metadata>
</root>

128
SettingsForm.Designer.cs generated Normal file
View File

@@ -0,0 +1,128 @@
namespace MeshCentralRouter
{
partial class SettingsForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingsForm));
this.cancelButton = new System.Windows.Forms.Button();
this.okButton = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.allInterfacesCheckBox = new System.Windows.Forms.CheckBox();
this.systemTrayCheckBox = new System.Windows.Forms.CheckBox();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// cancelButton
//
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(171, 94);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(75, 23);
this.cancelButton.TabIndex = 0;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
//
// okButton
//
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.okButton.Location = new System.Drawing.Point(90, 94);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 23);
this.okButton.TabIndex = 1;
this.okButton.Text = "OK";
this.okButton.UseVisualStyleBackColor = true;
this.okButton.Click += new System.EventHandler(this.okButton_Click);
//
// groupBox1
//
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox1.Controls.Add(this.systemTrayCheckBox);
this.groupBox1.Controls.Add(this.allInterfacesCheckBox);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(234, 76);
this.groupBox1.TabIndex = 2;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Settings";
//
// allInterfacesCheckBox
//
this.allInterfacesCheckBox.AutoSize = true;
this.allInterfacesCheckBox.Location = new System.Drawing.Point(13, 22);
this.allInterfacesCheckBox.Name = "allInterfacesCheckBox";
this.allInterfacesCheckBox.Size = new System.Drawing.Size(208, 17);
this.allInterfacesCheckBox.TabIndex = 0;
this.allInterfacesCheckBox.Text = "Bind local port to all network interfaces";
this.allInterfacesCheckBox.UseVisualStyleBackColor = true;
//
// systemTrayCheckBox
//
this.systemTrayCheckBox.AutoSize = true;
this.systemTrayCheckBox.Location = new System.Drawing.Point(13, 45);
this.systemTrayCheckBox.Name = "systemTrayCheckBox";
this.systemTrayCheckBox.Size = new System.Drawing.Size(123, 17);
this.systemTrayCheckBox.TabIndex = 1;
this.systemTrayCheckBox.Text = "Show on system tray";
this.systemTrayCheckBox.UseVisualStyleBackColor = true;
//
// SettingsForm
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(258, 129);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.okButton);
this.Controls.Add(this.cancelButton);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "SettingsForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Settings";
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Button okButton;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.CheckBox systemTrayCheckBox;
private System.Windows.Forms.CheckBox allInterfacesCheckBox;
}
}

41
SettingsForm.cs Normal file
View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MeshCentralRouter
{
public partial class SettingsForm : Form
{
public SettingsForm()
{
InitializeComponent();
}
public bool BindAllInterfaces
{
get { return allInterfacesCheckBox.Checked; }
set { allInterfacesCheckBox.Checked = value; }
}
public bool ShowSystemTray
{
get { return systemTrayCheckBox.Checked; }
set { systemTrayCheckBox.Checked = value; }
}
private void okButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
}
private void cancelButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
}
}

1815
SettingsForm.resx Normal file

File diff suppressed because it is too large Load Diff

124
Win32Api.cs Normal file
View File

@@ -0,0 +1,124 @@
/*
Copyright 2009-2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace MeshCentralRouter
{
public class Win32Api
{
public const int WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0;
public const int WINHTTP_ACCESS_TYPE_NO_PROXY = 1;
public const int WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3;
public const int WINHTTP_AUTOPROXY_AUTO_DETECT = 0x00000001;
public const int WINHTTP_AUTOPROXY_CONFIG_URL = 0x00000002;
public const int WINHTTP_AUTOPROXY_RUN_INPROCESS = 0x00010000;
public const int WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = 0x00020000;
public const int WINHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001;
public const int WINHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WINHTTP_AUTOPROXY_OPTIONS
{
[MarshalAs(UnmanagedType.U4)]
public int dwFlags;
[MarshalAs(UnmanagedType.U4)]
public int dwAutoDetectFlags;
public string lpszAutoConfigUrl;
public IntPtr lpvReserved;
[MarshalAs(UnmanagedType.U4)]
public int dwReserved;
public bool fAutoLoginIfChallenged;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WINHTTP_PROXY_INFO
{
[MarshalAs(UnmanagedType.U4)]
public int dwAccessType;
public string lpszProxy;
public string lpszProxyBypass;
}
[DllImport("winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool WinHttpGetProxyForUrl(IntPtr hSession, string lpcwszUrl, ref WINHTTP_AUTOPROXY_OPTIONS pAutoProxyOptions, ref WINHTTP_PROXY_INFO pProxyInfo);
[DllImport("winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr WinHttpOpen(string pwszUserAgent, int dwAccessType, IntPtr pwszProxyName, IntPtr pwszProxyBypass, int dwFlags);
[DllImport("winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool WinHttpCloseHandle(IntPtr hInternet);
[DllImport("kernel32.dll")]
public static extern int GetLastError();
public static Uri GetProxy(Uri url)
{
// Check if we need to use a HTTP proxy (Auto-proxy way)
try
{
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
Object x = registryKey.GetValue("AutoConfigURL", null);
if ((x != null) && (x.GetType() == typeof(string)))
{
string proxyStr = GetProxyForUrlUsingPac("http" + ((url.Port == 80) ? "" : "s") + "://" + url.Host + ":" + url.Port, x.ToString());
return new Uri("http://" + proxyStr);
}
}
catch (Exception) { }
Uri proxyUri = null;
try
{
// Check if we need to use a HTTP proxy (Normal way)
proxyUri = System.Net.HttpWebRequest.GetSystemWebProxy().GetProxy(url);
if ((url.Host.ToLower() == proxyUri.Host.ToLower()) && (url.Port == proxyUri.Port)) { return null; }
}
catch (Exception) { }
return proxyUri;
}
private static string GetProxyForUrlUsingPac(string DestinationUrl, string PacUri)
{
IntPtr WinHttpSession = Win32Api.WinHttpOpen("User", Win32Api.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, IntPtr.Zero, IntPtr.Zero, 0);
Win32Api.WINHTTP_AUTOPROXY_OPTIONS ProxyOptions = new Win32Api.WINHTTP_AUTOPROXY_OPTIONS();
Win32Api.WINHTTP_PROXY_INFO ProxyInfo = new Win32Api.WINHTTP_PROXY_INFO();
ProxyOptions.dwFlags = Win32Api.WINHTTP_AUTOPROXY_CONFIG_URL;
ProxyOptions.dwAutoDetectFlags = (Win32Api.WINHTTP_AUTO_DETECT_TYPE_DHCP | Win32Api.WINHTTP_AUTO_DETECT_TYPE_DNS_A);
ProxyOptions.lpszAutoConfigUrl = PacUri;
// Get Proxy
bool IsSuccess = Win32Api.WinHttpGetProxyForUrl(WinHttpSession, DestinationUrl, ref ProxyOptions, ref ProxyInfo);
Win32Api.WinHttpCloseHandle(WinHttpSession);
if (IsSuccess)
{
return ProxyInfo.lpszProxy;
}
else
{
Console.WriteLine("Error: {0}", Win32Api.GetLastError());
return null;
}
}
}
}

42
app.config Normal file
View File

@@ -0,0 +1,42 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="MeshServer.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
<section name="MeshStateMonitor.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
</sectionGroup>
</configSections>
<userSettings>
<MeshServer.Properties.Settings>
<setting name="ViewType" serializeAs="String">
<value>0</value>
</setting>
<setting name="GraphType" serializeAs="String">
<value>1</value>
</setting>
<setting name="ShowHiddenNodes" serializeAs="String">
<value>True</value>
</setting>
<setting name="ServerCertHash" serializeAs="String">
<value/>
</setting>
<setting name="AllowsAgentDownloads" serializeAs="String">
<value>False</value>
</setting>
<setting name="AllowsAgentUploads" serializeAs="String">
<value>False</value>
</setting>
</MeshServer.Properties.Settings>
<MeshStateMonitor.Properties.Settings>
<setting name="ViewType" serializeAs="String">
<value>0</value>
</setting>
<setting name="GraphType" serializeAs="String">
<value>1</value>
</setting>
<setting name="ShowHiddenNodes" serializeAs="String">
<value>True</value>
</setting>
</MeshStateMonitor.Properties.Settings>
</userSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>

75
app.manifest Normal file
View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on and is
is designed to work with. Uncomment the appropriate elements and Windows will
automatically selected the most compatible environment. -->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
</application>
</compatibility>
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
<!--
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
-->
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->
</assembly>

BIN
icons01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
icons02.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
icons03.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
icons04.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
icons05.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
icons06.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
icons50.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
warning-small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB