mirror of
https://github.com/snltty/linker.git
synced 2025-11-02 13:34:09 +08:00
桌面共享使用打洞或者服务器中继进行代理
This commit is contained in:
60
cmonitor.clipboard.win/MainForm.Designer.cs
generated
60
cmonitor.clipboard.win/MainForm.Designer.cs
generated
@@ -1,60 +0,0 @@
|
||||
namespace cmonitor.clipboard.win
|
||||
{
|
||||
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()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||
textBox1 = new TextBox();
|
||||
SuspendLayout();
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
textBox1.Location = new Point(12, 12);
|
||||
textBox1.Multiline = true;
|
||||
textBox1.Name = "textBox1";
|
||||
textBox1.Size = new Size(261, 287);
|
||||
textBox1.TabIndex = 0;
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 17F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new Size(285, 450);
|
||||
Controls.Add(textBox1);
|
||||
Icon = (Icon)resources.GetObject("$this.Icon");
|
||||
Name = "MainForm";
|
||||
Text = "剪贴板";
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private TextBox textBox1;
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace cmonitor.clipboard.win
|
||||
{
|
||||
public partial class MainForm : Form
|
||||
{
|
||||
protected override CreateParams CreateParams
|
||||
{
|
||||
get
|
||||
{
|
||||
const int WS_EX_APPWINDOW = 0x40000;
|
||||
const int WS_EX_TOOLWINDOW = 0x80;
|
||||
CreateParams cp = base.CreateParams;
|
||||
cp.ExStyle &= (~WS_EX_APPWINDOW);
|
||||
cp.ExStyle |= WS_EX_TOOLWINDOW;
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr nextClipboardViewer;
|
||||
const int WM_DRAWCLIPBOARD = 0x0308;
|
||||
const uint CF_TEXT = 1;
|
||||
const uint CF_HDROP = 15;
|
||||
public MainForm()
|
||||
{
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
|
||||
InitializeComponent();
|
||||
nextClipboardViewer = SetClipboardViewer(this.Handle);
|
||||
}
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
base.WndProc(ref m);
|
||||
|
||||
if (m.Msg == WM_DRAWCLIPBOARD)
|
||||
{
|
||||
OnClipboardChanged();
|
||||
}
|
||||
}
|
||||
private void OnClipboardChanged()
|
||||
{
|
||||
if (OpenClipboard(IntPtr.Zero))
|
||||
{
|
||||
uint format = 0;
|
||||
while ((format = EnumClipboardFormats(format)) != 0)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CF_TEXT:
|
||||
HandleTextData();
|
||||
break;
|
||||
case CF_HDROP:
|
||||
HandleFileListData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
}
|
||||
private void HandleTextData()
|
||||
{
|
||||
IntPtr clipboardData = GetClipboardData(CF_TEXT);
|
||||
if (clipboardData != IntPtr.Zero)
|
||||
{
|
||||
string text = Marshal.PtrToStringAnsi(clipboardData);
|
||||
this.Invoke(() =>
|
||||
{
|
||||
textBox1.Text = text;
|
||||
});
|
||||
}
|
||||
}
|
||||
private void HandleFileListData()
|
||||
{
|
||||
IntPtr clipboardData = GetClipboardData(CF_HDROP);
|
||||
if (clipboardData != IntPtr.Zero)
|
||||
{
|
||||
IntPtr fileDropHandle = Marshal.ReadIntPtr(clipboardData);
|
||||
uint fileCount = DragQueryFile(fileDropHandle, 0xFFFFFFFF, null, 0);
|
||||
|
||||
List<string> fileList = new List<string>();
|
||||
for (uint i = 0; i < fileCount; i++)
|
||||
{
|
||||
uint bufferSize = DragQueryFile(fileDropHandle, i, null, 0) + 1;
|
||||
char[] fileName = new char[bufferSize];
|
||||
|
||||
DragQueryFile(fileDropHandle, i, fileName, bufferSize);
|
||||
string filePath = new string(fileName);
|
||||
|
||||
fileList.Add(filePath);
|
||||
}
|
||||
|
||||
DragFinish(fileDropHandle);
|
||||
|
||||
this.Invoke(() =>
|
||||
{
|
||||
textBox1.Text = string.Join("\r\n", fileList);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern IntPtr GetClipboardData(uint uFormat);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern bool IsClipboardFormatAvailable(uint format);
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern uint EnumClipboardFormats(uint format);
|
||||
[DllImport("shell32.dll")]
|
||||
static extern uint DragQueryFile(IntPtr hDrop, uint iFile, char[] lpszFile, uint cch);
|
||||
|
||||
[DllImport("shell32.dll")]
|
||||
static extern void DragFinish(IntPtr hDrop);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern bool OpenClipboard(IntPtr hWndNewOwner);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern bool CloseClipboard();
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern IntPtr GlobalLock(IntPtr hMem);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern bool GlobalUnlock(IntPtr hMem);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,400 +0,0 @@
|
||||
<?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.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace cmonitor.clipboard.win
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
// To customize application configuration such as set high DPI settings or default font,
|
||||
// see https://aka.ms/applicationconfiguration.
|
||||
ApplicationConfiguration.Initialize();
|
||||
Application.Run(new MainForm());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?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 清单选项
|
||||
如果想要更改 Windows 用户帐户控制级别,请使用
|
||||
以下节点之一替换 requestedExecutionLevel 节点。
|
||||
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||
|
||||
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
|
||||
如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此
|
||||
元素。
|
||||
-->
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
|
||||
Windows 版本的列表。取消评论适当的元素,
|
||||
Windows 将自动选择最兼容的环境。 -->
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
|
||||
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
|
||||
选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应
|
||||
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。
|
||||
|
||||
将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
|
||||
<!--
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
-->
|
||||
|
||||
<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
|
||||
<!--
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
</assembly>
|
||||
@@ -1,17 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFrameworks>net7.0-windows;net8.0-windows</TargetFrameworks>
|
||||
<Nullable>disable</Nullable>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="favicon.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Compile Update="MainForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
@@ -180,10 +180,6 @@ namespace cmonitor.install.win
|
||||
{
|
||||
public sealed class ViewerConfigInfo
|
||||
{
|
||||
[JsonIgnore]
|
||||
public const string userNameKey = "viewer-username";
|
||||
|
||||
public int ProxyPort { get; set; } = 1803;
|
||||
}
|
||||
|
||||
public sealed partial class ConfigClientInfo
|
||||
|
||||
48
cmonitor.install.win/MainForm.Designer.cs
generated
48
cmonitor.install.win/MainForm.Designer.cs
generated
@@ -52,11 +52,6 @@
|
||||
shareItemLen = new TextBox();
|
||||
gbClient = new GroupBox();
|
||||
gbServer = new GroupBox();
|
||||
cbBlueProtect = new CheckBox();
|
||||
tbViewerPortClient = new TextBox();
|
||||
label7 = new Label();
|
||||
tbViewerPortServer = new TextBox();
|
||||
label8 = new Label();
|
||||
gbClient.SuspendLayout();
|
||||
gbServer.SuspendLayout();
|
||||
SuspendLayout();
|
||||
@@ -177,8 +172,6 @@
|
||||
// gbClient
|
||||
//
|
||||
resources.ApplyResources(gbClient, "gbClient");
|
||||
gbClient.Controls.Add(tbViewerPortClient);
|
||||
gbClient.Controls.Add(label7);
|
||||
gbClient.Controls.Add(machineName);
|
||||
gbClient.Controls.Add(label16);
|
||||
gbClient.Controls.Add(serverIP);
|
||||
@@ -195,8 +188,6 @@
|
||||
// gbServer
|
||||
//
|
||||
resources.ApplyResources(gbServer, "gbServer");
|
||||
gbServer.Controls.Add(tbViewerPortServer);
|
||||
gbServer.Controls.Add(label8);
|
||||
gbServer.Controls.Add(apiPort);
|
||||
gbServer.Controls.Add(serverPort);
|
||||
gbServer.Controls.Add(label2);
|
||||
@@ -206,37 +197,10 @@
|
||||
gbServer.Name = "gbServer";
|
||||
gbServer.TabStop = false;
|
||||
//
|
||||
// cbBlueProtect
|
||||
//
|
||||
resources.ApplyResources(cbBlueProtect, "cbBlueProtect");
|
||||
cbBlueProtect.Name = "cbBlueProtect";
|
||||
cbBlueProtect.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// tbViewerPortClient
|
||||
//
|
||||
resources.ApplyResources(tbViewerPortClient, "tbViewerPortClient");
|
||||
tbViewerPortClient.Name = "tbViewerPortClient";
|
||||
//
|
||||
// label7
|
||||
//
|
||||
resources.ApplyResources(label7, "label7");
|
||||
label7.Name = "label7";
|
||||
//
|
||||
// tbViewerPortServer
|
||||
//
|
||||
resources.ApplyResources(tbViewerPortServer, "tbViewerPortServer");
|
||||
tbViewerPortServer.Name = "tbViewerPortServer";
|
||||
//
|
||||
// label8
|
||||
//
|
||||
resources.ApplyResources(label8, "label8");
|
||||
label8.Name = "label8";
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
resources.ApplyResources(this, "$this");
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
Controls.Add(cbBlueProtect);
|
||||
Controls.Add(gbServer);
|
||||
Controls.Add(gbClient);
|
||||
Controls.Add(checkStateBtn);
|
||||
@@ -280,17 +244,5 @@
|
||||
private TextBox shareItemLen;
|
||||
private GroupBox gbClient;
|
||||
private GroupBox gbServer;
|
||||
private CheckBox cbBlueProtect;
|
||||
|
||||
/* 项目“cmonitor.install.win (net8.0-windows)”的未合并的更改
|
||||
在此之前:
|
||||
private TextBox textBox1;
|
||||
在此之后:
|
||||
private TextBox tbViewerPortCLient;
|
||||
*/
|
||||
private TextBox tbViewerPortClient;
|
||||
private Label label7;
|
||||
private TextBox tbViewerPortServer;
|
||||
private Label label8;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,14 +31,11 @@ namespace cmonitor.install.win
|
||||
}
|
||||
private void LoadConfig()
|
||||
{
|
||||
cbBlueProtect.Checked = config.Common.BlueProtect;
|
||||
|
||||
modeClient.Checked = config.Common.Modes.Contains("client");
|
||||
modeServer.Checked = config.Common.Modes.Contains("server");
|
||||
|
||||
machineName.Text = config.Client.Name;
|
||||
serverIP.Text = config.Client.Server;
|
||||
tbViewerPortClient.Text = config.Client.Viewer.ProxyPort.ToString();
|
||||
|
||||
shareKey.Text = config.Client.ShareMemoryKey;
|
||||
shareLen.Text = config.Client.ShareMemoryCount.ToString();
|
||||
@@ -47,7 +44,6 @@ namespace cmonitor.install.win
|
||||
serverPort.Text = config.Server.ServicePort.ToString();
|
||||
apiPort.Text = config.Server.ApiPort.ToString();
|
||||
webPort.Text = config.Server.WebPort.ToString();
|
||||
tbViewerPortServer.Text = config.Server.Viewer.ProxyPort.ToString();
|
||||
}
|
||||
|
||||
private bool loading = false;
|
||||
@@ -115,8 +111,6 @@ namespace cmonitor.install.win
|
||||
|
||||
private bool CheckMode()
|
||||
{
|
||||
config.Common.BlueProtect = cbBlueProtect.Checked;
|
||||
|
||||
if (modeClient.Checked == false && modeServer.Checked == false)
|
||||
{
|
||||
MessageBox.Show("客户端和服务端必须选择一样!");
|
||||
@@ -164,20 +158,11 @@ namespace cmonitor.install.win
|
||||
MessageBox.Show("web端口必填");
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(tbViewerPortClient.Text) || string.IsNullOrWhiteSpace(tbViewerPortServer.Text))
|
||||
{
|
||||
MessageBox.Show("共享桌面代理端口必填");
|
||||
return false;
|
||||
}
|
||||
config.Client.Server = serverIP.Text;
|
||||
config.Server.WebPort = int.Parse(webPort.Text);
|
||||
config.Server.ApiPort = int.Parse(apiPort.Text);
|
||||
config.Server.ServicePort = int.Parse(serverPort.Text);
|
||||
|
||||
config.Client.Viewer.ProxyPort = int.Parse(tbViewerPortClient.Text);
|
||||
config.Server.Viewer.ProxyPort = int.Parse(tbViewerPortServer.Text);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -119,165 +119,239 @@
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="serverIP.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>93, 52</value>
|
||||
<value>186, 95</value>
|
||||
</data>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="serverIP.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="serverIP.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>196, 38</value>
|
||||
</data>
|
||||
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>17, 55</value>
|
||||
<value>34, 100</value>
|
||||
</data>
|
||||
<data name="label1.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 0, 6, 0</value>
|
||||
</data>
|
||||
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>68, 17</value>
|
||||
<value>134, 31</value>
|
||||
</data>
|
||||
<data name="label1.Text" xml:space="preserve">
|
||||
<value>服务端地址</value>
|
||||
</data>
|
||||
<data name="label2.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>17, 80</value>
|
||||
<value>34, 146</value>
|
||||
</data>
|
||||
<data name="label2.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 0, 6, 0</value>
|
||||
</data>
|
||||
<data name="label2.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>56, 17</value>
|
||||
<value>110, 31</value>
|
||||
</data>
|
||||
<data name="label2.Text" xml:space="preserve">
|
||||
<value>服务端口</value>
|
||||
</data>
|
||||
<data name="serverPort.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>79, 77</value>
|
||||
<value>158, 140</value>
|
||||
</data>
|
||||
<data name="serverPort.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="serverPort.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>196, 38</value>
|
||||
</data>
|
||||
<data name="label3.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>17, 28</value>
|
||||
<value>34, 51</value>
|
||||
</data>
|
||||
<data name="label3.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 0, 6, 0</value>
|
||||
</data>
|
||||
<data name="label3.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>110, 31</value>
|
||||
</data>
|
||||
<data name="webPort.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>79, 24</value>
|
||||
<value>158, 44</value>
|
||||
</data>
|
||||
<data name="webPort.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="webPort.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>196, 38</value>
|
||||
</data>
|
||||
<data name="label4.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>17, 54</value>
|
||||
<value>34, 98</value>
|
||||
</data>
|
||||
<data name="label4.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 0, 6, 0</value>
|
||||
</data>
|
||||
<data name="label4.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>56, 17</value>
|
||||
<value>110, 31</value>
|
||||
</data>
|
||||
<data name="label4.Text" xml:space="preserve">
|
||||
<value>管理端口</value>
|
||||
</data>
|
||||
<data name="apiPort.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>79, 51</value>
|
||||
<value>158, 93</value>
|
||||
</data>
|
||||
<data name="apiPort.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="apiPort.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>196, 38</value>
|
||||
</data>
|
||||
<data name="modeClient.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>105, 45</value>
|
||||
<value>210, 39</value>
|
||||
</data>
|
||||
<data name="modeClient.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="modeClient.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>118, 35</value>
|
||||
</data>
|
||||
<data name="modeServer.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>298, 45</value>
|
||||
<value>596, 39</value>
|
||||
</data>
|
||||
<data name="modeServer.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="modeServer.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>118, 35</value>
|
||||
</data>
|
||||
<data name="label5.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>19, 150</value>
|
||||
<value>38, 274</value>
|
||||
</data>
|
||||
<data name="label5.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 0, 6, 0</value>
|
||||
</data>
|
||||
<data name="label5.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>110, 31</value>
|
||||
</data>
|
||||
<data name="shareLen.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>93, 147</value>
|
||||
<value>186, 268</value>
|
||||
</data>
|
||||
<data name="shareLen.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="shareLen.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>196, 38</value>
|
||||
</data>
|
||||
<data name="label6.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>14, 124</value>
|
||||
<value>28, 226</value>
|
||||
</data>
|
||||
<data name="label6.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 0, 6, 0</value>
|
||||
</data>
|
||||
<data name="label6.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>134, 31</value>
|
||||
</data>
|
||||
<data name="shareKey.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>93, 120</value>
|
||||
<value>186, 219</value>
|
||||
</data>
|
||||
<data name="shareKey.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="shareKey.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>196, 38</value>
|
||||
</data>
|
||||
<data name="label11.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>26, 29</value>
|
||||
<value>52, 53</value>
|
||||
</data>
|
||||
<data name="label11.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 0, 6, 0</value>
|
||||
</data>
|
||||
<data name="label11.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>86, 31</value>
|
||||
</data>
|
||||
<data name="machineName.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>93, 25</value>
|
||||
<value>186, 46</value>
|
||||
</data>
|
||||
<data name="machineName.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="machineName.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>196, 38</value>
|
||||
</data>
|
||||
<data name="installBtn.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>175, 299</value>
|
||||
<value>350, 502</value>
|
||||
</data>
|
||||
<data name="installBtn.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="installBtn.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>162, 64</value>
|
||||
</data>
|
||||
<data name="runBtn.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>88, 299</value>
|
||||
<value>176, 502</value>
|
||||
</data>
|
||||
<data name="runBtn.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="runBtn.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>162, 64</value>
|
||||
</data>
|
||||
<data name="checkStateBtn.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>305, 305</value>
|
||||
<value>610, 513</value>
|
||||
</data>
|
||||
<data name="checkStateBtn.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="checkStateBtn.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>150, 42</value>
|
||||
</data>
|
||||
<data name="label16.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>7, 179</value>
|
||||
<value>14, 326</value>
|
||||
</data>
|
||||
<data name="label16.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 0, 6, 0</value>
|
||||
</data>
|
||||
<data name="label16.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>158, 31</value>
|
||||
</data>
|
||||
<data name="shareItemLen.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>93, 176</value>
|
||||
<value>186, 321</value>
|
||||
</data>
|
||||
<data name="shareItemLen.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="shareItemLen.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>196, 38</value>
|
||||
</data>
|
||||
<data name="gbClient.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>12, 72</value>
|
||||
<value>24, 88</value>
|
||||
</data>
|
||||
<data name="gbClient.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="gbClient.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="gbClient.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>200, 212</value>
|
||||
<value>400, 387</value>
|
||||
</data>
|
||||
<data name="gbClient.Text" xml:space="preserve">
|
||||
<value>客户端参数</value>
|
||||
</data>
|
||||
<data name="gbServer.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>219, 73</value>
|
||||
<value>438, 90</value>
|
||||
</data>
|
||||
<data name="gbServer.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="gbServer.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
<data name="gbServer.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>187, 211</value>
|
||||
<value>374, 385</value>
|
||||
</data>
|
||||
<data name="gbServer.Text" xml:space="preserve">
|
||||
<value>服务端参数</value>
|
||||
</data>
|
||||
<assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="cbBlueProtect.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
</data>
|
||||
<data name="cbBlueProtect.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>111, 21</value>
|
||||
</data>
|
||||
<data name="cbBlueProtect.Text" xml:space="preserve">
|
||||
<value>异常关闭则蓝屏</value>
|
||||
</data>
|
||||
<data name="tbViewerPortClient.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>93, 80</value>
|
||||
</data>
|
||||
<data name="tbViewerPortClient.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>100, 23</value>
|
||||
</data>
|
||||
<data name="tbViewerPortClient.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>37</value>
|
||||
</data>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="label7.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="label7.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>11, 83</value>
|
||||
</data>
|
||||
<data name="label7.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>80, 17</value>
|
||||
</data>
|
||||
<data name="label7.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>38</value>
|
||||
</data>
|
||||
<data name="label7.Text" xml:space="preserve">
|
||||
<value>共享桌面端口</value>
|
||||
</data>
|
||||
<data name="tbViewerPortServer.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>79, 104</value>
|
||||
</data>
|
||||
<data name="tbViewerPortServer.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>100, 23</value>
|
||||
</data>
|
||||
<data name="tbViewerPortServer.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>39</value>
|
||||
</data>
|
||||
<data name="label8.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="label8.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>-3, 107</value>
|
||||
</data>
|
||||
<data name="label8.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>80, 17</value>
|
||||
</data>
|
||||
<data name="label8.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>40</value>
|
||||
</data>
|
||||
<data name="label8.Text" xml:space="preserve">
|
||||
<value>共享桌面端口</value>
|
||||
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
|
||||
<value>14, 31</value>
|
||||
</data>
|
||||
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>418, 346</value>
|
||||
<value>836, 601</value>
|
||||
</data>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
@@ -558,4 +632,7 @@
|
||||
lbj4VzZ7T6Ce2eKyfeTF92Tj/y+1yov7XH58jUaj0Wg0Gk2v5P8D5M/bzdE8cNIAAAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
<data name="$this.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>6, 5, 6, 5</value>
|
||||
</data>
|
||||
</root>
|
||||
16
cmonitor.sln
16
cmonitor.sln
@@ -27,9 +27,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.viewer.server.win"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmonitor.killer", "cmonitor.killer\cmonitor.killer.vcxproj", "{E19B86AC-AC42-417A-8536-C2FFF1FB7FDC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.clipboard.win", "cmonitor.clipboard.win\cmonitor.clipboard.win.csproj", "{2A23EA37-3EAC-4B60-8576-84607ADB0256}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cmonitor.tests", "cmonitor.tests\cmonitor.tests.csproj", "{04AA3054-5350-4D8B-97F6-31495AE0609D}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.tests", "cmonitor.tests\cmonitor.tests.csproj", "{04AA3054-5350-4D8B-97F6-31495AE0609D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -185,18 +183,6 @@ Global
|
||||
{E19B86AC-AC42-417A-8536-C2FFF1FB7FDC}.Release|x64.Build.0 = Release|x64
|
||||
{E19B86AC-AC42-417A-8536-C2FFF1FB7FDC}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E19B86AC-AC42-417A-8536-C2FFF1FB7FDC}.Release|x86.Build.0 = Release|Win32
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|x86.Build.0 = Release|Any CPU
|
||||
{04AA3054-5350-4D8B-97F6-31495AE0609D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{04AA3054-5350-4D8B-97F6-31495AE0609D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{04AA3054-5350-4D8B-97F6-31495AE0609D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project ver="10" name="cmonitor.viewer.client.win" libEmbed="true" icon="C:\Users\snltty\Desktop\cmonitor\cmonitor\favicon.ico" ui="win" output="cmonitor.viewer.client.win.exe" CompanyName="snltty" FileDescription="cmonitor.viewer.client.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="cmonitor.viewer.client.win" InternalName="cmonitor.viewer.client.win" FileVersion="0.0.0.42" ProductVersion="0.0.0.42" publishDir="/dist/" dstrip="false">
|
||||
<project ver="10" name="cmonitor.viewer.client.win" libEmbed="true" icon="C:\Users\snltty\Desktop\cmonitor\cmonitor\favicon.ico" ui="win" output="cmonitor.viewer.client.win.exe" CompanyName="snltty" FileDescription="cmonitor.viewer.client.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="cmonitor.viewer.client.win" InternalName="cmonitor.viewer.client.win" FileVersion="0.0.0.43" ProductVersion="0.0.0.43" publishDir="/dist/" dstrip="false">
|
||||
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
|
||||
<folder name="资源文件" path="res" embed="true"/>
|
||||
<folder name="窗体文件" path="dlg" comment="目录" embed="true"/>
|
||||
|
||||
Binary file not shown.
@@ -51,9 +51,9 @@ mainForm.connect = function(){
|
||||
mainForm.show();
|
||||
if(!_STUDIO_INVOKED)
|
||||
{
|
||||
//mainForm.fullscreen();
|
||||
//mainForm.modifyStyleEx(0x40000/*_WS_EX_APPWINDOW*/,0x80/*_WS_EX_TOOLWINDOW*/);
|
||||
//::SetWindowPos(mainForm.hwnd,-1/*_HWND_TOPMOST*/,0,0,0,0,0x2/*_SWP_NOMOVE*/ + 0x1/*_SWP_NOSIZE*/);
|
||||
mainForm.fullscreen();
|
||||
mainForm.modifyStyleEx(0x40000/*_WS_EX_APPWINDOW*/,0x80/*_WS_EX_TOOLWINDOW*/);
|
||||
::SetWindowPos(mainForm.hwnd,-1/*_HWND_TOPMOST*/,0,0,0,0,0x2/*_SWP_NOMOVE*/ + 0x1/*_SWP_NOSIZE*/);
|
||||
}
|
||||
|
||||
mainForm.setInterval(
|
||||
|
||||
17
cmonitor.web.client/src/apis/logger.js
Normal file
17
cmonitor.web.client/src/apis/logger.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { sendWebsocketMsg } from './request'
|
||||
|
||||
export const getLogger = (data) => {
|
||||
return sendWebsocketMsg('loggerclient/get', data);
|
||||
}
|
||||
|
||||
export const clearLogger = () => {
|
||||
return sendWebsocketMsg('loggerclient/clear');
|
||||
}
|
||||
|
||||
export const getLoggerConfig = () => {
|
||||
return sendWebsocketMsg('loggerclient/getconfig');
|
||||
}
|
||||
|
||||
export const updateLoggerConfig = (data) => {
|
||||
return sendWebsocketMsg('loggerclient/setconfig', data);
|
||||
}
|
||||
@@ -87,6 +87,10 @@ a {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.m-l-1 {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
table {
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
<img src="../assets/logo.png" alt="">
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="menu">
|
||||
<ul class="flex-1">
|
||||
<div class="menu flex-1">
|
||||
<ul class="flex">
|
||||
<li>
|
||||
<router-link :to="{name:'Index'}">首页</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{name:'Logger'}">日志</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -21,7 +24,7 @@
|
||||
接口 : <el-input v-model="state.api" style="width:70%"></el-input>
|
||||
</div>
|
||||
<div class="pdt-10">
|
||||
秘钥 : <el-input type="password" v-model="state.apipsd" style="width:70%"></el-input>
|
||||
秘钥 : <el-input type="password" v-model="state.psd" style="width:70%"></el-input>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
@@ -35,44 +38,41 @@
|
||||
import { computed, onMounted, reactive, watch } from 'vue';
|
||||
import { initWebsocket, subWebsocketState } from '../apis/request'
|
||||
import { getConfig,getSignInfo } from '../apis/signin'
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { injectGlobalData } from '../provide';
|
||||
export default {
|
||||
setup() {
|
||||
|
||||
const globalData = injectGlobalData();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const queryCache = JSON.parse(localStorage.getItem('api-cache') || JSON.stringify({api:`${window.location.hostname}:1805`,psd:'snltty',groupid:'snltty'}));
|
||||
const state = reactive({
|
||||
api: route.query.api ? `${window.location.hostname}:${route.query.api}` : (localStorage.getItem('api') || `${window.location.hostname}:1805`),
|
||||
apipsd: route.query.apipsd ? `${route.query.apipsd}` : (localStorage.getItem('apipsd') || `snltty`),
|
||||
groupid: route.query.groupid ? `${route.query.groupid}` : (localStorage.getItem('groupid') || `snltty`),
|
||||
api:queryCache.api,
|
||||
psd:queryCache.psd,
|
||||
groupid: queryCache.groupid,
|
||||
showPort: false
|
||||
});
|
||||
localStorage.setItem('api', state.api);
|
||||
localStorage.setItem('apipsd', state.apipsd);
|
||||
localStorage.setItem('groupid', state.groupid);
|
||||
globalData.value.groupid = state.groupid;
|
||||
const showPort = computed(() => globalData.value.connected == false && state.showPort);
|
||||
|
||||
const handleConnect = () => {
|
||||
initWebsocket(`ws://${state.api}`,state.apipsd);
|
||||
localStorage.setItem('api', state.api);
|
||||
localStorage.setItem('apipsd', state.apipsd);
|
||||
localStorage.setItem('groupid', state.groupid);
|
||||
globalData.value.groupid = state.groupid;
|
||||
queryCache.api = state.api;
|
||||
queryCache.psd = state.psd;
|
||||
queryCache.groupid = state.groupid;
|
||||
localStorage.setItem('api-cache',JSON.stringify(queryCache));
|
||||
initWebsocket(`ws://${state.api}`,state.psd);
|
||||
}
|
||||
|
||||
const _getConfig = ()=>{
|
||||
getConfig().then((res)=>{
|
||||
console.log(res);
|
||||
globalData.value.config.Common = res.Data.Common;
|
||||
globalData.value.config.Client = res.Data.Client;
|
||||
setTimeout(()=>{
|
||||
_getConfig();
|
||||
},1000);
|
||||
}).catch((err)=>{
|
||||
console.log(err);
|
||||
setTimeout(()=>{
|
||||
_getConfig();
|
||||
},1000);
|
||||
@@ -93,11 +93,17 @@ export default {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
_getConfig();
|
||||
_getSignInfoInfo();
|
||||
handleConnect();
|
||||
setTimeout(() => { state.showPort = true; }, 100);
|
||||
subWebsocketState((state) => { if (state) globalData.value.updateFlag = Date.now(); });
|
||||
subWebsocketState((state) => { if (state) {
|
||||
_getConfig();
|
||||
_getSignInfoInfo();
|
||||
}});
|
||||
router.isReady().then(()=>{
|
||||
state.api = route.query.api ?`${window.location.hostname}:${route.query.api}` : state.api;
|
||||
state.psd = route.query.psd || state.psd;
|
||||
state.groupid = route.query.groupid || state.groupid;
|
||||
handleConnect();
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -120,7 +126,7 @@ export default {
|
||||
}
|
||||
.menu{
|
||||
padding-left:1rem;font-size:1.4rem;
|
||||
li{box-sizing:border-box;padding:.5rem 0;margin-right:.5rem}
|
||||
li{box-sizing:border-box;padding:.5rem 0;margin-right:.5rem;}
|
||||
a{
|
||||
display:block;
|
||||
color:#333;
|
||||
|
||||
@@ -3,7 +3,12 @@ const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Index',
|
||||
component: () => import('../views/Index.vue')
|
||||
component: () => import('../views/devices/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/logger.html',
|
||||
name: 'Logger',
|
||||
component: () => import('../views/logger/Index.vue')
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
<el-table-column prop="LastSignIn" label="最后登入" width="140" />
|
||||
<el-table-column label="操作">
|
||||
<template #default="scope">
|
||||
<el-dropdown>
|
||||
<el-dropdown class="m-r-1">
|
||||
<el-button size="small">
|
||||
测试<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="handleTestTunnel(scope.row.MachineName)">打洞</el-dropdown-item>
|
||||
<el-dropdown-item @click="handleTestRelay(scope.row.MachineName)">中继</el-dropdown-item>
|
||||
<el-dropdown-item @click="handleTestTunnel(scope.row.MachineName)">打洞</el-dropdown-item>
|
||||
<el-dropdown-item @click="handleTestRelay(scope.row.MachineName)">中继</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
@@ -39,7 +39,7 @@
|
||||
</el-table>
|
||||
<div class="page t-c">
|
||||
<div class="page-wrap">
|
||||
<el-pagination small background layout="prev, pager, next"
|
||||
<el-pagination small background layout="total,prev, pager, next"
|
||||
:total="state.page.Count" :page-size="state.page.Request.Size" :current-page="state.page.Request.Page"
|
||||
@current-change="handlePageChange"/>
|
||||
</div>
|
||||
@@ -51,7 +51,7 @@ import {getSignList,updateSignInDel} from '@/apis/signin.js'
|
||||
import {updateTunnelConnect} from '@/apis/tunnel.js'
|
||||
import {updateRelayConnect} from '@/apis/relay.js'
|
||||
import {subWebsocketState} from '@/apis/request.js'
|
||||
import {injectGlobalData} from '../provide.js'
|
||||
import {injectGlobalData} from '@/provide.js'
|
||||
import {reactive,onMounted, ref, nextTick, onUnmounted} from 'vue'
|
||||
export default {
|
||||
setup(props) {
|
||||
@@ -68,6 +68,7 @@ export default {
|
||||
});
|
||||
|
||||
const _getSignList = ()=>{
|
||||
state.page.Request.GroupId = globalData.value.groupid;
|
||||
getSignList(state.page.Request).then((res)=>{
|
||||
state.page.Request = res.Request;
|
||||
state.page.Count = res.Count;
|
||||
@@ -98,6 +99,7 @@ export default {
|
||||
subWebsocketState((state)=>{ if(state)_getSignList();});
|
||||
resizeTable();
|
||||
window.addEventListener('resize',resizeTable);
|
||||
_getSignList();
|
||||
});
|
||||
onUnmounted(()=>{
|
||||
window.removeEventListener('resize',resizeTable);
|
||||
178
cmonitor.web.client/src/views/logger/Index.vue
Normal file
178
cmonitor.web.client/src/views/logger/Index.vue
Normal file
@@ -0,0 +1,178 @@
|
||||
<template>
|
||||
<div class="logger-setting-wrap flex flex-column h-100" ref="wrap">
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane label="主页">
|
||||
<div class="inner">
|
||||
<div class="head flex">
|
||||
<div>
|
||||
<el-select v-model="state.type" @change="loadData" size="small" class="m-r-1" style="width: 6rem;">
|
||||
<el-option :value="-1" label="all"></el-option>
|
||||
<el-option :value="0" label="debug"></el-option>
|
||||
<el-option :value="1" label="info"></el-option>
|
||||
<el-option :value="2" label="warning"></el-option>
|
||||
<el-option :value="3" label="error"></el-option>
|
||||
<el-option :value="4" label="fatal"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button type="warning" size="small" :loading="state.loading" @click="clearData">清空</el-button>
|
||||
<el-button size="small" :loading="state.loading" @click="loadData">刷新列表</el-button>
|
||||
<span class="flex-1"></span>
|
||||
</div>
|
||||
<div class="body flex-1 relative">
|
||||
<div v-if="state.page.List.length > 0">
|
||||
<el-table border :data="state.page.List" size="small" :height="`${state.height}px`" @row-click="handleRowClick" :row-class-name="tableRowClassName">
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column prop="Type" label="类别" width="80">
|
||||
<template #default="scope">
|
||||
<span>{{state.types[scope.row.Type]}} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="Time" label="时间" width="160"></el-table-column>
|
||||
<el-table-column prop="content" label="内容"></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<el-empty v-else />
|
||||
</div>
|
||||
<div class="pages t-c">
|
||||
<div class="page-wrap">
|
||||
<el-pagination small :total="state.page.Count" v-model:currentPage="state.page.Page" :page-size="state.page.Size" @current-change="loadData" background layout="total,prev, pager, next">
|
||||
</el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="配置">
|
||||
<Setting></Setting>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive } from '@vue/reactivity'
|
||||
import { getLogger, clearLogger } from '@/apis/logger'
|
||||
import { onMounted,onUnmounted } from '@vue/runtime-core'
|
||||
import Setting from './Setting.vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import {subWebsocketState} from '@/apis/request.js'
|
||||
import { nextTick, ref } from 'vue'
|
||||
export default {
|
||||
components: { Setting },
|
||||
setup() {
|
||||
|
||||
const wrap = ref(null);
|
||||
const state = reactive({
|
||||
loading: true,
|
||||
type:-1,
|
||||
page: { Page: 1, Size: 20, Count: 0, List: [] },
|
||||
types: ['debug', 'info', 'warning', 'error', 'fatal'],
|
||||
height:0,
|
||||
})
|
||||
const loadData = () => {
|
||||
state.loading = true;
|
||||
getLogger({
|
||||
Page : state.page.Page,
|
||||
Size : state.page.Size,
|
||||
Type : state.type
|
||||
}).then((res) => {
|
||||
state.loading = false;
|
||||
res.List.map(c => {
|
||||
c.content = c.Content.substring(0, 50);
|
||||
});
|
||||
state.page = res;
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
state.loading = false;
|
||||
});
|
||||
}
|
||||
const clearData = () => {
|
||||
state.loading = true;
|
||||
clearLogger().then(() => {
|
||||
state.loading = false;
|
||||
loadData();
|
||||
}).catch(() => {
|
||||
state.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
const tableRowClassName = ({ row, rowIndex }) => {
|
||||
return `type-${row.Type}`;
|
||||
}
|
||||
const handleRowClick = (row, column, event) => {
|
||||
let css = `padding:1rem;border:1px solid #ddd; resize:none;width:39rem;box-sizing: border-box;white-space: nowrap; height:30rem;`;
|
||||
|
||||
ElMessageBox.alert(`<textarea class="scrollbar-4" style="${css}">${row.Content}</textarea>`, '内容', {
|
||||
dangerouslyUseHTMLString: true,
|
||||
});
|
||||
}
|
||||
|
||||
const resizeTable = ()=>{
|
||||
nextTick(()=>{
|
||||
state.height = wrap.value.offsetHeight - 200;
|
||||
});
|
||||
}
|
||||
onMounted(()=>{
|
||||
subWebsocketState((state)=>{ if(state)loadData();});
|
||||
resizeTable();
|
||||
window.addEventListener('resize',resizeTable);
|
||||
loadData();
|
||||
});
|
||||
onUnmounted(()=>{
|
||||
window.removeEventListener('resize',resizeTable);
|
||||
});
|
||||
|
||||
return {
|
||||
wrap,state, loadData, clearData, tableRowClassName, handleRowClick
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
.pages {
|
||||
padding: 1rem 0 0 1rem;
|
||||
}
|
||||
|
||||
.page-wrap{
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.logger-setting-wrap {
|
||||
padding: 2rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
.inner {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.head {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="stylus">
|
||||
.logger-setting-wrap {
|
||||
.el-table {
|
||||
.type-0 {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.type-1 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.type-2 {
|
||||
color: #cd9906;
|
||||
}
|
||||
|
||||
.type-3 {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.type-4 {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
138
cmonitor.web.client/src/views/logger/Setting.vue
Normal file
138
cmonitor.web.client/src/views/logger/Setting.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<el-form label-width="8rem" ref="formDom" :model="state.form" :rules="state.rules">
|
||||
<el-form-item label="" label-width="0">
|
||||
<el-row>
|
||||
<el-col :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
|
||||
<el-form-item label="显示数量" prop="Size">
|
||||
<el-input size="default" v-model="state.form.Size"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
|
||||
<el-form-item label="日志等级" prop="LoggerType">
|
||||
<el-select v-model="state.form.LoggerType">
|
||||
<el-option :value="-1" label="all"></el-option>
|
||||
<el-option :value="0" label="debug"></el-option>
|
||||
<el-option :value="1" label="info"></el-option>
|
||||
<el-option :value="2" label="warning"></el-option>
|
||||
<el-option :value="3" label="error"></el-option>
|
||||
<el-option :value="4" label="fatal"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0">
|
||||
<div class="t-c w-100">
|
||||
<el-button type="primary" :loading="state.loading" @click="submit">确 定</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive } from "@vue/reactivity";
|
||||
import { getLoggerConfig, updateLoggerConfig } from "@/apis/logger";
|
||||
import { onMounted } from "@vue/runtime-core";
|
||||
import { ElMessage } from 'element-plus';
|
||||
import {subWebsocketState} from '@/apis/request.js'
|
||||
export default {
|
||||
setup() {
|
||||
const formDom = ref(null);
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
configInfo: {},
|
||||
form: {
|
||||
Size: 0,
|
||||
LoggerType: -1,
|
||||
},
|
||||
rules: {
|
||||
Size: [
|
||||
{ required: true, message: "必填", trigger: "blur" },
|
||||
{
|
||||
type: "number",
|
||||
min: 1,
|
||||
max: 10000,
|
||||
message: "数字 1-10000",
|
||||
trigger: "blur",
|
||||
transform(value) {
|
||||
return Number(value);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const loadConfig = () => {
|
||||
getLoggerConfig()
|
||||
.then((json) => {
|
||||
console.log(json);
|
||||
state.configInfo = json;
|
||||
state.form.Size = json.Size;
|
||||
state.form.LoggerType = json.LoggerType;
|
||||
})
|
||||
.catch((msg) => { });
|
||||
};
|
||||
const getJson = () => {
|
||||
let _json = JSON.parse(JSON.stringify(state.configInfo));
|
||||
_json.Size = +state.form.Size;
|
||||
_json.LoggerType = +state.form.LoggerType;
|
||||
return _json;
|
||||
};
|
||||
const submit = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
formDom.value.validate((valid) => {
|
||||
if (valid == false) {
|
||||
reject();
|
||||
return false;
|
||||
}
|
||||
state.loading = true;
|
||||
const _json = getJson();
|
||||
updateLoggerConfig(_json).then((res) => {
|
||||
state.loading = false;
|
||||
resolve();
|
||||
if (res) {
|
||||
ElMessage.success('操作成功!');
|
||||
} else {
|
||||
ElMessage.error('操作失败!');
|
||||
}
|
||||
}).catch(() => {
|
||||
state.loading = false;
|
||||
resolve();
|
||||
})
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
subWebsocketState((state)=>{ if(state)loadConfig();});
|
||||
loadConfig();
|
||||
});
|
||||
|
||||
return {
|
||||
state,
|
||||
formDom,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.el-row {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.el-form-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.el-col {
|
||||
margin-top: 0.6rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -60,7 +60,7 @@ namespace cmonitor
|
||||
|
||||
private static void LoggerConsole()
|
||||
{
|
||||
Logger.Instance.LoggerLevel = LoggerTypes.DEBUG;
|
||||
//Logger.Instance.LoggerLevel = LoggerTypes.DEBUG;
|
||||
if (Directory.Exists("logs") == false)
|
||||
{
|
||||
Directory.CreateDirectory("logs");
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace cmonitor.client.api
|
||||
}
|
||||
Logger.Instance.Warning($"load client api:{item.Name}");
|
||||
|
||||
string path = item.Name.Replace("ApiController", "");
|
||||
string path = item.Name.Replace("ApiController", "").Replace("ApiController", "");
|
||||
foreach (MethodInfo method in item.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
|
||||
{
|
||||
string key = $"{path}/{method.Name}".ToLower();
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace cmonitor.client.tunnel
|
||||
|
||||
public void BeginReceive(TunnelReceivceCallback receiveCallback, TunnelCloseCallback closeCallback, object userToken)
|
||||
{
|
||||
if (receiveCallback != null) return;
|
||||
if (this.receiveCallback != null) return;
|
||||
|
||||
this.receiveCallback = receiveCallback;
|
||||
this.closeCallback = closeCallback;
|
||||
@@ -162,4 +162,6 @@ namespace cmonitor.client.tunnel
|
||||
Socket?.SafeClose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
610
cmonitor/client/tunnel/TunnelProxy.cs
Normal file
610
cmonitor/client/tunnel/TunnelProxy.cs
Normal file
@@ -0,0 +1,610 @@
|
||||
using common.libs;
|
||||
using common.libs.extends;
|
||||
using System.Buffers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace cmonitor.client.tunnel
|
||||
{
|
||||
public class TunnelProxy
|
||||
{
|
||||
private AsyncUserToken userToken;
|
||||
private Socket socket;
|
||||
private UdpClient udpClient;
|
||||
private readonly NumberSpace ns = new NumberSpace();
|
||||
private readonly ConcurrentDictionary<ConnectId, Socket> dic = new ConcurrentDictionary<ConnectId, Socket>();
|
||||
|
||||
public IPEndPoint LocalEndpoint => socket?.LocalEndPoint as IPEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
|
||||
|
||||
public TunnelProxy()
|
||||
{
|
||||
}
|
||||
|
||||
public void Start(int port)
|
||||
{
|
||||
try
|
||||
{
|
||||
Stop();
|
||||
|
||||
IPEndPoint localEndPoint = new IPEndPoint(NetworkHelper.IPv6Support ? IPAddress.IPv6Any : IPAddress.Any, port);
|
||||
socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
socket.IPv6Only(localEndPoint.AddressFamily, false);
|
||||
socket.ReuseBind(localEndPoint);
|
||||
socket.Listen(int.MaxValue);
|
||||
|
||||
userToken = new AsyncUserToken
|
||||
{
|
||||
Socket = socket
|
||||
};
|
||||
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs
|
||||
{
|
||||
UserToken = userToken,
|
||||
SocketFlags = SocketFlags.None,
|
||||
};
|
||||
userToken.Saea = acceptEventArg;
|
||||
|
||||
acceptEventArg.Completed += IO_Completed;
|
||||
StartAccept(acceptEventArg);
|
||||
|
||||
udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, localEndPoint.Port));
|
||||
udpClient.Client.EnableBroadcast = true;
|
||||
udpClient.Client.WindowsUdpBug();
|
||||
IAsyncResult result = udpClient.BeginReceive(ReceiveCallbackUdp, null);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Instance.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private readonly AsyncUserUdpToken asyncUserUdpToken = new AsyncUserUdpToken
|
||||
{
|
||||
Proxy = new ProxyInfo { Step = ProxyStep.Forward, ConnectId = 0 }
|
||||
};
|
||||
private async void ReceiveCallbackUdp(IAsyncResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
//System.Net.Quic.QuicListener.IsSupported
|
||||
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
|
||||
byte[] bytes = udpClient.EndReceive(result, ref endPoint);
|
||||
|
||||
asyncUserUdpToken.Proxy.Data = bytes;
|
||||
await ConnectUdp(asyncUserUdpToken);
|
||||
|
||||
result = udpClient.BeginReceive(ReceiveCallbackUdp, null);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
protected virtual async Task ConnectUdp(AsyncUserUdpToken token)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
|
||||
{
|
||||
acceptEventArg.AcceptSocket = null;
|
||||
AsyncUserToken token = (AsyncUserToken)acceptEventArg.UserToken;
|
||||
try
|
||||
{
|
||||
if (token.Socket.AcceptAsync(acceptEventArg) == false)
|
||||
{
|
||||
ProcessAccept(acceptEventArg);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
token.Clear();
|
||||
}
|
||||
}
|
||||
private void IO_Completed(object sender, SocketAsyncEventArgs e)
|
||||
{
|
||||
switch (e.LastOperation)
|
||||
{
|
||||
case SocketAsyncOperation.Accept:
|
||||
ProcessAccept(e);
|
||||
break;
|
||||
case SocketAsyncOperation.Receive:
|
||||
ProcessReceive(e);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void ProcessAccept(SocketAsyncEventArgs e)
|
||||
{
|
||||
if (e.AcceptSocket != null)
|
||||
{
|
||||
BindReceive(e);
|
||||
StartAccept(e);
|
||||
}
|
||||
}
|
||||
private void BindReceive(SocketAsyncEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||
var socket = e.AcceptSocket;
|
||||
|
||||
if (socket == null || socket.RemoteEndPoint == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
socket.KeepAlive();
|
||||
AsyncUserToken userToken = new AsyncUserToken
|
||||
{
|
||||
Socket = socket,
|
||||
Proxy = new ProxyInfo { Data = Helper.EmptyArray, Step = ProxyStep.Request, ConnectId = ns.Increment() }
|
||||
};
|
||||
|
||||
SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs
|
||||
{
|
||||
UserToken = userToken,
|
||||
SocketFlags = SocketFlags.None,
|
||||
};
|
||||
userToken.Saea = readEventArgs;
|
||||
|
||||
readEventArgs.SetBuffer(new byte[8 * 1024], 0, 8 * 1024);
|
||||
readEventArgs.Completed += IO_Completed;
|
||||
if (socket.ReceiveAsync(readEventArgs) == false)
|
||||
{
|
||||
ProcessReceive(readEventArgs);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
Logger.Instance.Error(ex);
|
||||
}
|
||||
}
|
||||
private async void ProcessReceive(SocketAsyncEventArgs e)
|
||||
{
|
||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||
try
|
||||
{
|
||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
||||
{
|
||||
int offset = e.Offset;
|
||||
int length = e.BytesTransferred;
|
||||
await ReadPacket(token, e.Buffer.AsMemory(offset, length));
|
||||
if (token.Socket.Available > 0)
|
||||
{
|
||||
while (token.Socket.Available > 0)
|
||||
{
|
||||
length = token.Socket.Receive(e.Buffer);
|
||||
if (length > 0)
|
||||
{
|
||||
await ReadPacket(token, e.Buffer.AsMemory(0, length));
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (token.Socket.Connected == false)
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (token.Socket.ReceiveAsync(e) == false)
|
||||
{
|
||||
ProcessReceive(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
Logger.Instance.Error(ex);
|
||||
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
}
|
||||
private async Task ReadPacket(AsyncUserToken token, Memory<byte> data)
|
||||
{
|
||||
if (token.Proxy.Step == ProxyStep.Request)
|
||||
{
|
||||
await Connect(token);
|
||||
if (token.Connection != null)
|
||||
{
|
||||
//发送连接请求包
|
||||
await SendToConnection(token).ConfigureAwait(false);
|
||||
|
||||
token.Proxy.Step = ProxyStep.Forward;
|
||||
token.Proxy.TargetEP = null;
|
||||
|
||||
//发送后续数据包
|
||||
token.Proxy.Data = data;
|
||||
await SendToConnection(token).ConfigureAwait(false);
|
||||
|
||||
//绑定
|
||||
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode()), token.Socket);
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
token.Proxy.Data = data;
|
||||
await SendToConnection(token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async Task Connect(AsyncUserToken token)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task SendToConnection(AsyncUserToken token)
|
||||
{
|
||||
byte[] connectData = token.Proxy.ToBytes(out int length);
|
||||
try
|
||||
{
|
||||
await token.Connection.SendAsync(connectData.AsMemory(0, length)).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
token.Proxy.Return(connectData);
|
||||
}
|
||||
}
|
||||
|
||||
protected void BindConnectionReceive(ITunnelConnection connection)
|
||||
{
|
||||
connection.BeginReceive(InputConnectionData, CloseConnection, new AsyncUserToken
|
||||
{
|
||||
Connection = connection,
|
||||
Buffer = new ReceiveDataBuffer(),
|
||||
Proxy = new ProxyInfo { }
|
||||
});
|
||||
}
|
||||
protected async Task InputConnectionData(ITunnelConnection connection, Memory<byte> memory, object userToken)
|
||||
{
|
||||
AsyncUserToken token = userToken as AsyncUserToken;
|
||||
//是一个完整的包
|
||||
if (token.Buffer.Size == 0 && memory.Length > 4)
|
||||
{
|
||||
int packageLen = memory.ToInt32();
|
||||
if (packageLen == memory.Length - 4)
|
||||
{
|
||||
token.Proxy.DeBytes(memory.Slice(0, packageLen + 4));
|
||||
await ReadConnectionPack(token).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//不是完整包
|
||||
token.Buffer.AddRange(memory);
|
||||
do
|
||||
{
|
||||
int packageLen = token.Buffer.Data.ToInt32();
|
||||
if (packageLen > token.Buffer.Size - 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
token.Proxy.DeBytes(token.Buffer.Data.Slice(0, packageLen + 4));
|
||||
await ReadConnectionPack(token).ConfigureAwait(false);
|
||||
|
||||
token.Buffer.RemoveRange(0, packageLen + 4);
|
||||
} while (token.Buffer.Size > 4);
|
||||
}
|
||||
protected async Task CloseConnection(ITunnelConnection connection, object userToken)
|
||||
{
|
||||
CloseClientSocket(userToken as AsyncUserToken);
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
private async Task ReadConnectionPack(AsyncUserToken token)
|
||||
{
|
||||
if (token.Proxy.Step == ProxyStep.Request)
|
||||
{
|
||||
await ConnectBind(token).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await SendToSocket(token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
private async Task ConnectBind(AsyncUserToken token)
|
||||
{
|
||||
Socket socket = new Socket(token.Proxy.TargetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
socket.KeepAlive();
|
||||
await socket.ConnectAsync(token.Proxy.TargetEP);
|
||||
|
||||
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode()), socket);
|
||||
|
||||
BindReceiveTarget(new AsyncUserToken
|
||||
{
|
||||
Connection = token.Connection,
|
||||
Socket = socket,
|
||||
Proxy = new ProxyInfo
|
||||
{
|
||||
ConnectId = token.Proxy.ConnectId,
|
||||
Step = ProxyStep.Forward
|
||||
}
|
||||
});
|
||||
}
|
||||
private async Task SendToSocket(AsyncUserToken token)
|
||||
{
|
||||
ConnectId connectId = new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode());
|
||||
if (dic.TryGetValue(connectId, out Socket source))
|
||||
{
|
||||
try
|
||||
{
|
||||
await source.SendAsync(token.Proxy.Data);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void IO_CompletedTarget(object sender, SocketAsyncEventArgs e)
|
||||
{
|
||||
switch (e.LastOperation)
|
||||
{
|
||||
case SocketAsyncOperation.Receive:
|
||||
ProcessReceiveTarget(e);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void BindReceiveTarget(AsyncUserToken userToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs
|
||||
{
|
||||
UserToken = userToken,
|
||||
SocketFlags = SocketFlags.None,
|
||||
};
|
||||
readEventArgs.SetBuffer(new byte[8 * 1024], 0, 8 * 1024);
|
||||
readEventArgs.Completed += IO_CompletedTarget;
|
||||
if (userToken.Socket.ReceiveAsync(readEventArgs) == false)
|
||||
{
|
||||
ProcessReceiveTarget(readEventArgs);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
Logger.Instance.Error(ex);
|
||||
}
|
||||
}
|
||||
private async void ProcessReceiveTarget(SocketAsyncEventArgs e)
|
||||
{
|
||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||
try
|
||||
{
|
||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
||||
{
|
||||
int offset = e.Offset;
|
||||
int length = e.BytesTransferred;
|
||||
|
||||
token.Proxy.Data = e.Buffer.AsMemory(offset, length);
|
||||
await SendToConnection(token).ConfigureAwait(false);
|
||||
|
||||
if (token.Socket.Available > 0)
|
||||
{
|
||||
while (token.Socket.Available > 0)
|
||||
{
|
||||
length = token.Socket.Receive(e.Buffer);
|
||||
if (length > 0)
|
||||
{
|
||||
token.Proxy.Data = e.Buffer.AsMemory(0, length);
|
||||
await SendToConnection(token).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (token.Connection.Connected == false)
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (token.Socket.ReceiveAsync(e) == false)
|
||||
{
|
||||
ProcessReceiveTarget(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
Logger.Instance.Error(ex);
|
||||
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseClientSocket(AsyncUserToken token)
|
||||
{
|
||||
if (token == null) return;
|
||||
if (token.Connection != null)
|
||||
{
|
||||
int code = token.Connection.GetHashCode();
|
||||
if (token.Connection.Connected == false)
|
||||
{
|
||||
foreach (ConnectId item in dic.Keys.Where(c => c.hashCode == code).ToList())
|
||||
{
|
||||
dic.TryRemove(item, out _);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dic.TryRemove(new ConnectId(token.Proxy.ConnectId, code), out _);
|
||||
}
|
||||
}
|
||||
token.Clear();
|
||||
}
|
||||
public void Stop()
|
||||
{
|
||||
CloseClientSocket(userToken);
|
||||
udpClient?.Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum ProxyStep : byte
|
||||
{
|
||||
Request = 1,
|
||||
Forward = 2
|
||||
}
|
||||
public record struct ConnectId
|
||||
{
|
||||
public ulong connectId;
|
||||
public int hashCode;
|
||||
|
||||
public ConnectId(ulong connectId, int hashCode)
|
||||
{
|
||||
this.connectId = connectId;
|
||||
this.hashCode = hashCode;
|
||||
}
|
||||
}
|
||||
public sealed class ProxyInfo
|
||||
{
|
||||
public ulong ConnectId { get; set; }
|
||||
public ProxyStep Step { get; set; } = ProxyStep.Request;
|
||||
public IPEndPoint TargetEP { get; set; }
|
||||
|
||||
public Memory<byte> Data { get; set; }
|
||||
|
||||
public byte[] ToBytes(out int length)
|
||||
{
|
||||
int ipLength = TargetEP == null ? 0 : (TargetEP.AddressFamily == AddressFamily.InterNetwork ? 4 : 16) + 2;
|
||||
|
||||
length = 4 + 8 + 1
|
||||
+ 1 + ipLength
|
||||
+ Data.Length;
|
||||
|
||||
byte[] bytes = ArrayPool<byte>.Shared.Rent(length);
|
||||
Memory<byte> memory = bytes.AsMemory();
|
||||
|
||||
int index = 0;
|
||||
|
||||
(length - 4).ToBytes(memory);
|
||||
index += 4;
|
||||
|
||||
|
||||
ConnectId.ToBytes(memory.Slice(index));
|
||||
index += 8;
|
||||
|
||||
bytes[index] = (byte)Step;
|
||||
index += 1;
|
||||
|
||||
bytes[index] = (byte)ipLength;
|
||||
index += 1;
|
||||
|
||||
if (ipLength > 0)
|
||||
{
|
||||
TargetEP.Address.TryWriteBytes(memory.Slice(index).Span, out int writeLength);
|
||||
index += writeLength;
|
||||
|
||||
((ushort)TargetEP.Port).ToBytes(memory.Slice(index));
|
||||
index += 2;
|
||||
}
|
||||
|
||||
Data.CopyTo(memory.Slice(index));
|
||||
|
||||
return bytes;
|
||||
|
||||
}
|
||||
|
||||
public void Return(byte[] bytes)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(bytes);
|
||||
}
|
||||
|
||||
public void DeBytes(Memory<byte> memory)
|
||||
{
|
||||
int index = 4;
|
||||
Span<byte> span = memory.Span;
|
||||
|
||||
ConnectId = memory.Slice(index).ToUInt64();
|
||||
index += 8;
|
||||
|
||||
Step = (ProxyStep)span[index];
|
||||
index += 1;
|
||||
|
||||
byte ipLength = span[index];
|
||||
index += 1;
|
||||
if (ipLength > 0)
|
||||
{
|
||||
IPAddress ip = new IPAddress(span.Slice(index, ipLength - 2));
|
||||
index += ipLength;
|
||||
ushort port = span.Slice(index - 2).ToUInt16();
|
||||
TargetEP = new IPEndPoint(ip, port);
|
||||
}
|
||||
Data = memory.Slice(index);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AsyncUserUdpToken
|
||||
{
|
||||
public UdpClient SourceSocket { get; set; }
|
||||
public Socket TargetSocket { get; set; }
|
||||
public ProxyInfo Proxy { get; set; }
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
SourceSocket?.Close();
|
||||
SourceSocket = null;
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AsyncUserToken
|
||||
{
|
||||
public Socket Socket { get; set; }
|
||||
public ITunnelConnection Connection { get; set; }
|
||||
|
||||
public ProxyInfo Proxy { get; set; }
|
||||
|
||||
public ReceiveDataBuffer Buffer { get; set; }
|
||||
|
||||
public SocketAsyncEventArgs Saea { get; set; }
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Socket?.SafeClose();
|
||||
Socket = null;
|
||||
|
||||
Buffer?.Clear();
|
||||
|
||||
Saea?.Dispose();
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,6 +90,21 @@ namespace cmonitor.config
|
||||
{
|
||||
public string[] Modes { get; set; } = new string[] { "client", "server" };
|
||||
|
||||
#if DEBUG
|
||||
private LoggerTypes loggerType { get; set; } = LoggerTypes.DEBUG;
|
||||
#else
|
||||
private LoggerTypes loggerType { get; set; } = LoggerTypes.WARNING;
|
||||
#endif
|
||||
public LoggerTypes LoggerType
|
||||
{
|
||||
get => loggerType; set
|
||||
{
|
||||
loggerType = value;
|
||||
Logger.Instance.LoggerLevel = value;
|
||||
}
|
||||
}
|
||||
public int LoggerSize { get; set; } = 100;
|
||||
|
||||
private string[] includePlugins = Array.Empty<string>();
|
||||
public string[] IncludePlugins
|
||||
{
|
||||
@@ -102,7 +117,7 @@ namespace cmonitor.config
|
||||
{
|
||||
"cmonitor.client.","cmonitor.server.","cmonitor.serializes.",
|
||||
"cmonitor.plugins.signin.", "cmonitor.plugins.watch.","cmonitor.plugins.devices.","cmonitor.plugins.report.",
|
||||
"cmonitor.plugins.share.","cmonitor.plugins.rule.","cmonitor.plugins.modes.","cmonitor.plugins.tunnel.","cmonitor.plugins.relay",
|
||||
"cmonitor.plugins.share.","cmonitor.plugins.rule.","cmonitor.plugins.modes.","cmonitor.plugins.tunnel.","cmonitor.plugins.relay.","cmonitor.plugins.logger.",
|
||||
}).Distinct().ToArray();
|
||||
}
|
||||
}
|
||||
@@ -115,7 +130,7 @@ namespace cmonitor.config
|
||||
{
|
||||
types = types.Where(c => IncludePlugins.Any(d => c.FullName.Contains(d)));
|
||||
}
|
||||
if(ExcludePlugins.Length > 0)
|
||||
if (ExcludePlugins.Length > 0)
|
||||
{
|
||||
types = types.Where(c => ExcludePlugins.Any(d => c.FullName.Contains(d) == false));
|
||||
}
|
||||
|
||||
@@ -11,9 +11,8 @@ namespace cmonitor.plugins.firewall
|
||||
|
||||
public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
|
||||
#if RELEASE
|
||||
common.libs.FireWallHelper.Write(Path.GetFileNameWithoutExtension(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName));
|
||||
common.libs.FireWallHelper.Write(Path.GetFileNameWithoutExtension(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName), "./plugins/firewall");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace cmonitor.plugins.llock.report
|
||||
if (value)
|
||||
{
|
||||
CommandHelper.Windows(string.Empty, new string[] {
|
||||
$"start cmonitor.llock.win.exe {config.Data.Client.ShareMemoryKey} {config.Data.Client.ShareMemoryCount} {config.Data.Client.ShareMemorySize} {(int)ShareMemoryIndexs.LLock}"
|
||||
$"start ./plugins/llock/cmonitor.llock.win.exe {config.Data.Client.ShareMemoryKey} {config.Data.Client.ShareMemoryCount} {config.Data.Client.ShareMemorySize} {(int)ShareMemoryIndexs.LLock}"
|
||||
},false);
|
||||
}
|
||||
}
|
||||
|
||||
95
cmonitor/plugins/logger/LoggerController.cs
Normal file
95
cmonitor/plugins/logger/LoggerController.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using common.libs.extends;
|
||||
using common.libs.api;
|
||||
using cmonitor.client.api;
|
||||
using common.libs;
|
||||
using cmonitor.config;
|
||||
|
||||
namespace cmonitor.plugins.logger
|
||||
{
|
||||
public sealed class LoggerClientApiController : IApiClientController
|
||||
{
|
||||
private readonly List<LoggerModel> loggers = new List<LoggerModel>();
|
||||
|
||||
private readonly Config config;
|
||||
public LoggerClientApiController(Config config)
|
||||
{
|
||||
this.config = config;
|
||||
Logger.Instance.OnLogger += (LoggerModel logger) =>
|
||||
{
|
||||
loggers.Add(logger);
|
||||
if (loggers.Count > config.Data.Common.LoggerSize)
|
||||
{
|
||||
loggers.RemoveAt(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public LoggerPageInfo Get(ApiControllerParamsInfo param)
|
||||
{
|
||||
LoggerPageParamInfo info = param.Content.DeJson<LoggerPageParamInfo>();
|
||||
|
||||
IEnumerable<LoggerModel> result = loggers;
|
||||
if (info.Type >= 0)
|
||||
{
|
||||
result = result.Where(c => c.Type == (LoggerTypes)info.Type);
|
||||
}
|
||||
result = result.OrderByDescending(c => c.Time);
|
||||
|
||||
return new LoggerPageInfo
|
||||
{
|
||||
Page = info.Page,
|
||||
Size = info.Size,
|
||||
Type = info.Type,
|
||||
Count = result.Count(),
|
||||
List = result.Skip((info.Page - 1) * info.Size).Take(info.Size).ToList(),
|
||||
};
|
||||
}
|
||||
public bool Clear(ApiControllerParamsInfo param)
|
||||
{
|
||||
loggers.Clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public LoggerSetParamInfo GetConfig(ApiControllerParamsInfo param)
|
||||
{
|
||||
return new LoggerSetParamInfo
|
||||
{
|
||||
LoggerType = config.Data.Common.LoggerType,
|
||||
Size = config.Data.Common.LoggerSize
|
||||
};
|
||||
}
|
||||
|
||||
public bool SetConfig(ApiControllerParamsInfo param)
|
||||
{
|
||||
LoggerSetParamInfo info = param.Content.DeJson<LoggerSetParamInfo>();
|
||||
config.Data.Common.LoggerSize = info.Size;
|
||||
config.Data.Common.LoggerType = info.LoggerType;
|
||||
config.Save();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public sealed class LoggerPageInfo
|
||||
{
|
||||
public int Page { get; set; }
|
||||
public int Size { get; set; }
|
||||
public int Type { get; set; }
|
||||
public int Count { get; set; }
|
||||
public List<LoggerModel> List { get; set; }
|
||||
}
|
||||
|
||||
public sealed class LoggerPageParamInfo
|
||||
{
|
||||
public int Page { get; set; }
|
||||
public int Size { get; set; }
|
||||
public int Type { get; set; }
|
||||
}
|
||||
|
||||
public sealed class LoggerSetParamInfo
|
||||
{
|
||||
public LoggerTypes LoggerType { get; set; }
|
||||
public int Size { get; set; }
|
||||
}
|
||||
}
|
||||
31
cmonitor/plugins/logger/LoggerStartup.cs
Normal file
31
cmonitor/plugins/logger/LoggerStartup.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using cmonitor.config;
|
||||
using cmonitor.startup;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
|
||||
namespace cmonitor.plugins.logger
|
||||
{
|
||||
public sealed class LoggerStartup : IStartup
|
||||
{
|
||||
public StartupLevel Level => StartupLevel.Top;
|
||||
|
||||
public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
serviceCollection.AddSingleton<LoggerClientApiController>();
|
||||
}
|
||||
|
||||
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
LoggerClientApiController logger = serviceProvider.GetService<LoggerClientApiController>();
|
||||
}
|
||||
|
||||
public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,11 @@ namespace cmonitor.plugins.notify.report
|
||||
{
|
||||
AppDomain.CurrentDomain.ProcessExit += (sender, e) =>
|
||||
{
|
||||
CommandHelper.Windows(string.Empty, new string[] { "taskkill /f /im \"notify.win.exe\"" }, true);
|
||||
CommandHelper.Windows(string.Empty, new string[] { "taskkill /f /im \"cmonitor.notify.win.exe\"" }, true);
|
||||
};
|
||||
Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
CommandHelper.Windows(string.Empty, new string[] { "taskkill /f /im \"notify.win.exe\"" }, true);
|
||||
CommandHelper.Windows(string.Empty, new string[] { "taskkill /f /im \"cmonitor.notify.win.exe\"" }, true);
|
||||
};
|
||||
}
|
||||
public void Update(NotifyInfo notify)
|
||||
@@ -20,7 +20,7 @@ namespace cmonitor.plugins.notify.report
|
||||
Task.Run(() =>
|
||||
{
|
||||
CommandHelper.Windows(string.Empty, new string[] {
|
||||
$"start cmonitor.notify.win.exe {notify.Speed} \"{notify.Msg}\" {notify.Star1} {notify.Star2} {notify.Star3}"
|
||||
$"start ./plugins/notify/cmonitor.notify.win.exe {notify.Speed} \"{notify.Msg}\" {notify.Star1} {notify.Star2} {notify.Star3}"
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using cmonitor.config;
|
||||
using cmonitor.plugins.relay.transport;
|
||||
using common.libs;
|
||||
using common.libs.extends;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
@@ -67,11 +68,16 @@ namespace cmonitor.plugins.relay
|
||||
TransactionId = transactionId,
|
||||
TransportName = transport.Name
|
||||
};
|
||||
Logger.Instance.Debug($"relay to {relayInfo.RemoteMachineName} {relayInfo.ToJson()}");
|
||||
ITunnelConnection connection = await transport.RelayAsync(relayInfo);
|
||||
if (connection != null)
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Instance.Error($"relay to {relayInfo.RemoteMachineName} fail,{relayInfo.ToJson()}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,10 @@ namespace cmonitor.plugins.signin.messenger
|
||||
{
|
||||
this.configDataProvider = configDataProvider;
|
||||
config = configDataProvider.Load().Result ?? new SignCacheFileInfo();
|
||||
foreach (var item in config.Clients.Values)
|
||||
{
|
||||
item.Connected = false;
|
||||
}
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using cmonitor.config;
|
||||
using cmonitor.server;
|
||||
using common.libs;
|
||||
using common.libs.extends;
|
||||
using MemoryPack;
|
||||
|
||||
namespace cmonitor.plugins.signin.messenger
|
||||
@@ -37,13 +36,16 @@ namespace cmonitor.plugins.signin.messenger
|
||||
{
|
||||
SignInListRequestInfo request = MemoryPackSerializer.Deserialize<SignInListRequestInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
|
||||
List<SignCacheInfo> list = signCaching.Get(request.GroupId);
|
||||
int count = list.Count;
|
||||
list = list.Skip((request.Page - 1) * request.Size).Take(request.Size).ToList();
|
||||
if (signCaching.Get(connection.Name, out SignCacheInfo cache))
|
||||
{
|
||||
List<SignCacheInfo> list = signCaching.Get(cache.GroupId);
|
||||
int count = list.Count;
|
||||
list = list.Skip((request.Page - 1) * request.Size).Take(request.Size).ToList();
|
||||
|
||||
SignInListResponseInfo response = new SignInListResponseInfo { Request = request, Count = count, List = list };
|
||||
SignInListResponseInfo response = new SignInListResponseInfo { Request = request, Count = count, List = list };
|
||||
|
||||
connection.Write(MemoryPackSerializer.Serialize(response));
|
||||
connection.Write(MemoryPackSerializer.Serialize(response));
|
||||
}
|
||||
}
|
||||
|
||||
[MessengerId((ushort)SignInMessengerIds.Delete)]
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace cmonitor.plugins.snatch.report
|
||||
public void StartUp(SnatchQuestionInfo snatchQuestionInfo)
|
||||
{
|
||||
CommandHelper.Windows(string.Empty, new string[] {
|
||||
$"start cmonitor.snatch.win.exe {config.Data.Client.ShareMemoryKey} {config.Data.Client.ShareMemoryCount} {config.Data.Client.ShareMemorySize} {(int)ShareMemoryIndexs.SnatchQuestion} {(int)ShareMemoryIndexs.SnatchAnswer}"
|
||||
$"start ./plugins/snatch/cmonitor.snatch.win.exe {config.Data.Client.ShareMemoryKey} {config.Data.Client.ShareMemoryCount} {config.Data.Client.ShareMemorySize} {(int)ShareMemoryIndexs.SnatchQuestion} {(int)ShareMemoryIndexs.SnatchAnswer}"
|
||||
},false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +29,6 @@ namespace cmonitor.plugins.tunnel
|
||||
TunnelTest();
|
||||
}
|
||||
|
||||
public Dictionary<string, TunnelConnectInfo> Connections(ApiControllerParamsInfo param)
|
||||
{
|
||||
return tunnelTransfer.Connections;
|
||||
}
|
||||
public void Connect(ApiControllerParamsInfo param)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
@@ -50,6 +46,10 @@ namespace cmonitor.plugins.tunnel
|
||||
}
|
||||
connection.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Instance.Error($"tunnel {param.Content} fail");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using cmonitor.config;
|
||||
using cmonitor.plugins.tunnel.compact;
|
||||
using cmonitor.plugins.tunnel.messenger;
|
||||
using cmonitor.plugins.tunnel.report;
|
||||
using cmonitor.plugins.tunnel.server;
|
||||
using cmonitor.plugins.tunnel.transport;
|
||||
using cmonitor.startup;
|
||||
@@ -19,8 +18,6 @@ namespace cmonitor.plugins.tunnel
|
||||
{
|
||||
serviceCollection.AddSingleton<TunnelApiController>();
|
||||
|
||||
serviceCollection.AddSingleton<TunnelReport>();
|
||||
|
||||
serviceCollection.AddSingleton<TunnelClientMessenger>();
|
||||
|
||||
serviceCollection.AddSingleton<CompactTransfer>();
|
||||
|
||||
@@ -10,7 +10,6 @@ using common.libs.extends;
|
||||
using MemoryPack;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
using System.Transactions;
|
||||
|
||||
namespace cmonitor.plugins.tunnel
|
||||
{
|
||||
@@ -47,7 +46,6 @@ namespace cmonitor.plugins.tunnel
|
||||
item.OnConnectBegin = OnConnectBegin;
|
||||
item.OnConnecting = OnConnecting;
|
||||
item.OnConnected = _OnConnected;
|
||||
item.OnDisConnected = OnDisConnected;
|
||||
item.OnConnectFail = OnConnectFail;
|
||||
}
|
||||
|
||||
@@ -181,82 +179,29 @@ namespace cmonitor.plugins.tunnel
|
||||
}
|
||||
|
||||
|
||||
public Dictionary<string, TunnelConnectInfo> Connections { get; } = new Dictionary<string, TunnelConnectInfo>();
|
||||
private int connectionsChangeFlag = 1;
|
||||
public bool ConnectionChanged => Interlocked.CompareExchange(ref connectionsChangeFlag, 0, 1) == 1;
|
||||
private void OnConnecting(TunnelTransportInfo tunnelTransportInfo)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
Logger.Instance.Debug($"tunnel connect [{tunnelTransportInfo.TransactionId}]->{tunnelTransportInfo.Remote.MachineName}");
|
||||
}
|
||||
CheckDic(tunnelTransportInfo.Remote.MachineName, out TunnelConnectInfo info);
|
||||
info.Status = TunnelConnectStatus.Connecting;
|
||||
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
||||
Logger.Instance.Debug($"tunnel connecting {tunnelTransportInfo.Remote.MachineName},{tunnelTransportInfo.ToJson()}");
|
||||
}
|
||||
private void OnConnectBegin(TunnelTransportInfo tunnelTransportInfo)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
Logger.Instance.Debug($"tunnel connect from {tunnelTransportInfo.Remote.MachineName}->{tunnelTransportInfo.ToJson()}");
|
||||
}
|
||||
CheckDic(tunnelTransportInfo.Remote.MachineName, out TunnelConnectInfo info);
|
||||
info.Status = TunnelConnectStatus.Connecting;
|
||||
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
||||
Logger.Instance.Debug($"tunnel connecting from {tunnelTransportInfo.Remote.MachineName},{tunnelTransportInfo.ToJson()}");
|
||||
}
|
||||
private void _OnConnected(ITunnelConnection connection)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
Logger.Instance.Debug($"tunnel connect [{connection.TransactionId}]->{connection.RemoteMachineName} success");
|
||||
}
|
||||
CheckDic(connection.RemoteMachineName, out TunnelConnectInfo info);
|
||||
info.Status = TunnelConnectStatus.Connected;
|
||||
info.Connection = connection;
|
||||
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
||||
|
||||
if (OnConnected.TryGetValue(connection.TransactionId, out Action<ITunnelConnection> _callback) == false)
|
||||
Logger.Instance.Debug($"tunnel connect {connection.RemoteMachineName} success");
|
||||
if (OnConnected.TryGetValue(connection.TransactionId, out Action<ITunnelConnection> _callback))
|
||||
{
|
||||
_callback(connection);
|
||||
}
|
||||
}
|
||||
private void OnDisConnected(ITunnelConnection connection)
|
||||
public void OnDisConnected(ITunnelConnection connection)
|
||||
{
|
||||
CheckDic(connection.RemoteMachineName, out TunnelConnectInfo info);
|
||||
info.Status = TunnelConnectStatus.None;
|
||||
info.Connection = null;
|
||||
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
||||
|
||||
}
|
||||
private void OnConnectFail(string machineName)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
Logger.Instance.Error($"tunnel connect {machineName} fail");
|
||||
}
|
||||
CheckDic(machineName, out TunnelConnectInfo info);
|
||||
info.Status = TunnelConnectStatus.None;
|
||||
info.Connection = null;
|
||||
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
||||
}
|
||||
private void CheckDic(string name, out TunnelConnectInfo info)
|
||||
{
|
||||
if (Connections.TryGetValue(name, out info) == false)
|
||||
{
|
||||
info = new TunnelConnectInfo();
|
||||
Connections[name] = info;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TunnelConnectInfo
|
||||
{
|
||||
public TunnelConnectStatus Status { get; set; }
|
||||
public ITunnelConnection Connection { get; set; }
|
||||
}
|
||||
public enum TunnelConnectStatus
|
||||
{
|
||||
None = 0,
|
||||
Connecting = 1,
|
||||
Connected = 2,
|
||||
Logger.Instance.Error($"tunnel connect {machineName} fail");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
using cmonitor.client.report;
|
||||
using static cmonitor.plugins.tunnel.TunnelTransfer;
|
||||
|
||||
namespace cmonitor.plugins.tunnel.report
|
||||
{
|
||||
public sealed class TunnelReport : IClientReport
|
||||
{
|
||||
public string Name => "Tunnel";
|
||||
|
||||
private readonly TunnelTransfer tunnelTransfer;
|
||||
private readonly TunnelReportInfo tunnelReportInfo = new TunnelReportInfo();
|
||||
public TunnelReport(TunnelTransfer tunnelTransfer)
|
||||
{
|
||||
this.tunnelTransfer = tunnelTransfer;
|
||||
}
|
||||
public object GetReports(ReportType reportType)
|
||||
{
|
||||
if (tunnelTransfer.ConnectionChanged)
|
||||
{
|
||||
tunnelReportInfo.Connections = tunnelTransfer.Connections;
|
||||
return tunnelReportInfo;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public sealed class TunnelReportInfo
|
||||
{
|
||||
public Dictionary<string, TunnelConnectInfo> Connections { get; set; } = new Dictionary<string, TunnelConnectInfo>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,10 +26,6 @@ namespace cmonitor.plugins.tunnel.transport
|
||||
/// 收到连接
|
||||
/// </summary>
|
||||
public Action<ITunnelConnection> OnConnected { get; set; }
|
||||
/// <summary>
|
||||
/// 断开连接
|
||||
/// </summary>
|
||||
public Action<ITunnelConnection> OnDisConnected { get; set; }
|
||||
|
||||
public Action<string> OnConnectFail { get; set; }
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace cmonitor.plugins.tunnel.transport
|
||||
public Action<TunnelTransportInfo> OnConnectBegin { get; set; } = (info) => { };
|
||||
public Action<TunnelTransportInfo> OnConnecting { get; set; }
|
||||
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
|
||||
public Action<ITunnelConnection> OnDisConnected { get; set; } = (state) => { };
|
||||
public Action<string> OnConnectFail { get; set; } = (machineName) => { };
|
||||
|
||||
|
||||
|
||||
29
cmonitor/plugins/tuntap/TuntapStartup.cs
Normal file
29
cmonitor/plugins/tuntap/TuntapStartup.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using cmonitor.config;
|
||||
using cmonitor.startup;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
|
||||
namespace cmonitor.plugins.viewer
|
||||
{
|
||||
public sealed class TuntapStartup : IStartup
|
||||
{
|
||||
public StartupLevel Level => StartupLevel.Normal;
|
||||
|
||||
public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
}
|
||||
|
||||
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
}
|
||||
|
||||
public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace cmonitor.plugins.viewer
|
||||
serviceCollection.AddSingleton<ViewerClientMessenger>();
|
||||
|
||||
|
||||
serviceCollection.AddSingleton<ViewerProxyClient>();
|
||||
serviceCollection.AddSingleton<ViewerProxy>();
|
||||
}
|
||||
|
||||
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
@@ -37,7 +37,7 @@ namespace cmonitor.plugins.viewer
|
||||
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
Logger.Instance.Info($"use viewer proxy server in client mode.");
|
||||
ViewerProxyClient viewerProxyServer = serviceProvider.GetService<ViewerProxyClient>();
|
||||
ViewerProxy viewerProxyServer = serviceProvider.GetService<ViewerProxy>();
|
||||
viewerProxyServer.Start(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,612 +1,52 @@
|
||||
using cmonitor.client.tunnel;
|
||||
using cmonitor.client.running;
|
||||
using cmonitor.client.tunnel;
|
||||
using cmonitor.config;
|
||||
using cmonitor.plugins.relay;
|
||||
using cmonitor.plugins.tunnel;
|
||||
using common.libs;
|
||||
using common.libs.extends;
|
||||
using System.Buffers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace cmonitor.plugins.viewer.proxy
|
||||
{
|
||||
public class ViewerProxy
|
||||
public sealed class ViewerProxy : TunnelProxy
|
||||
{
|
||||
private AsyncUserToken userToken;
|
||||
private Socket socket;
|
||||
private UdpClient udpClient;
|
||||
private readonly NumberSpace ns = new NumberSpace();
|
||||
private readonly ConcurrentDictionary<ConnectId, Socket> dic = new ConcurrentDictionary<ConnectId, Socket>();
|
||||
private readonly RunningConfig runningConfig;
|
||||
private readonly TunnelTransfer tunnelTransfer;
|
||||
private readonly RelayTransfer relayTransfer;
|
||||
private readonly Config config;
|
||||
|
||||
public IPEndPoint LocalEndpoint => socket?.LocalEndPoint as IPEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
|
||||
private ITunnelConnection connection;
|
||||
|
||||
public ViewerProxy()
|
||||
public ViewerProxy(RunningConfig runningConfig, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, Config config)
|
||||
{
|
||||
this.runningConfig = runningConfig;
|
||||
this.tunnelTransfer = tunnelTransfer;
|
||||
this.relayTransfer = relayTransfer;
|
||||
this.config = config;
|
||||
|
||||
Start(0);
|
||||
Logger.Instance.Info($"start viewer proxy, port : {LocalEndpoint.Port}");
|
||||
|
||||
tunnelTransfer.SetConnectCallback("viewer", BindConnectionReceive);
|
||||
relayTransfer.SetConnectCallback("viewer", BindConnectionReceive);
|
||||
}
|
||||
|
||||
public void Start(int port)
|
||||
protected override async Task Connect(AsyncUserToken token)
|
||||
{
|
||||
try
|
||||
token.Proxy.TargetEP = runningConfig.Data.Viewer.ConnectEP;
|
||||
token.Connection = connection;
|
||||
if (connection == null || connection.Connected == false)
|
||||
{
|
||||
Stop();
|
||||
|
||||
IPEndPoint localEndPoint = new IPEndPoint(NetworkHelper.IPv6Support ? IPAddress.IPv6Any : IPAddress.Any, port);
|
||||
socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
socket.IPv6Only(localEndPoint.AddressFamily, false);
|
||||
socket.ReuseBind(localEndPoint);
|
||||
socket.Listen(int.MaxValue);
|
||||
|
||||
userToken = new AsyncUserToken
|
||||
connection = await tunnelTransfer.ConnectAsync(runningConfig.Data.Viewer.ServerMachine, "viewer");
|
||||
if (connection == null)
|
||||
{
|
||||
Socket = socket
|
||||
};
|
||||
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs
|
||||
connection = await relayTransfer.ConnectAsync(runningConfig.Data.Viewer.ServerMachine, "viewer", config.Data.Client.Relay.SecretKey);
|
||||
}
|
||||
if (connection != null)
|
||||
{
|
||||
UserToken = userToken,
|
||||
SocketFlags = SocketFlags.None,
|
||||
};
|
||||
userToken.Saea = acceptEventArg;
|
||||
|
||||
acceptEventArg.Completed += IO_Completed;
|
||||
StartAccept(acceptEventArg);
|
||||
|
||||
udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, localEndPoint.Port));
|
||||
udpClient.Client.EnableBroadcast = true;
|
||||
udpClient.Client.WindowsUdpBug();
|
||||
IAsyncResult result = udpClient.BeginReceive(ReceiveCallbackUdp, null);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Instance.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private readonly AsyncUserUdpToken asyncUserUdpToken = new AsyncUserUdpToken
|
||||
{
|
||||
Proxy = new ProxyInfo { Step = ProxyStep.Forward, ConnectId = 0 }
|
||||
};
|
||||
private async void ReceiveCallbackUdp(IAsyncResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
//System.Net.Quic.QuicListener.IsSupported
|
||||
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
|
||||
byte[] bytes = udpClient.EndReceive(result, ref endPoint);
|
||||
|
||||
asyncUserUdpToken.Proxy.Data = bytes;
|
||||
await ConnectUdp(asyncUserUdpToken);
|
||||
|
||||
result = udpClient.BeginReceive(ReceiveCallbackUdp, null);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
protected virtual async Task ConnectUdp(AsyncUserUdpToken token)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
|
||||
{
|
||||
acceptEventArg.AcceptSocket = null;
|
||||
AsyncUserToken token = (AsyncUserToken)acceptEventArg.UserToken;
|
||||
try
|
||||
{
|
||||
if (token.Socket.AcceptAsync(acceptEventArg) == false)
|
||||
{
|
||||
ProcessAccept(acceptEventArg);
|
||||
BindConnectionReceive(connection);
|
||||
token.Connection = connection;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
token.Clear();
|
||||
}
|
||||
}
|
||||
private void IO_Completed(object sender, SocketAsyncEventArgs e)
|
||||
{
|
||||
switch (e.LastOperation)
|
||||
{
|
||||
case SocketAsyncOperation.Accept:
|
||||
ProcessAccept(e);
|
||||
break;
|
||||
case SocketAsyncOperation.Receive:
|
||||
ProcessReceive(e);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void ProcessAccept(SocketAsyncEventArgs e)
|
||||
{
|
||||
if (e.AcceptSocket != null)
|
||||
{
|
||||
BindReceive(e);
|
||||
StartAccept(e);
|
||||
}
|
||||
}
|
||||
private void BindReceive(SocketAsyncEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||
var socket = e.AcceptSocket;
|
||||
|
||||
if (socket == null || socket.RemoteEndPoint == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
socket.KeepAlive();
|
||||
AsyncUserToken userToken = new AsyncUserToken
|
||||
{
|
||||
Socket = socket,
|
||||
Proxy = new ProxyInfo { Data = Helper.EmptyArray, Step = ProxyStep.Request, ConnectId = ns.Increment() }
|
||||
};
|
||||
|
||||
SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs
|
||||
{
|
||||
UserToken = userToken,
|
||||
SocketFlags = SocketFlags.None,
|
||||
};
|
||||
userToken.Saea = readEventArgs;
|
||||
|
||||
readEventArgs.SetBuffer(new byte[8 * 1024], 0, 8 * 1024);
|
||||
readEventArgs.Completed += IO_Completed;
|
||||
if (socket.ReceiveAsync(readEventArgs) == false)
|
||||
{
|
||||
ProcessReceive(readEventArgs);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
Logger.Instance.Error(ex);
|
||||
}
|
||||
}
|
||||
private async void ProcessReceive(SocketAsyncEventArgs e)
|
||||
{
|
||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||
try
|
||||
{
|
||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
||||
{
|
||||
int offset = e.Offset;
|
||||
int length = e.BytesTransferred;
|
||||
await ReadPacket(token, e.Buffer.AsMemory(offset, length));
|
||||
if (token.Socket.Available > 0)
|
||||
{
|
||||
while (token.Socket.Available > 0)
|
||||
{
|
||||
length = token.Socket.Receive(e.Buffer);
|
||||
if (length > 0)
|
||||
{
|
||||
await ReadPacket(token, e.Buffer.AsMemory(0, length));
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (token.Socket.Connected == false)
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (token.Socket.ReceiveAsync(e) == false)
|
||||
{
|
||||
ProcessReceive(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
Logger.Instance.Error(ex);
|
||||
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
}
|
||||
private async Task ReadPacket(AsyncUserToken token, Memory<byte> data)
|
||||
{
|
||||
if (token.Proxy.Step == ProxyStep.Request)
|
||||
{
|
||||
await Connect(token);
|
||||
if (token.Connection != null)
|
||||
{
|
||||
//发送连接请求包
|
||||
await SendToConnection(token).ConfigureAwait(false);
|
||||
|
||||
token.Proxy.Step = ProxyStep.Forward;
|
||||
token.Proxy.TargetEP = null;
|
||||
|
||||
//发送后续数据包
|
||||
token.Proxy.Data = data;
|
||||
await SendToConnection(token).ConfigureAwait(false);
|
||||
|
||||
//绑定
|
||||
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode()), token.Socket);
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
token.Proxy.Data = data;
|
||||
await SendToConnection(token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async Task Connect(AsyncUserToken token)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task SendToConnection(AsyncUserToken token)
|
||||
{
|
||||
byte[] connectData = token.Proxy.ToBytes(out int length);
|
||||
try
|
||||
{
|
||||
await token.Connection.SendAsync(connectData.AsMemory(0, length)).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
token.Proxy.Return(connectData);
|
||||
}
|
||||
}
|
||||
|
||||
protected void BindConnectionReceive(ITunnelConnection connection)
|
||||
{
|
||||
connection.BeginReceive(InputConnectionData, CloseConnection, new AsyncUserToken
|
||||
{
|
||||
Connection = connection,
|
||||
Buffer = new ReceiveDataBuffer(),
|
||||
Proxy = new ProxyInfo { }
|
||||
});
|
||||
}
|
||||
protected async Task InputConnectionData(ITunnelConnection connection, Memory<byte> memory, object userToken)
|
||||
{
|
||||
AsyncUserToken token = userToken as AsyncUserToken;
|
||||
//是一个完整的包
|
||||
if (token.Buffer.Size == 0 && memory.Length > 4)
|
||||
{
|
||||
int packageLen = memory.ToInt32();
|
||||
if (packageLen == memory.Length - 4)
|
||||
{
|
||||
token.Proxy.DeBytes(memory.Slice(0, packageLen + 4));
|
||||
await ReadConnectionPack(token).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//不是完整包
|
||||
token.Buffer.AddRange(memory);
|
||||
do
|
||||
{
|
||||
int packageLen = token.Buffer.Data.ToInt32();
|
||||
if (packageLen > token.Buffer.Size - 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
token.Proxy.DeBytes(token.Buffer.Data.Slice(0, packageLen + 4));
|
||||
await ReadConnectionPack(token).ConfigureAwait(false);
|
||||
|
||||
token.Buffer.RemoveRange(0, packageLen + 4);
|
||||
} while (token.Buffer.Size > 4);
|
||||
}
|
||||
protected async Task CloseConnection(ITunnelConnection connection, object userToken)
|
||||
{
|
||||
CloseClientSocket(userToken as AsyncUserToken);
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
private async Task ReadConnectionPack(AsyncUserToken token)
|
||||
{
|
||||
if (token.Proxy.Step == ProxyStep.Request)
|
||||
{
|
||||
await ConnectBind(token).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await SendToSocket(token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
private async Task ConnectBind(AsyncUserToken token)
|
||||
{
|
||||
Socket socket = new Socket(token.Proxy.TargetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
socket.KeepAlive();
|
||||
await socket.ConnectAsync(token.Proxy.TargetEP);
|
||||
|
||||
dic.TryAdd(new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode()), socket);
|
||||
|
||||
BindReceiveTarget(new AsyncUserToken
|
||||
{
|
||||
Connection = token.Connection,
|
||||
Socket = socket,
|
||||
Proxy = new ProxyInfo
|
||||
{
|
||||
ConnectId = token.Proxy.ConnectId,
|
||||
Step = ProxyStep.Forward
|
||||
}
|
||||
});
|
||||
}
|
||||
private async Task SendToSocket(AsyncUserToken token)
|
||||
{
|
||||
ConnectId connectId = new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode());
|
||||
if (dic.TryGetValue(connectId, out Socket source))
|
||||
{
|
||||
try
|
||||
{
|
||||
await source.SendAsync(token.Proxy.Data);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void IO_CompletedTarget(object sender, SocketAsyncEventArgs e)
|
||||
{
|
||||
switch (e.LastOperation)
|
||||
{
|
||||
case SocketAsyncOperation.Receive:
|
||||
ProcessReceiveTarget(e);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void BindReceiveTarget(AsyncUserToken userToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs
|
||||
{
|
||||
UserToken = userToken,
|
||||
SocketFlags = SocketFlags.None,
|
||||
};
|
||||
readEventArgs.SetBuffer(new byte[8 * 1024], 0, 8 * 1024);
|
||||
readEventArgs.Completed += IO_CompletedTarget;
|
||||
if (userToken.Socket.ReceiveAsync(readEventArgs) == false)
|
||||
{
|
||||
ProcessReceiveTarget(readEventArgs);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
Logger.Instance.Error(ex);
|
||||
}
|
||||
}
|
||||
private async void ProcessReceiveTarget(SocketAsyncEventArgs e)
|
||||
{
|
||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||
try
|
||||
{
|
||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
||||
{
|
||||
int offset = e.Offset;
|
||||
int length = e.BytesTransferred;
|
||||
|
||||
token.Proxy.Data = e.Buffer.AsMemory(offset, length);
|
||||
await SendToConnection(token).ConfigureAwait(false);
|
||||
|
||||
if (token.Socket.Available > 0)
|
||||
{
|
||||
while (token.Socket.Available > 0)
|
||||
{
|
||||
length = token.Socket.Receive(e.Buffer);
|
||||
if (length > 0)
|
||||
{
|
||||
token.Proxy.Data = e.Buffer.AsMemory(0, length);
|
||||
await SendToConnection(token).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (token.Connection.Connected == false)
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (token.Socket.ReceiveAsync(e) == false)
|
||||
{
|
||||
ProcessReceiveTarget(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
Logger.Instance.Error(ex);
|
||||
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CloseClientSocket(AsyncUserToken token)
|
||||
{
|
||||
if (token.Connection != null)
|
||||
{
|
||||
int code = token.Connection.GetHashCode();
|
||||
if (token.Connection.Connected == false)
|
||||
{
|
||||
foreach (ConnectId item in dic.Keys.Where(c => c.hashCode == code).ToList())
|
||||
{
|
||||
dic.TryRemove(item, out _);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dic.TryRemove(new ConnectId(token.Proxy.ConnectId, code), out _);
|
||||
}
|
||||
}
|
||||
token.Clear();
|
||||
}
|
||||
public void Stop()
|
||||
{
|
||||
CloseClientSocket(userToken);
|
||||
udpClient?.Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum ProxyStep : byte
|
||||
{
|
||||
Request = 1,
|
||||
Forward = 2
|
||||
}
|
||||
public record struct ConnectId
|
||||
{
|
||||
public ulong connectId;
|
||||
public int hashCode;
|
||||
|
||||
public ConnectId(ulong connectId, int hashCode)
|
||||
{
|
||||
this.connectId = connectId;
|
||||
this.hashCode = hashCode;
|
||||
}
|
||||
}
|
||||
public sealed class ProxyInfo
|
||||
{
|
||||
public ulong ConnectId { get; set; }
|
||||
public ProxyStep Step { get; set; } = ProxyStep.Request;
|
||||
public IPEndPoint TargetEP { get; set; }
|
||||
|
||||
public Memory<byte> Data { get; set; }
|
||||
|
||||
public byte[] ToBytes(out int length)
|
||||
{
|
||||
int ipLength = TargetEP == null ? 0 : (TargetEP.AddressFamily == AddressFamily.InterNetwork ? 4 : 16) + 2;
|
||||
|
||||
length = 4 + 8 + 1
|
||||
+ 1 + ipLength
|
||||
+ Data.Length;
|
||||
|
||||
byte[] bytes = ArrayPool<byte>.Shared.Rent(length);
|
||||
Memory<byte> memory = bytes.AsMemory();
|
||||
|
||||
int index = 0;
|
||||
|
||||
(length - 4).ToBytes(memory);
|
||||
index += 4;
|
||||
|
||||
|
||||
ConnectId.ToBytes(memory.Slice(index));
|
||||
index += 8;
|
||||
|
||||
bytes[index] = (byte)Step;
|
||||
index += 1;
|
||||
|
||||
bytes[index] = (byte)ipLength;
|
||||
index += 1;
|
||||
|
||||
if (ipLength > 0)
|
||||
{
|
||||
TargetEP.Address.TryWriteBytes(memory.Slice(index).Span, out int writeLength);
|
||||
index += writeLength;
|
||||
|
||||
((ushort)TargetEP.Port).ToBytes(memory.Slice(index));
|
||||
index += 2;
|
||||
}
|
||||
|
||||
Data.CopyTo(memory.Slice(index));
|
||||
|
||||
return bytes;
|
||||
|
||||
}
|
||||
|
||||
public void Return(byte[] bytes)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(bytes);
|
||||
}
|
||||
|
||||
public void DeBytes(Memory<byte> memory)
|
||||
{
|
||||
int index = 4;
|
||||
Span<byte> span = memory.Span;
|
||||
|
||||
ConnectId = memory.Slice(index).ToUInt64();
|
||||
index += 8;
|
||||
|
||||
Step = (ProxyStep)span[index];
|
||||
index += 1;
|
||||
|
||||
byte ipLength = span[index];
|
||||
index += 1;
|
||||
if (ipLength > 0)
|
||||
{
|
||||
IPAddress ip = new IPAddress(span.Slice(index, ipLength - 2));
|
||||
index += ipLength;
|
||||
ushort port = span.Slice(index - 2).ToUInt16();
|
||||
TargetEP = new IPEndPoint(ip, port);
|
||||
}
|
||||
Data = memory.Slice(index);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AsyncUserUdpToken
|
||||
{
|
||||
public UdpClient SourceSocket { get; set; }
|
||||
public Socket TargetSocket { get; set; }
|
||||
public ProxyInfo Proxy { get; set; }
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
SourceSocket?.Close();
|
||||
SourceSocket = null;
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AsyncUserToken
|
||||
{
|
||||
public Socket Socket { get; set; }
|
||||
public ITunnelConnection Connection { get; set; }
|
||||
|
||||
public ProxyInfo Proxy { get; set; }
|
||||
|
||||
public ReceiveDataBuffer Buffer { get; set; }
|
||||
|
||||
public SocketAsyncEventArgs Saea { get; set; }
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Socket?.SafeClose();
|
||||
Socket = null;
|
||||
|
||||
Buffer?.Clear();
|
||||
|
||||
Saea?.Dispose();
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
using cmonitor.client.running;
|
||||
using cmonitor.client.tunnel;
|
||||
using cmonitor.config;
|
||||
using cmonitor.plugins.relay;
|
||||
using cmonitor.plugins.tunnel;
|
||||
using common.libs;
|
||||
|
||||
namespace cmonitor.plugins.viewer.proxy
|
||||
{
|
||||
public sealed class ViewerProxyClient : ViewerProxy
|
||||
{
|
||||
private readonly RunningConfig runningConfig;
|
||||
private readonly TunnelTransfer tunnelTransfer;
|
||||
private readonly RelayTransfer relayTransfer;
|
||||
private readonly Config config;
|
||||
|
||||
private ITunnelConnection connection;
|
||||
|
||||
public ViewerProxyClient(RunningConfig runningConfig, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, Config config)
|
||||
{
|
||||
this.runningConfig = runningConfig;
|
||||
this.tunnelTransfer = tunnelTransfer;
|
||||
this.relayTransfer = relayTransfer;
|
||||
this.config = config;
|
||||
|
||||
Start(0);
|
||||
Logger.Instance.Info($"start viewer proxy, port : {LocalEndpoint.Port}");
|
||||
|
||||
tunnelTransfer.SetConnectCallback("viewer", BindConnectionReceive);
|
||||
relayTransfer.SetConnectCallback("viewer", BindConnectionReceive);
|
||||
}
|
||||
|
||||
protected override async Task Connect(AsyncUserToken token)
|
||||
{
|
||||
token.Proxy.TargetEP = runningConfig.Data.Viewer.ConnectEP;
|
||||
token.Connection = connection;
|
||||
if (connection == null || connection.Connected == false)
|
||||
{
|
||||
connection = await tunnelTransfer.ConnectAsync(runningConfig.Data.Viewer.ServerMachine, "viewer");
|
||||
if (connection == null)
|
||||
{
|
||||
connection = await relayTransfer.ConnectAsync(runningConfig.Data.Viewer.ServerMachine, "viewer", config.Data.Client.Relay.SecretKey);
|
||||
}
|
||||
if (connection != null)
|
||||
{
|
||||
BindConnectionReceive(connection);
|
||||
token.Connection = connection;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,9 @@ namespace cmonitor.plugins.viewer.report
|
||||
private readonly MessengerSender messengerSender;
|
||||
private readonly ClientSignInState clientSignInState;
|
||||
private readonly Config config;
|
||||
private readonly ViewerProxyClient viewerProxyClient;
|
||||
private readonly ViewerProxy viewerProxyClient;
|
||||
|
||||
public ViewerReport(Config config, RunningConfig runningConfig, IViewer viewer, ShareMemory shareMemory, ClientSignInState clientSignInState, MessengerSender messengerSender, ViewerProxyClient viewerProxyClient)
|
||||
public ViewerReport(Config config, RunningConfig runningConfig, IViewer viewer, ShareMemory shareMemory, ClientSignInState clientSignInState, MessengerSender messengerSender, ViewerProxy viewerProxyClient)
|
||||
{
|
||||
this.config = config;
|
||||
this.runningConfig = runningConfig;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace cmonitor.plugins.wallpaper.report
|
||||
if (info.Open)
|
||||
{
|
||||
CommandHelper.Windows(string.Empty, new string[] {
|
||||
$"start cmonitor.wallpaper.win.exe \"{info.ImgUrl}\" {config.Data.Client.ShareMemoryKey} {config.Data.Client.ShareMemoryCount} {config.Data.Client.ShareMemorySize} {(int)ShareMemoryIndexs.Keyboard} {(int)ShareMemoryIndexs.Wallpaper}"
|
||||
$"start ./plugins/wallpaper/cmonitor.wallpaper.win.exe \"{info.ImgUrl}\" {config.Data.Client.ShareMemoryKey} {config.Data.Client.ShareMemoryCount} {config.Data.Client.ShareMemorySize} {(int)ShareMemoryIndexs.Keyboard} {(int)ShareMemoryIndexs.Wallpaper}"
|
||||
},false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using cmonitor.client.report;
|
||||
using cmonitor.config;
|
||||
using common.libs;
|
||||
|
||||
namespace cmonitor.plugins.watch.report
|
||||
{
|
||||
@@ -12,6 +13,7 @@ namespace cmonitor.plugins.watch.report
|
||||
#if RELEASE
|
||||
OpenFiles();
|
||||
#endif
|
||||
OpenFiles();
|
||||
}
|
||||
|
||||
public object GetReports(ReportType reportType)
|
||||
@@ -27,11 +29,32 @@ namespace cmonitor.plugins.watch.report
|
||||
try
|
||||
{
|
||||
fss.Add(new FileStream(item, FileMode.Open, FileAccess.Read, FileShare.Read));
|
||||
Logger.Instance.Warning($"watch file {item}");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
OpenFiles("./plugins");
|
||||
}
|
||||
|
||||
private void OpenFiles(string path)
|
||||
{
|
||||
foreach (var item in Directory.GetFiles(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
fss.Add(new FileStream(item, FileMode.Open, FileAccess.Read, FileShare.Read));
|
||||
Logger.Instance.Warning($"watch file {item}");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
foreach (var item in Directory.GetDirectories(path))
|
||||
{
|
||||
OpenFiles(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace common.libs
|
||||
{
|
||||
public static class FireWallHelper
|
||||
{
|
||||
public static void Write(string fileName)
|
||||
public static void Write(string fileName, string distPatt)
|
||||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
Windows(fileName);
|
||||
Windows(fileName, distPatt);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux())
|
||||
{
|
||||
@@ -29,7 +30,7 @@ namespace common.libs
|
||||
});
|
||||
}
|
||||
|
||||
private static void Windows(string fileName)
|
||||
private static void Windows(string fileName,string distPatth)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -51,9 +52,15 @@ cmd /c netsh advfirewall firewall add rule name=""{fileName}"" dir=in action=all
|
||||
cmd /c netsh advfirewall firewall add rule name=""{fileName}"" dir=in action=allow program=""%CD%\{fileName}.exe"" protocol=tcp enable=yes profile=private
|
||||
cmd /c netsh advfirewall firewall add rule name=""{fileName}"" dir=in action=allow program=""%CD%\{fileName}.exe"" protocol=udp enable=yes profile=private
|
||||
:end";
|
||||
System.IO.File.WriteAllText("firewall.bat", content);
|
||||
CommandHelper.Execute("firewall.bat", string.Empty, new string[0]);
|
||||
System.IO.File.Delete("firewall.bat");
|
||||
if(Directory.Exists(distPatth) == false)
|
||||
{
|
||||
Directory.CreateDirectory(distPatth);
|
||||
}
|
||||
string firewall = Path.Join(distPatth, "firewall.bat");
|
||||
|
||||
System.IO.File.WriteAllText(firewall, content);
|
||||
CommandHelper.Execute(firewall, string.Empty, new string[0]);
|
||||
System.IO.File.Delete(firewall);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
@@ -14,10 +14,10 @@ cd ../
|
||||
|
||||
dotnet publish ./cmonitor.sas.service -c release -f net8.0 -o public/extends/ -r win-x64 -p:PublishTrimmed=true -p:TrimMode=partial --self-contained true -p:TieredPGO=true -p:DebugType=none -p:DebugSymbols=false -p:PublishSingleFile=true -p:EnableCompressionInSingleFile=true -p:DebuggerSupport=false -p:EnableUnsafeBinaryFormatterSerialization=false -p:EnableUnsafeUTF7Encoding=false -p:HttpActivityPropagationSupport=false -p:InvariantGlobalization=true -p:MetadataUpdaterSupport=false -p:UseSystemResourceKeys=true
|
||||
dotnet publish ./cmonitor.install.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
|
||||
dotnet publish ./cmonitor.snatch.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
|
||||
dotnet publish ./cmonitor.llock.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
|
||||
dotnet publish ./cmonitor.message.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
|
||||
dotnet publish ./cmonitor.notify.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
|
||||
dotnet publish ./cmonitor.wallpaper.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
|
||||
dotnet publish ./cmonitor.snatch.win -c release -f net8.0-windows -r win-x64 -o public/extends/plugins/snatch -p:PublishSingleFile=true --self-contained false
|
||||
dotnet publish ./cmonitor.llock.win -c release -f net8.0-windows -r win-x64 -o public/extends/plugins/llock -p:PublishSingleFile=true --self-contained false
|
||||
dotnet publish ./cmonitor.message.win -c release -f net8.0-windows -r win-x64 -o public/extends/plugins/message -p:PublishSingleFile=true --self-contained false
|
||||
dotnet publish ./cmonitor.notify.win -c release -f net8.0-windows -r win-x64 -o public/extends/plugins/notify -p:PublishSingleFile=true --self-contained false
|
||||
dotnet publish ./cmonitor.wallpaper.win -c release -f net8.0-windows -r win-x64 -o public/extends/plugins/wallpaper -p:PublishSingleFile=true --self-contained false
|
||||
dotnet restore ./cmonitor.viewer.server.win
|
||||
MSBuild.exe ./cmonitor.viewer.server.win /t:Publish /p:Configuration=Release /p:TargetFramework=net8.0-windows /p:PublishSingleFile=true /p:RuntimeIdentifier=win-x64 /p:PublishDir=../public/extends/
|
||||
MSBuild.exe ./cmonitor.viewer.server.win /t:Publish /p:Configuration=Release /p:TargetFramework=net8.0-windows /p:PublishSingleFile=true /p:RuntimeIdentifier=win-x64 /p:PublishDir=../public/extends/plugins/viewer
|
||||
@@ -15,7 +15,7 @@ dotnet publish ./cmonitor -c release -f net8.0 -r linux-x64 -o ./public/publish/
|
||||
|
||||
for %%r in (win-x64,win-x64-any) do (
|
||||
echo F|xcopy "public\\extends\\*" "public\\publish\\%%r\\*" /s /f /h /y
|
||||
echo F|xcopy "cmonitor.viewer.client.win\\dist\\*" "public\\publish\\%%r\\*" /s /f /h /y
|
||||
echo F|xcopy "cmonitor.viewer.client.win\\dist\\*" "public\\publish\\%%r\\plugins\\viewer\\*" /s /f /h /y
|
||||
)
|
||||
|
||||
for %%r in (linux-x64,linux-x64-any) do (
|
||||
|
||||
Reference in New Issue
Block a user