mirror of
				https://github.com/snltty/linker.git
				synced 2025-10-31 20:43:00 +08:00 
			
		
		
		
	给桌面共享增加代理功能
This commit is contained in:
		
							
								
								
									
										59
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								README.md
									
									
									
									
									
								
							| @@ -28,17 +28,17 @@ | ||||
| 1. 这是一个粗略的局域网监控程序(说是局域网,你放外网也不是不行) | ||||
| 2. 使用组件式,非常方便扩展,可由 **内存共享(MemoryMappedFiles)** 提供自己定义数据 | ||||
| 3. 内存占用小,(非定时,自动GC),linux无解 | ||||
| 4. 使用 **MemoryPack**、**SharpDX**、**NAudio** | ||||
| 1.  | ||||
| 4. 使用 **MemoryPack**、**SharpDX**、**NAudio**、**RdpSession+RdpViewer** | ||||
| 5.  | ||||
| <p><img src="./readme/size.jpg"></p>  | ||||
|  | ||||
| ## 功能 | ||||
| ###### 系统 | ||||
| - [x] 桌面捕获,捕获鼠标,**sharpDX** | ||||
| - [x] 桌面捕获,捕获鼠标,**screen** | ||||
|     - [x] 登录界面捕获和登录页面键盘输入 | ||||
|     - [x] 双指画面缩放 | ||||
|     - [ ] 区域热更新 | ||||
| - [x] 功能禁用,禁用各种系统功能 **regedit** **第一次成功连接服务端后自动恢复限制** | ||||
| - [x] 功能禁用,禁用各种系统功能 **system** | ||||
|     - 任务栏锁定,任务栏设置,任务栏菜单 | ||||
|     - 任务管理器 | ||||
|     - 注册表编辑,组策略编辑 | ||||
| @@ -49,35 +49,36 @@ | ||||
|     - 关机按钮,注销按钮,锁定按钮,修改密码,切换用户 | ||||
|     - 安全SAS | ||||
|     - 禁用U盘 | ||||
| - [x] 系统信息,展示CPU,内存利用率,硬盘使用率,发呆时间 **win api** | ||||
| - [x] 音量控制,音量和静音 **NAudio** | ||||
| - [x] 音频峰值,展示音频峰值,是否在播放音视频,及激昂程度 **NAudio** | ||||
| - [x] 系统亮度,暂不支持外界显示器 **WMI** | ||||
| - [x] 模拟键盘,键盘操作,模拟ctrl+alt+delete,模拟win+l,等等 **win api** | ||||
| - [ ] 模拟鼠标,鼠标操作 **win api** | ||||
| - [x] 系统信息,展示CPU,内存利用率,硬盘使用率,发呆时间 **system** | ||||
| - [x] 音量控制,音量和静音 **volume** | ||||
| - [x] 音频峰值,展示音频峰值,是否在播放音视频,及激昂程度 **volume** | ||||
| - [x] 系统亮度,暂不支持外界显示器 **light** | ||||
| - [x] 模拟键盘,键盘操作,模拟ctrl+alt+delete,模拟win+l,等等 **keyboard** | ||||
| - [ ] 模拟鼠标,鼠标操作 **volume** | ||||
| ###### 程序 | ||||
| - [x] 程序限制,分为禁止打开程序,和自定检测关闭程序 **regedit** **第一次成功连接服务端后自动恢复限制** | ||||
| - [x] 前景窗口,当前焦点程序捕获,手动关闭之 **win api** | ||||
| - [x] 时间统计,查看程序使用时间记录 | ||||
| - [x] 程序限制,分为禁止打开程序,和自定检测关闭程序 **active** | ||||
| - [x] 前景窗口,当前焦点程序捕获,手动关闭之 **active** | ||||
| - [x] 时间统计,查看程序使用时间记录 **active** | ||||
| ###### 网络 | ||||
| - [x] 网络限制,程序,域名,IP 黑白名单 **第一次成功连接服务端后恢复限制** | ||||
| - [x] 网速显示,由网络限制组件提供 | ||||
| - [x] 网络限制,程序,域名,IP 黑白名单 **hijack** | ||||
| - [x] 网速显示,由网络限制组件提供 **hijack** | ||||
| - [x] 自动连接wifi **wlan** | ||||
| ###### 消息 | ||||
| - [x] 消息提醒,向设备发送消息提醒 **winform** | ||||
| - [x] 全局广播,向所有设备发送广播 **winform** | ||||
| - [x] 语音消息,向设备发送语音消息 **NAudio** | ||||
| - [x] 消息提醒,向设备发送消息提醒 **message** | ||||
| - [x] 全局广播,向所有设备发送广播 **notify** | ||||
| - [x] 语音消息,向设备发送语音消息 **message** | ||||
| ###### 命令 | ||||
| - [x] 发送命令,执行cmd命令,等等 | ||||
| - [x] 发送命令,执行cmd命令,等等 **command** | ||||
| ###### 互动 | ||||
| - [x] 互动答题 **winform** | ||||
| - [x] 屏幕共享,以某一设备为主机,向其它设备共享屏幕,用于演示 **RDPSession+RDPViewer** **第一次成功连接服务端后自动恢复** | ||||
| - [x] 互动答题 **snatch** | ||||
| - [x] 屏幕共享,以某一设备为主机,向其它设备共享屏幕,用于演示 **viewer**第一次成功连接服务端后自动恢复** | ||||
| ###### 壁纸 | ||||
| - [x] 壁纸程序,为所有设备设置统一壁纸,以程序的方式 **winform** **第一次成功连接服务端后自动恢复** | ||||
| - [x] 键盘按键,显示键盘按键(当前键盘按键由壁纸程序提供) **win api** | ||||
| - [x] 壁纸程序,为所有设备设置统一壁纸,以程序的方式 **wallpaper** | ||||
| - [x] 键盘按键,显示键盘按键(当前键盘按键由壁纸程序提供) **wallpaper** | ||||
| ###### 锁屏 | ||||
| - [x] 锁屏程序,打开锁屏程序,禁用键盘 **winform** **第一次成功连接服务端后自动恢复** | ||||
| - [x] 锁屏程序,打开锁屏程序,禁用键盘 **llock** | ||||
| ###### 其它 | ||||
| - [x] 设备用户,显示当前使用设备用户姓名 **MemoryMappedFiles** | ||||
| - [x] 设备用户,显示当前使用设备用户姓名 **devices** | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -86,8 +87,7 @@ | ||||
|  | ||||
| ## 运行参数 | ||||
| ``` | ||||
| 第一次运行【cmonitor.exe】后,在 configs/  文件夹下,会生成配置文件,可以根据需要进行修改,然后再次运行 | ||||
|  | ||||
| 第一次运行后,在 configs/  文件夹下,会生成配置文件,可以根据需要进行修改,然后再次运行 | ||||
| ``` | ||||
|  | ||||
| ## 安装示例 | ||||
| @@ -129,7 +129,10 @@ systemctl restart cmonitor | ||||
| docker镜像 snltty/cmonitor-alpine-x64 or snltty/cmonitor-alpine-arm64 | ||||
| ``` | ||||
| docker run -it -d --name="cmonitor" \  | ||||
| -p 1800:1800/tcp -p 1801:1801/tcp -p 1802:1802/tcp -p 1802:1802/udp \  | ||||
| -p 1800:1800/tcp -p 1800:1800/udp \  | ||||
| -p 1801:1801/tcp -p 1801:1801/udp \  | ||||
| -p 1802:1802/tcp -p 1802:1802/udp \  | ||||
| -p 1802:1803/tcp -p 1802:1803/udp \  | ||||
| -v /usr/local/cmonitor/configs:/app/configs \ | ||||
| snltty/cmonitor-alpine-x64 | ||||
| ``` | ||||
|   | ||||
| @@ -126,12 +126,12 @@ namespace cmonitor.install.win | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public sealed class ConfigCommonInfo | ||||
|     public sealed partial class ConfigCommonInfo | ||||
|     { | ||||
|         public string[] Modes { get; set; } = new string[] { "client", "server" }; | ||||
|         public bool BlueProtect { get; set; } | ||||
|     } | ||||
|     public sealed class ConfigClientInfo | ||||
|     public sealed partial class ConfigClientInfo | ||||
|     { | ||||
|         private string server = new IPEndPoint(IPAddress.Loopback, 1802).ToString(); | ||||
|         public string Server | ||||
| @@ -165,7 +165,7 @@ namespace cmonitor.install.win | ||||
|         public int ShareMemorySize { get; set; } = 1024; | ||||
|  | ||||
|     } | ||||
|     public sealed class ConfigServerInfo | ||||
|     public sealed partial class ConfigServerInfo | ||||
|     { | ||||
|         public int WebPort { get; set; } = 1800; | ||||
|         public string WebRoot { get; set; } = "./web/"; | ||||
| @@ -174,3 +174,25 @@ namespace cmonitor.install.win | ||||
|  | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| 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 | ||||
|     { | ||||
|         public ViewerConfigInfo Viewer { get; set; } = new ViewerConfigInfo(); | ||||
|     } | ||||
|  | ||||
|     public sealed partial class ConfigServerInfo | ||||
|     { | ||||
|         public ViewerConfigInfo Viewer { get; set; } = new ViewerConfigInfo(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										39
									
								
								cmonitor.install.win/MainForm.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										39
									
								
								cmonitor.install.win/MainForm.Designer.cs
									
									
									
										generated
									
									
									
								
							| @@ -53,6 +53,10 @@ | ||||
|             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(); | ||||
| @@ -173,6 +177,8 @@ | ||||
|             // 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); | ||||
| @@ -189,6 +195,8 @@ | ||||
|             // 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); | ||||
| @@ -204,6 +212,26 @@ | ||||
|             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"); | ||||
| @@ -253,5 +281,16 @@ | ||||
|         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; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -38,6 +38,7 @@ namespace cmonitor.install.win | ||||
|  | ||||
|             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(); | ||||
| @@ -46,6 +47,7 @@ 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; | ||||
| @@ -162,10 +164,20 @@ 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
											
										
									
								
							| @@ -131,7 +131,7 @@ | ||||
|     <value>服务端地址</value> | ||||
|   </data> | ||||
|   <data name="label2.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>17, 85</value> | ||||
|     <value>17, 80</value> | ||||
|   </data> | ||||
|   <data name="label2.Size" type="System.Drawing.Size, System.Drawing"> | ||||
|     <value>56, 17</value> | ||||
| @@ -140,7 +140,7 @@ | ||||
|     <value>服务端口</value> | ||||
|   </data> | ||||
|   <data name="serverPort.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>79, 82</value> | ||||
|     <value>79, 77</value> | ||||
|   </data> | ||||
|   <data name="label3.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>17, 28</value> | ||||
| @@ -149,7 +149,7 @@ | ||||
|     <value>79, 24</value> | ||||
|   </data> | ||||
|   <data name="label4.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>17, 56</value> | ||||
|     <value>17, 54</value> | ||||
|   </data> | ||||
|   <data name="label4.Size" type="System.Drawing.Size, System.Drawing"> | ||||
|     <value>56, 17</value> | ||||
| @@ -158,7 +158,7 @@ | ||||
|     <value>管理端口</value> | ||||
|   </data> | ||||
|   <data name="apiPort.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>79, 53</value> | ||||
|     <value>79, 51</value> | ||||
|   </data> | ||||
|   <data name="modeClient.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>105, 45</value> | ||||
| @@ -167,16 +167,16 @@ | ||||
|     <value>298, 45</value> | ||||
|   </data> | ||||
|   <data name="label5.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>19, 130</value> | ||||
|     <value>19, 150</value> | ||||
|   </data> | ||||
|   <data name="shareLen.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>93, 127</value> | ||||
|     <value>93, 147</value> | ||||
|   </data> | ||||
|   <data name="label6.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>14, 104</value> | ||||
|     <value>14, 124</value> | ||||
|   </data> | ||||
|   <data name="shareKey.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>93, 100</value> | ||||
|     <value>93, 120</value> | ||||
|   </data> | ||||
|   <data name="label11.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>26, 29</value> | ||||
| @@ -185,25 +185,25 @@ | ||||
|     <value>93, 25</value> | ||||
|   </data> | ||||
|   <data name="installBtn.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>175, 268</value> | ||||
|     <value>175, 299</value> | ||||
|   </data> | ||||
|   <data name="runBtn.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>88, 268</value> | ||||
|     <value>88, 299</value> | ||||
|   </data> | ||||
|   <data name="checkStateBtn.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>305, 274</value> | ||||
|     <value>305, 305</value> | ||||
|   </data> | ||||
|   <data name="label16.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>7, 159</value> | ||||
|     <value>7, 179</value> | ||||
|   </data> | ||||
|   <data name="shareItemLen.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>93, 156</value> | ||||
|     <value>93, 176</value> | ||||
|   </data> | ||||
|   <data name="gbClient.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>12, 72</value> | ||||
|   </data> | ||||
|   <data name="gbClient.Size" type="System.Drawing.Size, System.Drawing"> | ||||
|     <value>200, 190</value> | ||||
|     <value>200, 212</value> | ||||
|   </data> | ||||
|   <data name="gbClient.Text" xml:space="preserve"> | ||||
|     <value>客户端参数</value> | ||||
| @@ -212,7 +212,7 @@ | ||||
|     <value>219, 73</value> | ||||
|   </data> | ||||
|   <data name="gbServer.Size" type="System.Drawing.Size, System.Drawing"> | ||||
|     <value>187, 189</value> | ||||
|     <value>187, 211</value> | ||||
|   </data> | ||||
|   <data name="gbServer.Text" xml:space="preserve"> | ||||
|     <value>服务端参数</value> | ||||
| @@ -221,20 +221,63 @@ | ||||
|   <data name="cbBlueProtect.AutoSize" type="System.Boolean, mscorlib"> | ||||
|     <value>True</value> | ||||
|   </data> | ||||
|   <data name="cbBlueProtect.Location" type="System.Drawing.Point, System.Drawing"> | ||||
|     <value>174, 12</value> | ||||
|   </data> | ||||
|   <data name="cbBlueProtect.Size" type="System.Drawing.Size, System.Drawing"> | ||||
|     <value>111, 21</value> | ||||
|   </data> | ||||
|   <data name="cbBlueProtect.TabIndex" type="System.Int32, mscorlib"> | ||||
|     <value>39</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> | ||||
|   <data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing"> | ||||
|     <value>418, 315</value> | ||||
|     <value>418, 346</value> | ||||
|   </data> | ||||
|   <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | ||||
|     <value> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <project ver="10" name="cmonitor.viewer.client.win" libEmbed="true" icon="D:\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.29" ProductVersion="0.0.0.29" publishDir="/dist/" dstrip="false"> | ||||
| <project ver="10" name="cmonitor.viewer.client.win" libEmbed="true" icon="D:\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.31" ProductVersion="0.0.0.31" 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.
										
									
								
							| @@ -37,7 +37,7 @@ mainForm.connect = function(){ | ||||
| 			var invitationString = reg.queryValue("viewerConnectStr"); | ||||
| 			if(string.len(invitationString)>0) | ||||
| 			{ | ||||
| 				mainForm.tsc.Connect(invitationString,"snltty","snltty"); | ||||
| 				mainForm.tsc.Connect(invitationString,_ARGV[1],_ARGV[1]); | ||||
| 			}else{ | ||||
| 				mainForm.connecting = false; | ||||
| 			} | ||||
|   | ||||
| @@ -3,11 +3,8 @@ using cmonitor.viewer.server.win.Properties; | ||||
| using common.libs; | ||||
| using Microsoft.Win32; | ||||
| using RDPCOMAPILib; | ||||
| using System.Data.SqlTypes; | ||||
| using System.Diagnostics; | ||||
| using System.Resources; | ||||
| using System.Text; | ||||
| using System.Windows.Forms; | ||||
| using System.Net; | ||||
| using System.Xml; | ||||
|  | ||||
| namespace cmonitor.viewer.server.win | ||||
| @@ -29,18 +26,16 @@ namespace cmonitor.viewer.server.win | ||||
|  | ||||
|         private readonly Hook hook = new Hook(); | ||||
|         private readonly ShareMemory shareMemory; | ||||
|         private int shareIndex = 0; | ||||
|         private Mode shareMode = Mode.Client; | ||||
|         private const string shareClientExe = "cmonitor.viewer.client.win"; | ||||
|         private byte[] shareKeyBytes = Encoding.UTF8.GetBytes(shareClientExe); | ||||
|  | ||||
|         public MainForm(string key, int length, int size, int index, Mode mode) | ||||
|         ParamInfo paramInfo; | ||||
|  | ||||
|         public MainForm(ParamInfo paramInfo) | ||||
|         { | ||||
|             InitializeComponent(); | ||||
|             this.paramInfo = paramInfo; | ||||
|  | ||||
|             shareMode = mode; | ||||
|             shareIndex = index; | ||||
|             shareMemory = new ShareMemory(key, length, size); | ||||
|             InitializeComponent(); | ||||
|             shareMemory = new ShareMemory(paramInfo.ShareMkey, paramInfo.ShareMLength, paramInfo.ShareItemMLength); | ||||
|             shareMemory.InitLocal(); | ||||
|         } | ||||
|  | ||||
| @@ -51,12 +46,12 @@ namespace cmonitor.viewer.server.win | ||||
|             this.ShowInTaskbar = false; | ||||
|             this.WindowState = FormWindowState.Minimized; | ||||
|             this.Visible = false; | ||||
|             FireWallHelper.Write(Path.GetFileNameWithoutExtension(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName)); | ||||
| #endif | ||||
|  | ||||
|             FireWallHelper.Write(Path.GetFileNameWithoutExtension(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName)); | ||||
|             CheckRunning(); | ||||
|  | ||||
|             if (shareMode == Mode.Client) | ||||
|             if (paramInfo.Mode == Mode.Client) | ||||
|             { | ||||
|                 OpenShareClient(); | ||||
|             } | ||||
| @@ -68,25 +63,25 @@ namespace cmonitor.viewer.server.win | ||||
|         private void CheckRunning() | ||||
|         { | ||||
|             hook.Close(); | ||||
|             shareMemory.AddAttribute(shareIndex, ShareMemoryAttribute.Running); | ||||
|             shareMemory.RemoveAttribute(shareIndex, ShareMemoryAttribute.Closed); | ||||
|             shareMemory.AddAttribute(paramInfo.ShareIndex, ShareMemoryAttribute.Running); | ||||
|             shareMemory.RemoveAttribute(paramInfo.ShareIndex, ShareMemoryAttribute.Closed); | ||||
|             Task.Run(async () => | ||||
|             { | ||||
|                 while (true) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         if (shareMemory.ReadAttributeEqual(shareIndex, ShareMemoryAttribute.Closed)) | ||||
|                         if (shareMemory.ReadAttributeEqual(paramInfo.ShareIndex, ShareMemoryAttribute.Closed)) | ||||
|                         { | ||||
|                             CloseServer(); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             shareMemory.IncrementVersion(shareIndex); | ||||
|                             shareMemory.IncrementVersion(paramInfo.ShareIndex); | ||||
|                         } | ||||
|                         if (Process.GetProcessesByName(shareClientExe).Length == 0) | ||||
|                         { | ||||
|                             shareMemory.AddAttribute(shareIndex, ShareMemoryAttribute.Error); | ||||
|                             shareMemory.AddAttribute(paramInfo.ShareIndex, ShareMemoryAttribute.Error); | ||||
|                         } | ||||
|                     } | ||||
|                     catch (Exception) | ||||
| @@ -99,7 +94,7 @@ namespace cmonitor.viewer.server.win | ||||
|         } | ||||
|         private void CloseServer() | ||||
|         { | ||||
|             shareMemory.RemoveAttribute(shareIndex, ShareMemoryAttribute.Running); | ||||
|             shareMemory.RemoveAttribute(paramInfo.ShareIndex, ShareMemoryAttribute.Running); | ||||
|             CloseShareClient(); | ||||
|             CloseShareDesktop(); | ||||
|             Application.ExitThread(); | ||||
| @@ -111,7 +106,7 @@ namespace cmonitor.viewer.server.win | ||||
|         { | ||||
|             hook.Start((code) => { return true; }); | ||||
|  | ||||
|             CommandHelper.Windows(string.Empty, new string[] { $"start {shareClientExe}.exe" }, false); | ||||
|             CommandHelper.Windows(string.Empty, new string[] { $"start {shareClientExe}.exe {paramInfo.GroupName}" }, false); | ||||
|         } | ||||
|         private void CloseShareClient() | ||||
|         { | ||||
| @@ -155,24 +150,43 @@ namespace cmonitor.viewer.server.win | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     string guid = Guid.NewGuid().ToString(); | ||||
|                     CloseShareDesktop(); | ||||
|                     session = new RDPSession(); | ||||
|                     session.SetDesktopSharedRect(0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); | ||||
|                     session.OnAttendeeConnected += Session_OnAttendeeConnected; | ||||
|                     session.Open(); | ||||
|                     IRDPSRAPIInvitation invitation = session.Invitations.CreateInvitation(guid, "snltty", "snltty", 1024); | ||||
|                     IRDPSRAPIInvitation invitation = session.Invitations.CreateInvitation(null, paramInfo.GroupName, paramInfo.GroupName, 1024); | ||||
|                     invitationString = invitation.ConnectionString; | ||||
|  | ||||
|                     /* | ||||
|                     XmlDocument xmlDoc = new XmlDocument(); | ||||
|                     xmlDoc.LoadXml(invitationString); | ||||
|                     XmlElement newLNode = xmlDoc.CreateElement("L"); | ||||
|                     newLNode.SetAttribute("P", "12345"); | ||||
|                     newLNode.SetAttribute("N", "192.168.1.35"); | ||||
|                     xmlDoc.DocumentElement["C"]["T"].AppendChild(newLNode); | ||||
|                     Debug.WriteLine(xmlDoc.OuterXml); | ||||
|                     */ | ||||
|                     if(string.IsNullOrWhiteSpace(paramInfo.ProxyServers) == false) | ||||
|                     { | ||||
|                         XmlDocument xmlDoc = new XmlDocument(); | ||||
|                         xmlDoc.LoadXml(invitationString); | ||||
|  | ||||
|                         //留给客户端自己替换为自己本地的代理地址 | ||||
|                         XmlElement newLNode = xmlDoc.CreateElement("L"); | ||||
|                         newLNode.SetAttribute("P", "{port}"); | ||||
|                         newLNode.SetAttribute("N", "{ip}"); | ||||
|                         xmlDoc.DocumentElement["C"]["T"].AppendChild(newLNode); | ||||
|  | ||||
|                         //插入其它代理地址 | ||||
|                         foreach (var item in paramInfo.ProxyServers.Split(',')) | ||||
|                         { | ||||
|                             try | ||||
|                             { | ||||
|                                 IPEndPoint ep = IPEndPoint.Parse(item); | ||||
|  | ||||
|                                 XmlElement newLNode1 = xmlDoc.CreateElement("L"); | ||||
|                                 newLNode1.SetAttribute("P", ep.Port.ToString()); | ||||
|                                 newLNode1.SetAttribute("N", ep.Address.ToString()); | ||||
|                                 xmlDoc.DocumentElement["C"]["T"].AppendChild(newLNode1); | ||||
|                             } | ||||
|                             catch (Exception) | ||||
|                             { | ||||
|                             } | ||||
|                         } | ||||
|                         invitationString = xmlDoc.OuterXml; | ||||
|                     } | ||||
|  | ||||
|                     Registry.SetValue("HKEY_CURRENT_USER\\SOFTWARE\\Cmonitor", "viewerConnectStr", invitationString); | ||||
|  | ||||
| @@ -182,14 +196,11 @@ namespace cmonitor.viewer.server.win | ||||
|                 catch (Exception ex) | ||||
|                 { | ||||
|                     Debug.WriteLine(ex + ""); | ||||
|                     //MessageBox.Show(ex.Message); | ||||
|                     notifyIcon.Icon = Icon.FromHandle(Resources.logo_share_gray.GetHicon()); | ||||
|                     notifyIcon.Text = "共享失败"; | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         private void Session_OnAttendeeConnected(object pAttendee) | ||||
|         { | ||||
|             IRDPSRAPIAttendee attendee = (IRDPSRAPIAttendee)pAttendee; | ||||
| @@ -200,7 +211,7 @@ namespace cmonitor.viewer.server.win | ||||
|             try | ||||
|             { | ||||
|                 session?.Close(); | ||||
|                 Registry.SetValue("HKEY_CURRENT_USER\\SOFTWARE\\Cmonitor", "viewerConnectStr", string.Empty); | ||||
|                 //Registry.SetValue("HKEY_CURRENT_USER\\SOFTWARE\\Cmonitor", "viewerConnectStr", string.Empty); | ||||
|             } | ||||
|             catch (Exception) | ||||
|             { | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
| using System.Net; | ||||
| using System.Text.Json; | ||||
|  | ||||
| namespace cmonitor.viewer.server.win | ||||
| { | ||||
|     internal static class Program | ||||
| @@ -19,22 +22,26 @@ namespace cmonitor.viewer.server.win | ||||
|                 MessageBox.Show(b.ExceptionObject.ToString()); | ||||
|             }; | ||||
|  | ||||
|             string shareMkey = "cmonitor/share"; | ||||
|             int shareMLength = 10; | ||||
|             int shareItemMLength = 1024; | ||||
|             int shareIndex = 5; | ||||
|             Mode mode = Mode.Server; | ||||
|             ParamInfo paramInfo = new ParamInfo(); | ||||
|             if (arg.Length > 0) | ||||
|             { | ||||
|                 shareMkey = arg[0]; | ||||
|                 shareMLength = int.Parse(arg[1]); | ||||
|                 shareItemMLength = int.Parse(arg[2]); | ||||
|                 shareIndex = int.Parse(arg[3]); | ||||
|                 mode = (Mode)byte.Parse(arg[4]); | ||||
|                 paramInfo = JsonSerializer.Deserialize<ParamInfo>(arg[0]); | ||||
|             } | ||||
|  | ||||
|             ApplicationConfiguration.Initialize(); | ||||
|             Application.Run(new MainForm(shareMkey, shareMLength, shareItemMLength, shareIndex, mode)); | ||||
|             Application.Run(new MainForm(paramInfo)); | ||||
|         } | ||||
|  | ||||
|          | ||||
|     } | ||||
|  | ||||
|     public sealed class ParamInfo | ||||
|     { | ||||
|         public string ShareMkey { get; set; } = "cmonitor/share"; | ||||
|         public int ShareMLength { get; set; } = 10; | ||||
|         public int ShareItemMLength { get; set; } = 1024; | ||||
|         public int ShareIndex { get; set; } = 5; | ||||
|         public Mode Mode { get; set; } = Mode.Server; | ||||
|         public string GroupName { get; set; } = "snltty"; | ||||
|         public string ProxyServers { get; set; } = "127.0.0.1:1803"; | ||||
|     } | ||||
| } | ||||
| @@ -46,10 +46,13 @@ export default { | ||||
|                 ElMessage.error('请选择一个共享设备'); | ||||
|                 return; | ||||
|             } | ||||
|             const device = globalState.value.devices.filter(c=>c.MachineName == pluginState.value.viewer.device) | ||||
|  | ||||
|             viewerUpdate({ | ||||
|                 Open: true, | ||||
|                 Server: pluginState.value.viewer.device, | ||||
|                 Clients: clients, | ||||
|                 ShareId: device.Viewer.id, | ||||
|             }).then(() => { | ||||
|                 pluginState.value.viewer.showShare = false; | ||||
|                 ElMessage.success('操作成功'); | ||||
|   | ||||
| @@ -31,7 +31,8 @@ export default { | ||||
|         const handleConfirm = () => { | ||||
|             viewerUpdate({ | ||||
|                 open: false, | ||||
|                 server: props.data.MachineName | ||||
|                 server: props.data.MachineName, | ||||
|                 shareid:props.data.Viewer.id | ||||
|             }).then(() => { | ||||
|                 ElMessage.success('已操作!') | ||||
|             }).catch(() => { | ||||
|   | ||||
| @@ -3,7 +3,8 @@ export default { | ||||
|         return { | ||||
|             Viewer: { | ||||
|                 share: false, | ||||
|                 mode: 'server' | ||||
|                 mode: 'server', | ||||
|                 id: '' | ||||
|             } | ||||
|         }; | ||||
|     }, | ||||
| @@ -25,6 +26,7 @@ export default { | ||||
|         if (!report.Viewer) return; | ||||
|  | ||||
|  | ||||
|         item.Viewer.id = report.Viewer.ShareId; | ||||
|         item.Viewer.share = report.Viewer.Value; | ||||
|         item.Viewer.mode = ['client', 'server'][report.Viewer.Mode]; | ||||
|     } | ||||
|   | ||||
| @@ -15,10 +15,10 @@ namespace cmonitor | ||||
|  | ||||
|             //初始化配置文件 | ||||
|             Config config = new Config(); | ||||
|             config.Elevated = args.Any(c => c.Contains("elevated")); | ||||
|             config.Data.Elevated = args.Any(c => c.Contains("elevated")); | ||||
|  | ||||
|             Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); | ||||
|             StartupTransfer.Init(); | ||||
|             StartupTransfer.Init(config); | ||||
|  | ||||
|             //依赖注入 | ||||
|             ServiceProvider serviceProvider = null; | ||||
| @@ -33,9 +33,6 @@ namespace cmonitor | ||||
|             serviceProvider = serviceCollection.BuildServiceProvider(); | ||||
|             StartupTransfer.Use(serviceProvider, config, assemblies); | ||||
|  | ||||
|  | ||||
|             FireWallHelper.Write(Path.GetFileNameWithoutExtension(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName)); | ||||
|  | ||||
|             GCHelper.FlushMemory(); | ||||
|             await Helper.Await(); | ||||
|         } | ||||
| @@ -66,6 +63,7 @@ namespace cmonitor | ||||
|             { | ||||
|                 common.libs.winapis.Win32Interop.RelaunchElevated(); | ||||
|             } | ||||
|             FireWallHelper.Write(Path.GetFileNameWithoutExtension(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName)); | ||||
| #endif | ||||
|         } | ||||
|  | ||||
| @@ -116,6 +114,6 @@ namespace cmonitor | ||||
|  | ||||
|     } | ||||
|  | ||||
|     | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -38,7 +38,11 @@ namespace cmonitor.api | ||||
|             Type voidType = typeof(void); | ||||
|  | ||||
|             IEnumerable<Type> types = assemblys.SelectMany(c => c.GetTypes()).Where(c => c.GetInterfaces().Contains(typeof(IApiController))); | ||||
|             | ||||
|             if (config.Data.Common.PluginNames.Length > 0) | ||||
|             { | ||||
|                 types = types.Where(c => config.Data.Common.PluginNames.Any(d => c.FullName.Contains(d))); | ||||
|             } | ||||
|  | ||||
|             foreach (Type item in types) | ||||
|             { | ||||
|                 object obj = serviceProvider.GetService(item); | ||||
| @@ -76,7 +80,7 @@ namespace cmonitor.api | ||||
|             server = new WebSocketServer(); | ||||
|             try | ||||
|             { | ||||
|                 server.Start(System.Net.IPAddress.Any, config.Server.ApiPort); | ||||
|                 server.Start(System.Net.IPAddress.Any, config.Data.Server.ApiPort); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|   | ||||
| @@ -27,7 +27,7 @@ namespace cmonitor.api | ||||
|             IApiServer clientServer = serviceProvider.GetService<IApiServer>(); | ||||
|             clientServer.LoadPlugins(assemblies); | ||||
|             clientServer.Websocket(); | ||||
|             Logger.Instance.Info($"api listen:{config.Server.ApiPort}"); | ||||
|             Logger.Instance.Info($"api listen:{config.Data.Server.ApiPort}"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using cmonitor.config; | ||||
| using cmonitor.client.args; | ||||
| using cmonitor.config; | ||||
| using cmonitor.plugins.signIn.messenger; | ||||
| using cmonitor.server; | ||||
| using common.libs; | ||||
| @@ -15,13 +16,15 @@ namespace cmonitor.client | ||||
|         private readonly Config config; | ||||
|         private readonly TcpServer tcpServer; | ||||
|         private readonly MessengerSender messengerSender; | ||||
|         private readonly SignInArgsTransfer signInArgsTransfer; | ||||
|  | ||||
|         public ClientSignInTransfer(ClientSignInState clientSignInState, Config config, TcpServer tcpServer, MessengerSender messengerSender) | ||||
|         public ClientSignInTransfer(ClientSignInState clientSignInState, Config config, TcpServer tcpServer, MessengerSender messengerSender, SignInArgsTransfer signInArgsTransfer) | ||||
|         { | ||||
|             this.clientSignInState = clientSignInState; | ||||
|             this.config = config; | ||||
|             this.tcpServer = tcpServer; | ||||
|             this.messengerSender = messengerSender; | ||||
|             this.signInArgsTransfer = signInArgsTransfer; | ||||
|  | ||||
|             SignInTask(); | ||||
|             tcpServer.OnDisconnected += (hashcode) => | ||||
| @@ -57,45 +60,27 @@ namespace cmonitor.client | ||||
|         } | ||||
|         private async Task SignIn() | ||||
|         { | ||||
|             IPAddress[] ips = new IPAddress[] { config.Client.ServerEP.Address }; | ||||
|             IPEndPoint[] ips = new IPEndPoint[] { config.Data.Client.ServerEP }; | ||||
|  | ||||
|             if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG) | ||||
|                 Logger.Instance.Info($"get ip:{ips.ToJsonFormat()}"); | ||||
|  | ||||
|             if (ips.Length == 0) return; | ||||
|             foreach (IPAddress ip in ips) | ||||
|             foreach (IPEndPoint ip in ips) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     IPEndPoint remote = new IPEndPoint(ip, config.Client.ServerEP.Port); | ||||
|                     //Logger.Instance.Info($"connect server {remote}"); | ||||
|                     Socket socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | ||||
|                     socket.KeepAlive(); | ||||
|                     IAsyncResult result = socket.BeginConnect(remote, null, null); | ||||
|                     await Task.Delay(500); | ||||
|                     if (result.IsCompleted == false) | ||||
|                     if (await ConnectServer(ip) == false) | ||||
|                     { | ||||
|                         socket.SafeClose(); | ||||
|                         continue; | ||||
|                     } | ||||
|                     clientSignInState.Connection = tcpServer.BindReceive(socket); | ||||
|                     MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap | ||||
|                     if (await SignIn2Server() == false) | ||||
|                     { | ||||
|                         Connection = clientSignInState.Connection, | ||||
|                         MessengerId = (ushort)SignInMessengerIds.SignIn, | ||||
|                         Payload = MemoryPackSerializer.Serialize(new SignInfo | ||||
|                         { | ||||
|                             MachineName = config.Client.Name, | ||||
|                             Version = config.Version | ||||
|                         }) | ||||
|                     }); | ||||
|                     if (resp.Code != MessageResponeCodes.OK || resp.Data.Span.SequenceEqual(Helper.TrueArray) == false) | ||||
|                     { | ||||
|                         clientSignInState.Connection?.Disponse(); | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     GCHelper.FlushMemory(); | ||||
|                     clientSignInState.PushNetworkEnabled(); | ||||
|  | ||||
|                     break; | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
| @@ -106,5 +91,42 @@ namespace cmonitor.client | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private async Task<bool> ConnectServer(IPEndPoint remote) | ||||
|         { | ||||
|             Socket socket = new Socket(remote.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | ||||
|             socket.KeepAlive(); | ||||
|             IAsyncResult result = socket.BeginConnect(remote, null, null); | ||||
|             await Task.Delay(500); | ||||
|             if (result.IsCompleted == false) | ||||
|             { | ||||
|                 socket.SafeClose(); | ||||
|                 return false; | ||||
|             } | ||||
|             clientSignInState.Connection = tcpServer.BindReceive(socket); | ||||
|             return true; | ||||
|         } | ||||
|         private async Task<bool> SignIn2Server() | ||||
|         { | ||||
|             Dictionary<string, string> args = new Dictionary<string, string>(); | ||||
|             signInArgsTransfer.Invoke(args); | ||||
|  | ||||
|             MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap | ||||
|             { | ||||
|                 Connection = clientSignInState.Connection, | ||||
|                 MessengerId = (ushort)SignInMessengerIds.SignIn, | ||||
|                 Payload = MemoryPackSerializer.Serialize(new SignInfo | ||||
|                 { | ||||
|                     MachineName = config.Data.Client.Name, | ||||
|                     Version = config.Data.Version, | ||||
|                     Args = args, | ||||
|                 }) | ||||
|             }); | ||||
|             if (resp.Code != MessageResponeCodes.OK || resp.Data.Span.SequenceEqual(Helper.TrueArray) == false) | ||||
|             { | ||||
|                 clientSignInState.Connection?.Disponse(); | ||||
|                 return false; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| using cmonitor.client.runningConfig; | ||||
| using cmonitor.client.report; | ||||
| using cmonitor.client.report; | ||||
| using cmonitor.config; | ||||
| using cmonitor.libs; | ||||
| using cmonitor.startup; | ||||
| using common.libs; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using System.Reflection; | ||||
| using cmonitor.server.ruleConfig; | ||||
| using cmonitor.client.args; | ||||
| using cmonitor.client.running; | ||||
|  | ||||
| namespace cmonitor.client | ||||
| { | ||||
| @@ -14,30 +14,24 @@ namespace cmonitor.client | ||||
|     { | ||||
|         public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|             serviceCollection.AddSingleton<RunningConfig>(); | ||||
|  | ||||
|             serviceCollection.AddSingleton<SignInArgsTransfer>(); | ||||
|  | ||||
|             serviceCollection.AddSingleton<ClientReportTransfer>(); | ||||
|  | ||||
|             serviceCollection.AddSingleton<ClientSignInState>(); | ||||
|             serviceCollection.AddSingleton<ClientSignInTransfer>(); | ||||
|  | ||||
|  | ||||
|             if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IRunningConfig, RunningConfigWindows>(); | ||||
|             else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IRunningConfig, RunningConfigLinux>(); | ||||
|             else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<IRunningConfig, RunningConfigMacOS>(); | ||||
|  | ||||
|             //内存共享 | ||||
|             ShareMemory shareMemory = new ShareMemory(config.Client.ShareMemoryKey, config.Client.ShareMemoryCount, config.Client.ShareMemorySize); | ||||
|             ShareMemory shareMemory = new ShareMemory(config.Data.Client.ShareMemoryKey, config.Data.Client.ShareMemoryCount, config.Data.Client.ShareMemorySize); | ||||
|             serviceCollection.AddSingleton<ShareMemory>((a) => shareMemory); | ||||
|         } | ||||
|  | ||||
|         public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|              | ||||
|         } | ||||
|  | ||||
|         public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|             Logger.Instance.Info($"start client"); | ||||
|             Logger.Instance.Info($"server ip {config.Client.ServerEP}"); | ||||
|             Logger.Instance.Info($"server ip {config.Data.Client.ServerEP}"); | ||||
|  | ||||
|             Logger.Instance.Info($"start client report transfer"); | ||||
|             ClientReportTransfer report = serviceProvider.GetService<ClientReportTransfer>(); | ||||
| @@ -53,6 +47,11 @@ namespace cmonitor.client | ||||
|             ClientSignInTransfer clientTransfer = serviceProvider.GetService<ClientSignInTransfer>(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|  | ||||
|         } | ||||
|         public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|         } | ||||
|   | ||||
							
								
								
									
										7
									
								
								cmonitor/client/args/ISignInArgs.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								cmonitor/client/args/ISignInArgs.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| namespace cmonitor.client.args | ||||
| { | ||||
|     public interface ISignInArgs | ||||
|     { | ||||
|         public void Invoke(Dictionary<string, string> args); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										30
									
								
								cmonitor/client/args/SignInArgsTransfer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								cmonitor/client/args/SignInArgsTransfer.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| using cmonitor.config; | ||||
| using common.libs; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using System; | ||||
|  | ||||
| namespace cmonitor.client.args | ||||
| { | ||||
|     public sealed class SignInArgsTransfer | ||||
|     { | ||||
|         private List<ISignInArgs> startups; | ||||
|  | ||||
|         public SignInArgsTransfer(ServiceProvider serviceProvider, Config config) | ||||
|         { | ||||
|             var types = ReflectionHelper.GetInterfaceSchieves(typeof(ISignInArgs)); | ||||
|             if (config.Data.Common.PluginNames.Length > 0) | ||||
|             { | ||||
|                 types = types.Where(c => config.Data.Common.PluginNames.Any(d => c.FullName.Contains(d))); | ||||
|             } | ||||
|             startups = types.Select(c => serviceProvider.GetService(c) as ISignInArgs).Where(c=>c != null).ToList(); | ||||
|         } | ||||
|  | ||||
|         public void Invoke(Dictionary<string, string> args) | ||||
|         { | ||||
|             foreach (var item in startups) | ||||
|             { | ||||
|                 item.Invoke(args); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										48
									
								
								cmonitor/client/config/Config.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								cmonitor/client/config/Config.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| using common.libs; | ||||
| using common.libs.extends; | ||||
| using System.Net; | ||||
| using System.Text.Json.Serialization; | ||||
|  | ||||
| namespace cmonitor.config | ||||
| { | ||||
|     public sealed partial class ConfigInfo | ||||
|     { | ||||
|         public ConfigClientInfo Client { get; set; } = new ConfigClientInfo(); | ||||
|     } | ||||
|  | ||||
|     public sealed partial class ConfigClientInfo | ||||
|     { | ||||
|         private string server = new IPEndPoint(IPAddress.Loopback, 1802).ToString(); | ||||
|         public string Server | ||||
|         { | ||||
|             get => server; set | ||||
|             { | ||||
|                 server = value; | ||||
|                 if (string.IsNullOrWhiteSpace(server) == false) | ||||
|                 { | ||||
|                     string[] arr = server.Split(':'); | ||||
|                     int port = arr.Length == 2 ? int.Parse(arr[1]) : 1802; | ||||
|                     IPAddress ip = NetworkHelper.GetDomainIp(arr[0]); | ||||
|                     ServerEP = new IPEndPoint(ip, port); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         [JsonIgnore] | ||||
|         public IPEndPoint ServerEP { get; set; } = new IPEndPoint(IPAddress.Loopback, 1802); | ||||
|  | ||||
|  | ||||
|         private string name = Dns.GetHostName().SubStr(0, 12); | ||||
|         public string Name | ||||
|         { | ||||
|             get => name; set | ||||
|             { | ||||
|                 name = value.SubStr(0, 12); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public string ShareMemoryKey { get; set; } = "cmonitor/share"; | ||||
|         public int ShareMemoryCount { get; set; } = 100; | ||||
|         public int ShareMemorySize { get; set; } = 1024; | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -34,7 +34,11 @@ namespace cmonitor.client.report | ||||
|         public void LoadPlugins(Assembly[] assembs) | ||||
|         { | ||||
|             IEnumerable<Type> types = ReflectionHelper.GetInterfaceSchieves(assembs, typeof(IClientReport)); | ||||
|             reports = types.Select(c => (IClientReport)serviceProvider.GetService(c)).Where(c => string.IsNullOrWhiteSpace(c.Name) == false).ToList(); | ||||
|             if (config.Data.Common.PluginNames.Length > 0) | ||||
|             { | ||||
|                 types = types.Where(c => config.Data.Common.PluginNames.Any(d => c.FullName.Contains(d))); | ||||
|             } | ||||
|             reports = types.Select(c => (IClientReport)serviceProvider.GetService(c)).Where(c => c != null).Where(c => string.IsNullOrWhiteSpace(c.Name) == false).ToList(); | ||||
|             reportObj = new Dictionary<string, object>(reports.Count); | ||||
|  | ||||
|             Logger.Instance.Warning($"load reports:{string.Join(",", reports.Select(c => c.Name))}"); | ||||
|   | ||||
							
								
								
									
										104
									
								
								cmonitor/client/running/RunningConfig.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								cmonitor/client/running/RunningConfig.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| using common.libs; | ||||
| using common.libs.extends; | ||||
| using System.Net; | ||||
| using System.Text.Json.Serialization; | ||||
|  | ||||
| namespace cmonitor.client.running | ||||
| { | ||||
|     public sealed class RunningConfig | ||||
|     { | ||||
|         private FileStream fs = null; | ||||
|         private StreamWriter writer = null; | ||||
|         private StreamReader reader = null; | ||||
|         private SemaphoreSlim slim = new SemaphoreSlim(1); | ||||
|         private string configPath { get; } = "./configs/"; | ||||
|  | ||||
|         public RunningConfigInfo Data { get; private set; } = new RunningConfigInfo(); | ||||
|  | ||||
|  | ||||
|         public RunningConfig() | ||||
|         { | ||||
|             if (Directory.Exists(configPath) == false) | ||||
|             { | ||||
|                 Directory.CreateDirectory(configPath); | ||||
|             } | ||||
|             string path = Path.Join(configPath, "running.json"); | ||||
|             fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read); | ||||
|             reader = new StreamReader(fs, System.Text.Encoding.UTF8); | ||||
|             writer = new StreamWriter(fs, System.Text.Encoding.UTF8); | ||||
|  | ||||
|             Load(); | ||||
|             Save(); | ||||
|             SaveTask(); | ||||
|         } | ||||
|  | ||||
|         private void Load() | ||||
|         { | ||||
|             slim.Wait(); | ||||
|             try | ||||
|             { | ||||
|                 fs.Seek(0, SeekOrigin.Begin); | ||||
|                 string text = reader.ReadToEnd(); | ||||
|                 if (string.IsNullOrWhiteSpace(text)) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|                 Data = text.DeJson<RunningConfigInfo>(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 slim.Release(); | ||||
|             } | ||||
|         } | ||||
|         private void SaveTask() | ||||
|         { | ||||
|             Task.Run(async () => | ||||
|             { | ||||
|                 while (true) | ||||
|                 { | ||||
|                     uint updated = Data.Updated; | ||||
|                     while (updated > 0) | ||||
|                     { | ||||
|                         Save(); | ||||
|                         updated--; | ||||
|                     } | ||||
|                     await Task.Delay(1000); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|         private void Save() | ||||
|         { | ||||
|             slim.Wait(); | ||||
|             try | ||||
|             { | ||||
|                 fs.Seek(0, SeekOrigin.Begin); | ||||
|                 fs.SetLength(0); | ||||
|                 writer.Write(Data.ToJsonFormat()); | ||||
|                 writer.Flush(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 slim.Release(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public sealed partial class RunningConfigInfo | ||||
|     { | ||||
|         [JsonIgnore] | ||||
|         public uint Updated { get; set; } = 1; | ||||
|  | ||||
|         public void Update() | ||||
|         { | ||||
|             Updated++; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,8 +0,0 @@ | ||||
| namespace cmonitor.client.runningConfig | ||||
| { | ||||
|     public interface IRunningConfig | ||||
|     { | ||||
|         public T Get<T>(T defaultValue); | ||||
|         public void Set<T>(T data); | ||||
|     } | ||||
| } | ||||
| @@ -1,15 +0,0 @@ | ||||
| namespace cmonitor.client.runningConfig | ||||
| { | ||||
|     public sealed class RunningConfigLinux : IRunningConfig | ||||
|     { | ||||
|         public T Get<T>(T defaultValue) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|  | ||||
|         public void Set<T>(T data) | ||||
|         { | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,15 +0,0 @@ | ||||
| namespace cmonitor.client.runningConfig | ||||
| { | ||||
|     public sealed class RunningConfigMacOS : IRunningConfig | ||||
|     { | ||||
|         public T Get<T>(T defaultValue) | ||||
|         { | ||||
|             return defaultValue; | ||||
|         } | ||||
|  | ||||
|         public void Set<T>(T data) | ||||
|         { | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,75 +0,0 @@ | ||||
| using common.libs; | ||||
| using common.libs.database; | ||||
| using common.libs.extends; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
| using System.Runtime.Versioning; | ||||
|  | ||||
| namespace cmonitor.client.runningConfig | ||||
| { | ||||
|     [SupportedOSPlatform("windows")] | ||||
|  | ||||
|     public sealed class RunningConfigWindows : IRunningConfig | ||||
|     { | ||||
|         private readonly IConfigDataProvider<RunningConfigInfo> configDataProvider; | ||||
|         private readonly RunningConfigInfo runningConfigInfo; | ||||
|  | ||||
|         private Dictionary<string, object> cache = new Dictionary<string, object>(); | ||||
|  | ||||
|  | ||||
|         public RunningConfigWindows(IConfigDataProvider<RunningConfigInfo> configDataProvider) | ||||
|         { | ||||
|             this.configDataProvider = configDataProvider; | ||||
|             runningConfigInfo = configDataProvider.Load().Result ?? new RunningConfigInfo(); | ||||
|         } | ||||
|  | ||||
|         public T Get<T>(T defaultValue) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 string name = typeof(T).Name; | ||||
|                 if (cache.TryGetValue(name, out object cacheValue)) | ||||
|                 { | ||||
|                     return (T)cacheValue; | ||||
|                 } | ||||
|  | ||||
|                 if (runningConfigInfo.Running.TryGetValue(name, out string value)) | ||||
|                 { | ||||
|                     if (string.IsNullOrWhiteSpace(value) == false) | ||||
|                     { | ||||
|                         T data = value.DeJson<T>(); | ||||
|                         cache[name] = data; | ||||
|                         return data; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|             } | ||||
|             return defaultValue; | ||||
|         } | ||||
|  | ||||
|         public void Set<T>(T data) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 string name = typeof(T).Name; | ||||
|                 string value = data.ToJson(); | ||||
|                 runningConfigInfo.Running[name] = value; | ||||
|                 cache[name] = data; | ||||
|  | ||||
|                 configDataProvider.Save(runningConfigInfo).Wait(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     [Table("running")] | ||||
|     public sealed class RunningConfigInfo | ||||
|     { | ||||
|         public Dictionary<string, string> Running { get; set; } = new Dictionary<string, string>(); | ||||
|     } | ||||
| } | ||||
| @@ -1,9 +0,0 @@ | ||||
| namespace cmonitor.client.trigger | ||||
| { | ||||
|     public interface ITrigger | ||||
|     { | ||||
|         public string Name { get; } | ||||
|         public string Desc { get; } | ||||
|         public void Execute(); | ||||
|     } | ||||
| } | ||||
| @@ -7,62 +7,30 @@ namespace cmonitor.config | ||||
| { | ||||
|     public sealed class Config | ||||
|     { | ||||
|         FileStream fs = null; | ||||
|         StreamWriter writer = null; | ||||
|         StreamReader reader = null; | ||||
|         SemaphoreSlim slim = new SemaphoreSlim(1); | ||||
|         private FileStream fs = null; | ||||
|         private StreamWriter writer = null; | ||||
|         private StreamReader reader = null; | ||||
|         private SemaphoreSlim slim = new SemaphoreSlim(1); | ||||
|         private string configPath = "./configs/"; | ||||
|  | ||||
|         public ConfigInfo Data { get; private set; } = new ConfigInfo(); | ||||
|  | ||||
|         public Config() | ||||
|         { | ||||
|             if (Directory.Exists(ConfigPath) == false) | ||||
|             if (Directory.Exists(configPath) == false) | ||||
|             { | ||||
|                 Directory.CreateDirectory(ConfigPath); | ||||
|                 Directory.CreateDirectory(configPath); | ||||
|             } | ||||
|             string path = Path.Join(ConfigPath, "config.json"); | ||||
|             string path = Path.Join(configPath, "config.json"); | ||||
|             fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read); | ||||
|             reader = new StreamReader(fs, System.Text.Encoding.UTF8); | ||||
|             writer = new StreamWriter(fs, System.Text.Encoding.UTF8); | ||||
|  | ||||
|             Load(); | ||||
|         } | ||||
|  | ||||
|         public ConfigCommonInfo Common { get; set; } = new ConfigCommonInfo(); | ||||
|         public ConfigClientInfo Client { get; set; } = new ConfigClientInfo(); | ||||
|         public ConfigServerInfo Server { get; set; } = new ConfigServerInfo(); | ||||
|  | ||||
|         public string ConfigPath { get; } = "./configs/"; | ||||
|  | ||||
|  | ||||
|         private Dictionary<string, Dictionary<string, object>> JsonDic = new Dictionary<string, Dictionary<string, object>>(); | ||||
|         public T Get<T>(T defaultValue) | ||||
|         { | ||||
|             return Get<T>(typeof(T).Name, defaultValue); | ||||
|         } | ||||
|         public T Get<T>(string name, T defaultValue) | ||||
|         { | ||||
|             if (JsonDic.ContainsKey(name)) | ||||
|             { | ||||
|                 return JsonDic[name].ToJson().DeJson<T>(); | ||||
|             } | ||||
|             return defaultValue; | ||||
|         } | ||||
|         public void Set<T>(T value) | ||||
|         { | ||||
|             Set<T>(typeof(T).Name, value); | ||||
|         } | ||||
|         public void Set<T>(string name, T value) | ||||
|         { | ||||
|             JsonDic[name] = value.ToJson().DeJson<Dictionary<string, object>>(); | ||||
|             Save(); | ||||
|         } | ||||
|  | ||||
|         private void Load() | ||||
|         { | ||||
|             InitFileConfig(); | ||||
|             ReadJson(); | ||||
|             Logger.Instance.Debug($"config:{JsonDic.ToJson()}"); | ||||
|             Save(); | ||||
|         } | ||||
|         private void InitFileConfig() | ||||
|         { | ||||
|             slim.Wait(); | ||||
|             try | ||||
| @@ -73,7 +41,7 @@ namespace cmonitor.config | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|                 JsonDic = text.DeJson<Dictionary<string, Dictionary<string, object>>>(); | ||||
|                 Data = text.DeJson<ConfigInfo>(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
| @@ -83,36 +51,17 @@ namespace cmonitor.config | ||||
|             { | ||||
|                 slim.Release(); | ||||
|             } | ||||
|         } | ||||
|         private void ReadJson() | ||||
|         { | ||||
|             if (JsonDic.TryGetValue("Client", out Dictionary<string, object> elClient)) | ||||
|             { | ||||
|                 Client = elClient.ToJson().DeJson<ConfigClientInfo>(); | ||||
|             } | ||||
|  | ||||
|             if (JsonDic.TryGetValue("Server", out Dictionary<string, object> elServer)) | ||||
|             { | ||||
|                 Server = elServer.ToJson().DeJson<ConfigServerInfo>(); | ||||
|             } | ||||
|             if (JsonDic.TryGetValue("Common", out Dictionary<string, object> elCommon)) | ||||
|             { | ||||
|                 Common = elCommon.ToJson().DeJson<ConfigCommonInfo>(); | ||||
|             } | ||||
|             | ||||
|         } | ||||
|  | ||||
|         public void Save() | ||||
|         private void Save() | ||||
|         { | ||||
|             slim.Wait(); | ||||
|             try | ||||
|             { | ||||
|                 JsonDic["Client"] = Client.ToJson().DeJson<Dictionary<string, object>>(); | ||||
|                 JsonDic["Server"] = Server.ToJson().DeJson<Dictionary<string, object>>(); | ||||
|                 JsonDic["Common"] = Common.ToJson().DeJson<Dictionary<string, object>>(); | ||||
|  | ||||
|                 fs.Seek(0, SeekOrigin.Begin); | ||||
|                 fs.SetLength(0); | ||||
|                 writer.Write(JsonDic.ToJsonFormat()); | ||||
|                 writer.Write(Data.ToJsonFormat()); | ||||
|                 writer.Flush(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
| @@ -125,59 +74,32 @@ namespace cmonitor.config | ||||
|             } | ||||
|         } | ||||
|  | ||||
|          | ||||
|     } | ||||
|  | ||||
|     public sealed partial class ConfigInfo | ||||
|     { | ||||
|         public ConfigCommonInfo Common { get; set; } = new ConfigCommonInfo(); | ||||
|  | ||||
|         [JsonIgnore] | ||||
|         public string Version { get; set; } = "1.0.0.1"; | ||||
|         [JsonIgnore] | ||||
|         public bool Elevated { get; set; } | ||||
|     } | ||||
|  | ||||
|     public sealed class ConfigCommonInfo | ||||
|     public sealed partial class ConfigCommonInfo | ||||
|     { | ||||
|         public string[] Modes { get; set; } = new string[] { "client", "server" }; | ||||
|         public bool BlueProtect { get; set; } | ||||
|     } | ||||
|     public sealed class ConfigClientInfo | ||||
|     { | ||||
|         private string server = new IPEndPoint(IPAddress.Loopback, 1802).ToString(); | ||||
|         public string Server | ||||
|  | ||||
|         public string[] plugins = Array.Empty<string>(); | ||||
|         public string[] Plugins | ||||
|         { | ||||
|             get => server; set | ||||
|             get => plugins; set | ||||
|             { | ||||
|                 server = value; | ||||
|                 if (string.IsNullOrWhiteSpace(server) == false) | ||||
|                 { | ||||
|                     string[] arr = server.Split(':'); | ||||
|                     int port = arr.Length == 2 ? int.Parse(arr[1]) : 1802; | ||||
|                     IPAddress ip = NetworkHelper.GetDomainIp(arr[0]); | ||||
|                     ServerEP = new IPEndPoint(ip, port); | ||||
|                 } | ||||
|                 PluginNames = value.Select(c => $"plugins.{c}.").ToArray(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [JsonIgnore] | ||||
|         public IPEndPoint ServerEP { get; set; } = new IPEndPoint(IPAddress.Loopback, 1802); | ||||
|  | ||||
|         private string name = Dns.GetHostName().SubStr(0, 12); | ||||
|         public string Name | ||||
|         { | ||||
|             get => name; set | ||||
|             { | ||||
|                 name = value.SubStr(0, 12); | ||||
|             } | ||||
|         } | ||||
|         public string ShareMemoryKey { get; set; } = "cmonitor/share"; | ||||
|         public int ShareMemoryCount { get; set; } = 100; | ||||
|         public int ShareMemorySize { get; set; } = 1024; | ||||
|  | ||||
|         public string[] PluginNames = Array.Empty<string>(); | ||||
|     } | ||||
|     public sealed class ConfigServerInfo | ||||
|     { | ||||
|         public int WebPort { get; set; } = 1800; | ||||
|         public string WebRoot { get; set; } = "./web/"; | ||||
|         public int ApiPort { get; set; } = 1801; | ||||
|         public int ServicePort { get; set; } = 1802; | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| using cmonitor.client; | ||||
| using cmonitor.client.runningConfig; | ||||
| using cmonitor.client.report; | ||||
| using cmonitor.config; | ||||
| using common.libs; | ||||
| @@ -7,6 +6,8 @@ using MemoryPack; | ||||
| using System.Collections.Concurrent; | ||||
| using System.Text.RegularExpressions; | ||||
| using System.Diagnostics; | ||||
| using cmonitor.client.running; | ||||
| using cmonitor.plugins.active.report; | ||||
|  | ||||
| namespace cmonitor.plugins.active.report | ||||
| { | ||||
| @@ -14,22 +15,20 @@ namespace cmonitor.plugins.active.report | ||||
|     { | ||||
|         public string Name => "ActiveWindow"; | ||||
|  | ||||
|         private readonly IRunningConfig clientConfig; | ||||
|         private readonly RunningConfig runningConfig; | ||||
|         private readonly IActiveWindow activeWindow; | ||||
|         private readonly ActiveWindowTimeManager activeWindowTimeManager = new ActiveWindowTimeManager(); | ||||
|         private ActiveReportInfo report = new ActiveReportInfo(); | ||||
|         private ActiveDisallowInfo activeConfig; | ||||
|  | ||||
|         public ActiveWindowReport(Config config, IRunningConfig clientConfig, IActiveWindow activeWindow, ClientSignInState clientSignInState) | ||||
|         public ActiveWindowReport(Config config, RunningConfig runningConfig, IActiveWindow activeWindow, ClientSignInState clientSignInState) | ||||
|         { | ||||
|             this.clientConfig = clientConfig; | ||||
|             this.runningConfig = runningConfig; | ||||
|             this.activeWindow = activeWindow; | ||||
|  | ||||
|             DisallowRun(Array.Empty<string>()); | ||||
|             activeConfig = clientConfig.Get(new ActiveDisallowInfo { }); | ||||
|             clientSignInState.NetworkFirstEnabledHandle += () => | ||||
|             { | ||||
|                 DisallowRun(activeConfig.FileNames); | ||||
|                 DisallowRun(runningConfig.Data.Active.FileNames); | ||||
|                 Loop(); | ||||
|             }; | ||||
|         } | ||||
| @@ -38,8 +37,8 @@ namespace cmonitor.plugins.active.report | ||||
|         public object GetReports(ReportType reportType) | ||||
|         { | ||||
|             ticks = DateTime.UtcNow.Ticks; | ||||
|             report.Ids1 = activeConfig.Ids1; | ||||
|             report.Ids2 = activeConfig.Ids2; | ||||
|             report.Ids1 = runningConfig.Data.Active.Ids1; | ||||
|             report.Ids2 = runningConfig.Data.Active.Ids2; | ||||
|             if (reportType == ReportType.Full || report.Updated()) | ||||
|             { | ||||
|                 return report; | ||||
| @@ -50,8 +49,7 @@ namespace cmonitor.plugins.active.report | ||||
|  | ||||
|         public void DisallowRun(ActiveDisallowInfo activeDisallowInfo) | ||||
|         { | ||||
|             activeConfig = activeDisallowInfo; | ||||
|             clientConfig.Set(activeConfig); | ||||
|             runningConfig.Data.Active = activeDisallowInfo; | ||||
|             report.DisallowCount = activeDisallowInfo.FileNames.Length; | ||||
|             activeWindow.DisallowRun(activeDisallowInfo.FileNames); | ||||
|         } | ||||
| @@ -131,13 +129,13 @@ namespace cmonitor.plugins.active.report | ||||
|  | ||||
|         private bool Disallow(ActiveWindowInfo window) | ||||
|         { | ||||
|             if (activeConfig.FileNames.Length > 0) | ||||
|             if (runningConfig.Data.Active.FileNames.Length > 0) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     ReadOnlySpan<char> filenameSpan = window.FileName.AsSpan(); | ||||
|                     uint pid = window.Pid; | ||||
|                     foreach (string item in activeConfig.FileNames) | ||||
|                     foreach (string item in runningConfig.Data.Active.FileNames) | ||||
|                     { | ||||
|                         ReadOnlySpan<char> nameSpan = item.AsSpan(); | ||||
|                         bool result = item == window.Title | ||||
| @@ -257,6 +255,7 @@ namespace cmonitor.plugins.active.report | ||||
|         public DateTime StartTime { get; set; } = DateTime.Now; | ||||
|         public List<ActiveWindowTimeInfo> List { get; set; } = new List<ActiveWindowTimeInfo>(); | ||||
|     } | ||||
|  | ||||
|     [MemoryPackable] | ||||
|     public sealed partial class ActiveWindowTimeInfo | ||||
|     { | ||||
| @@ -267,3 +266,19 @@ namespace cmonitor.plugins.active.report | ||||
|         public Dictionary<string, uint> Titles { get; set; } | ||||
|     } | ||||
| } | ||||
|  | ||||
| namespace cmonitor.client.running | ||||
| { | ||||
|     public sealed partial class RunningConfigInfo | ||||
|     { | ||||
|         private ActiveDisallowInfo active = new ActiveDisallowInfo(); | ||||
|         public ActiveDisallowInfo Active | ||||
|         { | ||||
|             get => active; set | ||||
|             { | ||||
|                 Updated++; | ||||
|                 active = value; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -212,10 +212,12 @@ namespace cmonitor.plugins.active.report | ||||
|  | ||||
|         private void InitDriver() | ||||
|         { | ||||
|             AppDomain.CurrentDomain.ProcessExit += (sender, e) => { | ||||
|             AppDomain.CurrentDomain.ProcessExit += (sender, e) => | ||||
|             { | ||||
|                 CommandHelper.Windows(string.Empty, new string[] { "sc stop cmonitor.killer & sc delete cmonitor.killer" }, true); | ||||
|             }; | ||||
|             Console.CancelKeyPress += (sender, e) => { | ||||
|             Console.CancelKeyPress += (sender, e) => | ||||
|             { | ||||
|                 CommandHelper.Windows(string.Empty, new string[] { "sc stop cmonitor.killer & sc delete cmonitor.killer" }, true); | ||||
|             }; | ||||
|             Task.Run(() => | ||||
| @@ -228,7 +230,15 @@ namespace cmonitor.plugins.active.report | ||||
|  | ||||
|                     Logger.Instance.Info($"killer starting"); | ||||
|                     string sourcePath = Path.GetFullPath(Path.Join("./", "killer.sys")); | ||||
|                     string distPath = Path.GetFullPath(Path.Join("./", "killer-temp.sys")); | ||||
|                     string distPath = $"{Environment.SystemDirectory}\\drivers\\killer.sys"; | ||||
|  | ||||
|                     try | ||||
|                     { | ||||
|                         File.Delete("killer-temp.sys"); | ||||
|                     } | ||||
|                     catch (Exception) | ||||
|                     { | ||||
|                     } | ||||
|                     try | ||||
|                     { | ||||
|                         File.Copy(sourcePath, distPath, true); | ||||
|   | ||||
| @@ -11,7 +11,6 @@ namespace cmonitor.plugins.hijack | ||||
|     { | ||||
|         public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|             serviceCollection.AddSingleton<HijackConfig>(); | ||||
|             serviceCollection.AddSingleton<HijackReport>(); | ||||
|             if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IHijack, HijackWindows>(); | ||||
|             else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IHijack, HijackLinux>(); | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| namespace cmonitor.plugins.hijack.report | ||||
| using cmonitor.plugins.hijack.report; | ||||
|  | ||||
| namespace cmonitor.plugins.hijack.report | ||||
| { | ||||
|     public sealed class HijackConfig | ||||
|     { | ||||
| @@ -42,3 +44,19 @@ | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| namespace cmonitor.client.running | ||||
| { | ||||
|     public sealed partial class RunningConfigInfo | ||||
|     { | ||||
|         private HijackConfig hijack = new HijackConfig(); | ||||
|         public HijackConfig Hijack | ||||
|         { | ||||
|             get => hijack; set | ||||
|             { | ||||
|                 Updated++; | ||||
|                 hijack = value; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| using cmonitor.client; | ||||
| using cmonitor.client.runningConfig; | ||||
| using cmonitor.client.report; | ||||
| using cmonitor.config; | ||||
| using common.libs; | ||||
| using MemoryPack; | ||||
| using cmonitor.client.running; | ||||
|  | ||||
| namespace cmonitor.plugins.hijack.report | ||||
| { | ||||
| @@ -11,19 +11,17 @@ namespace cmonitor.plugins.hijack.report | ||||
|     { | ||||
|         public string Name => "Hijack"; | ||||
|  | ||||
|         private readonly HijackConfig hijackConfig; | ||||
|         private readonly IRunningConfig clientConfig; | ||||
|         private readonly RunningConfig runningConfig; | ||||
|         private readonly IHijack hijack; | ||||
|         private readonly ClientSignInState clientSignInState; | ||||
|  | ||||
|         private HijackReportInfo hijackReportInfo = new HijackReportInfo(); | ||||
|         private long ticks = DateTime.UtcNow.Ticks; | ||||
|  | ||||
|         public HijackReport(IHijack hijack, HijackConfig hijackConfig, IRunningConfig clientConfig, Config config, ClientSignInState clientSignInState) | ||||
|         public HijackReport(IHijack hijack, RunningConfig runningConfig, Config config, ClientSignInState clientSignInState) | ||||
|         { | ||||
|             this.hijack = hijack; | ||||
|             this.hijackConfig = hijackConfig; | ||||
|             this.clientConfig = clientConfig; | ||||
|             this.runningConfig = runningConfig; | ||||
|             this.clientSignInState = clientSignInState; | ||||
|             Init(); | ||||
|         } | ||||
| @@ -33,18 +31,6 @@ namespace cmonitor.plugins.hijack.report | ||||
|             try | ||||
|             { | ||||
|                 clientSignInState.NetworkFirstEnabledHandle += hijack.Start; | ||||
|  | ||||
|                 HijackConfig config = clientConfig.Get(new HijackConfig { }); | ||||
|  | ||||
|                 hijackConfig.DeniedProcesss = config.DeniedProcesss; | ||||
|                 hijackConfig.AllowProcesss = config.AllowProcesss; | ||||
|                 hijackConfig.DeniedDomains = config.DeniedDomains; | ||||
|                 hijackConfig.AllowDomains = config.AllowDomains; | ||||
|                 hijackConfig.DeniedIPs = config.DeniedIPs; | ||||
|                 hijackConfig.AllowIPs = config.AllowIPs; | ||||
|                 hijackConfig.DomainKill = config.DomainKill; | ||||
|                 hijackConfig.HijackIds1 = config.HijackIds1; | ||||
|                 hijackConfig.HijackIds2 = config.HijackIds2; | ||||
|                 UpdateRules(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
| @@ -55,26 +41,26 @@ namespace cmonitor.plugins.hijack.report | ||||
|  | ||||
|         public void Update(HijackSetRuleInfo info) | ||||
|         { | ||||
|             hijackConfig.AllowDomains = info.Rules.AllowDomains; | ||||
|             hijackConfig.DeniedDomains = info.Rules.DeniedDomains; | ||||
|             hijackConfig.AllowProcesss = info.Rules.AllowProcesss; | ||||
|             hijackConfig.DeniedProcesss = info.Rules.DeniedProcesss; | ||||
|             hijackConfig.AllowIPs = info.Rules.AllowIPs; | ||||
|             hijackConfig.DeniedIPs = info.Rules.DeniedIPs; | ||||
|             hijackConfig.DomainKill = info.Rules.DomainKill; | ||||
|             hijackConfig.HijackIds1 = info.Ids1; | ||||
|             hijackConfig.HijackIds2 = info.Ids2; | ||||
|             runningConfig.Data.Hijack.AllowDomains = info.Rules.AllowDomains; | ||||
|             runningConfig.Data.Hijack.DeniedDomains = info.Rules.DeniedDomains; | ||||
|             runningConfig.Data.Hijack.AllowProcesss = info.Rules.AllowProcesss; | ||||
|             runningConfig.Data.Hijack.DeniedProcesss = info.Rules.DeniedProcesss; | ||||
|             runningConfig.Data.Hijack.AllowIPs = info.Rules.AllowIPs; | ||||
|             runningConfig.Data.Hijack.DeniedIPs = info.Rules.DeniedIPs; | ||||
|             runningConfig.Data.Hijack.DomainKill = info.Rules.DomainKill; | ||||
|             runningConfig.Data.Hijack.HijackIds1 = info.Ids1; | ||||
|             runningConfig.Data.Hijack.HijackIds2 = info.Ids2; | ||||
|  | ||||
|             clientConfig.Set(hijackConfig); | ||||
|             runningConfig.Data.Update(); | ||||
|  | ||||
|             UpdateRules(); | ||||
|         } | ||||
|  | ||||
|         private void UpdateRules() | ||||
|         { | ||||
|             hijack.SetProcess(hijackConfig.AllowProcesss, hijackConfig.DeniedProcesss); | ||||
|             hijack.SetDomain(hijackConfig.AllowDomains, hijackConfig.DeniedDomains, hijackConfig.DomainKill); | ||||
|             hijack.SetIP(hijackConfig.AllowIPs, hijackConfig.DeniedIPs); | ||||
|             hijack.SetProcess(runningConfig.Data.Hijack.AllowProcesss, runningConfig.Data.Hijack.DeniedProcesss); | ||||
|             hijack.SetDomain(runningConfig.Data.Hijack.AllowDomains, runningConfig.Data.Hijack.DeniedDomains, runningConfig.Data.Hijack.DomainKill); | ||||
|             hijack.SetIP(runningConfig.Data.Hijack.AllowIPs, runningConfig.Data.Hijack.DeniedIPs); | ||||
|             hijack.UpdateRules(); | ||||
|         } | ||||
|  | ||||
| @@ -82,10 +68,10 @@ namespace cmonitor.plugins.hijack.report | ||||
|         { | ||||
|             hijackReportInfo.Upload = hijack.UdpSend + hijack.TcpSend; | ||||
|             hijackReportInfo.Download = hijack.TcpReceive + hijack.UdpReceive; | ||||
|             hijackReportInfo.Count = (ulong)(hijackConfig.AllowIPs.Length + hijackConfig.DeniedIPs.Length + hijackConfig.AllowDomains.Length + hijackConfig.DeniedDomains.Length + hijackConfig.AllowProcesss.Length + hijackConfig.DeniedProcesss.Length); | ||||
|             hijackReportInfo.Ids1 = hijackConfig.HijackIds1; | ||||
|             hijackReportInfo.Ids2 = hijackConfig.HijackIds2; | ||||
|             hijackReportInfo.DomainKill = hijackConfig.DomainKill; | ||||
|             hijackReportInfo.Count = (ulong)(runningConfig.Data.Hijack.AllowIPs.Length + runningConfig.Data.Hijack.DeniedIPs.Length + runningConfig.Data.Hijack.AllowDomains.Length + runningConfig.Data.Hijack.DeniedDomains.Length + runningConfig.Data.Hijack.AllowProcesss.Length + runningConfig.Data.Hijack.DeniedProcesss.Length); | ||||
|             hijackReportInfo.Ids1 = runningConfig.Data.Hijack.HijackIds1; | ||||
|             hijackReportInfo.Ids2 = runningConfig.Data.Hijack.HijackIds2; | ||||
|             hijackReportInfo.DomainKill = runningConfig.Data.Hijack.DomainKill; | ||||
|  | ||||
|             long _ticks = DateTime.UtcNow.Ticks; | ||||
|             if (((_ticks - ticks) / TimeSpan.TicksPerMillisecond >= 300 && hijackReportInfo.Updated()) || reportType == ReportType.Full) | ||||
| @@ -97,7 +83,7 @@ namespace cmonitor.plugins.hijack.report | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public sealed class HijackReportInfo:ReportInfo | ||||
|     public sealed class HijackReportInfo : ReportInfo | ||||
|     { | ||||
|         public ulong Upload { get; set; } | ||||
|         public ulong Download { get; set; } | ||||
|   | ||||
| @@ -77,7 +77,7 @@ namespace cmonitor.plugins.keyboard.report | ||||
|  | ||||
|                             if (inputActions.TryDequeue(out var action)) | ||||
|                             { | ||||
|                                 if (config.Elevated == true && !Win32Interop.SwitchToInputDesktop()) | ||||
|                                 if (config.Data.Elevated == true && !Win32Interop.SwitchToInputDesktop()) | ||||
|                                 { | ||||
|                                     uint code = Kernel32.GetLastError(); | ||||
|                                     tks.Cancel(); | ||||
|   | ||||
| @@ -1,9 +1,10 @@ | ||||
| using cmonitor.client; | ||||
| using cmonitor.client.runningConfig; | ||||
| using cmonitor.client.report; | ||||
| using cmonitor.config; | ||||
| using cmonitor.libs; | ||||
| using common.libs; | ||||
| using cmonitor.client.running; | ||||
| using cmonitor.plugins.llock.report; | ||||
|  | ||||
| namespace cmonitor.plugins.llock.report | ||||
| { | ||||
| @@ -13,21 +14,19 @@ namespace cmonitor.plugins.llock.report | ||||
|  | ||||
|         private LLockReportInfo report = new LLockReportInfo(); | ||||
|  | ||||
|         private readonly IRunningConfig clientConfig; | ||||
|         private readonly RunningConfig runningConfig; | ||||
|         private readonly ILLock lLock; | ||||
|         private readonly ShareMemory shareMemory; | ||||
|         private readonly LLockConfigInfo lLockConfigInfo = new LLockConfigInfo(); | ||||
|  | ||||
|         public LLockReport(Config config, IRunningConfig clientConfig, ILLock lLock, ShareMemory shareMemory, ClientSignInState clientSignInState) | ||||
|         public LLockReport(Config config, RunningConfig runningConfig, ILLock lLock, ShareMemory shareMemory, ClientSignInState clientSignInState) | ||||
|         { | ||||
|             this.clientConfig = clientConfig; | ||||
|             this.runningConfig = runningConfig; | ||||
|             this.lLock = lLock; | ||||
|             this.shareMemory = shareMemory; | ||||
|  | ||||
|             lLockConfigInfo = clientConfig.Get(new LLockConfigInfo { }); | ||||
|             clientSignInState.NetworkFirstEnabledHandle += () => | ||||
|             { | ||||
|                 LockScreen(lLockConfigInfo.Open); | ||||
|                 LockScreen(runningConfig.Data.LLock.Open); | ||||
|                 WallpaperTask(); | ||||
|             }; | ||||
|         } | ||||
| @@ -44,10 +43,10 @@ namespace cmonitor.plugins.llock.report | ||||
|  | ||||
|         public void LockScreen(bool open) | ||||
|         { | ||||
|             lLockConfigInfo.Open = open; | ||||
|             runningConfig.Data.LLock.Open = open; | ||||
|             runningConfig.Data.Update(); | ||||
|             Task.Run(async () => | ||||
|             { | ||||
|                 clientConfig.Set(lLockConfigInfo); | ||||
|                 shareMemory.AddAttribute((int)ShareMemoryIndexs.LLock, ShareMemoryAttribute.Closed); | ||||
|                 await Task.Delay(100); | ||||
|                 lLock.Set(open); | ||||
| @@ -72,11 +71,11 @@ namespace cmonitor.plugins.llock.report | ||||
|             { | ||||
|                 while (true) | ||||
|                 { | ||||
|                     if (lLockConfigInfo.Open) | ||||
|                     if (runningConfig.Data.LLock.Open) | ||||
|                     { | ||||
|                         if (Running() == false) | ||||
|                         { | ||||
|                             LockScreen(lLockConfigInfo.Open); | ||||
|                             LockScreen(runningConfig.Data.LLock.Open); | ||||
|                         } | ||||
|                     } | ||||
|                     await Task.Delay(5000); | ||||
| @@ -102,3 +101,21 @@ namespace cmonitor.plugins.llock.report | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| namespace cmonitor.client.running | ||||
| { | ||||
|     public sealed partial class RunningConfigInfo | ||||
|     { | ||||
|         private LLockConfigInfo llock = new LLockConfigInfo(); | ||||
|         public LLockConfigInfo LLock | ||||
|         { | ||||
|             get => llock; set | ||||
|             { | ||||
|                 Updated++; | ||||
|                 llock = value; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -17,7 +17,7 @@ namespace cmonitor.plugins.llock.report | ||||
|             if (value) | ||||
|             { | ||||
|                 CommandHelper.Windows(string.Empty, new string[] { | ||||
|                         $"start cmonitor.llock.win.exe {config.Client.ShareMemoryKey} {config.Client.ShareMemoryCount} {config.Client.ShareMemorySize} {(int)ShareMemoryIndexs.LLock}" | ||||
|                         $"start cmonitor.llock.win.exe {config.Data.Client.ShareMemoryKey} {config.Data.Client.ShareMemoryCount} {config.Data.Client.ShareMemorySize} {(int)ShareMemoryIndexs.LLock}" | ||||
|                     },false); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,6 +1,4 @@ | ||||
| using cmonitor.api; | ||||
| using cmonitor.plugins.signIn.messenger; | ||||
| using cmonitor.server; | ||||
| using cmonitor.server.ruleConfig; | ||||
| using common.libs.extends; | ||||
|  | ||||
|   | ||||
| @@ -63,7 +63,7 @@ namespace cmonitor.plugins.screen.messenger | ||||
|         { | ||||
|             if (signCaching.Get(connection.Name, out SignCacheInfo cache)) | ||||
|             { | ||||
|                 if (cache.Version == config.Version) | ||||
|                 if (cache.Version == config.Data.Version) | ||||
|                 { | ||||
|                     clientServer.Notify("/notify/report/screen/full", connection.Name, connection.ReceiveRequestWrap.Payload); | ||||
|                 } | ||||
|   | ||||
| @@ -245,7 +245,7 @@ namespace cmonitor.plugins.screen.report | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 if (config.Elevated) | ||||
|                 if (config.Data.Elevated) | ||||
|                 { | ||||
|                     Win32Interop.SwitchToInputDesktop(); | ||||
|                 } | ||||
| @@ -372,7 +372,7 @@ namespace cmonitor.plugins.screen.report | ||||
|             bool result = false; | ||||
|             try | ||||
|             { | ||||
|                 if (config.Elevated == true && !Win32Interop.SwitchToInputDesktop()) | ||||
|                 if (config.Data.Elevated == true && !Win32Interop.SwitchToInputDesktop()) | ||||
|                 { | ||||
|                     var errCode = Marshal.GetLastWin32Error(); | ||||
|                     if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG) | ||||
|   | ||||
| @@ -38,7 +38,7 @@ namespace cmonitor.plugins.screen.report | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     if (config.Elevated == true && !Win32Interop.SwitchToInputDesktop()) | ||||
|                     if (config.Data.Elevated == true && !Win32Interop.SwitchToInputDesktop()) | ||||
|                     { | ||||
|                         var errCode = Marshal.GetLastWin32Error(); | ||||
|                         if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG) | ||||
|   | ||||
| @@ -31,7 +31,8 @@ namespace cmonitor.plugins.signIn.messenger | ||||
|             { | ||||
|                 Connection = connection, | ||||
|                 MachineName = signInfo.MachineName, | ||||
|                 Version = signInfo.Version | ||||
|                 Version = signInfo.Version, | ||||
|                 Args = signInfo.Args, | ||||
|             }; | ||||
|             config.Clients.TryAdd(signInfo.MachineName, cache1); | ||||
|             changed = true; | ||||
| @@ -86,6 +87,8 @@ namespace cmonitor.plugins.signIn.messenger | ||||
|         public string MachineName { get; set; } | ||||
|         public string Version { get; set; } = "1.0.0.0"; | ||||
|  | ||||
|         public Dictionary<string, string> Args { get; set; } = new Dictionary<string, string>(); | ||||
|  | ||||
|         [JsonIgnore] | ||||
|         public int ReportFlag = 1; | ||||
|         [JsonIgnore] | ||||
| @@ -115,7 +118,6 @@ namespace cmonitor.plugins.signIn.messenger | ||||
|             ScreenTime = Environment.TickCount; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public bool Connected | ||||
|         { | ||||
|             get | ||||
| @@ -130,7 +132,9 @@ namespace cmonitor.plugins.signIn.messenger | ||||
|     [MemoryPackable] | ||||
|     public sealed partial class SignInfo | ||||
|     { | ||||
|         public string MachineName { get; set; } | ||||
|         public string Version { get; set; } | ||||
|         public string MachineName { get; set; } = string.Empty; | ||||
|         public string Version { get; set; } = string.Empty; | ||||
|  | ||||
|         public Dictionary<string, string> Args { get; set; } = new Dictionary<string, string>(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -19,7 +19,7 @@ namespace cmonitor.plugins.signIn.messenger | ||||
|         public void SignIn(IConnection connection) | ||||
|         { | ||||
|             SignInfo info = MemoryPackSerializer.Deserialize<SignInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             if (info.Version == config.Version) | ||||
|             if (info.Version == config.Data.Version) | ||||
|             { | ||||
|                 signCaching.Sign(connection, info); | ||||
|                 connection.Write(Helper.TrueArray); | ||||
|   | ||||
| @@ -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.Client.ShareMemoryKey} {config.Client.ShareMemoryCount} {config.Client.ShareMemorySize} {(int)ShareMemoryIndexs.SnatchQuestion} {(int)ShareMemoryIndexs.SnatchAnswer}" | ||||
|                         $"start cmonitor.snatch.win.exe {config.Data.Client.ShareMemoryKey} {config.Data.Client.ShareMemoryCount} {config.Data.Client.ShareMemorySize} {(int)ShareMemoryIndexs.SnatchQuestion} {(int)ShareMemoryIndexs.SnatchAnswer}" | ||||
|                     },false); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -115,7 +115,7 @@ namespace cmonitor.plugins.system.report | ||||
|                         { | ||||
|                             while (actions.TryDequeue(out Action action)) | ||||
|                             { | ||||
|                                 if (config.Elevated) | ||||
|                                 if (config.Data.Elevated) | ||||
|                                 { | ||||
|                                     Win32Interop.SwitchToInputDesktop(); | ||||
|                                 } | ||||
|   | ||||
							
								
								
									
										552
									
								
								cmonitor/plugins/viewer/RDP桌面共享流程.drawio
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										552
									
								
								cmonitor/plugins/viewer/RDP桌面共享流程.drawio
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,552 @@ | ||||
| <mxfile host="Electron" modified="2024-04-13T08:49:39.679Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.1.2 Chrome/106.0.5249.199 Electron/21.4.3 Safari/537.36" etag="N35__DeDEHlFxssWZWsV" version="21.1.2" type="device"> | ||||
|   <diagram name="第 1 页" id="cBPwx1frQaiKcuuC_Qt-"> | ||||
|     <mxGraphModel dx="6020" dy="3312" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> | ||||
|       <root> | ||||
|         <mxCell id="0" /> | ||||
|         <mxCell id="1" parent="0" /> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-91" value="" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;fillColor=none;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-240" width="1240" height="960" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-1" value="服务端" style="image;html=1;image=img/lib/clip_art/computers/Server_Rack_128x128.png;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;imageBorder=default;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="420" y="80" width="80" height="80" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-2" value="客户端A" style="image;html=1;image=img/lib/clip_art/computers/iMac_128x128.png;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Comic Sans MS;fontSize=20;imageBorder=default;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="240" y="240" width="80" height="80" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-3" value="客户端B" style="image;html=1;image=img/lib/clip_art/computers/iMac_128x128.png;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Comic Sans MS;fontSize=20;imageBorder=default;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="600" y="240" width="80" height="80" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-4" value="RDP桌面共享流程" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontFamily=Architects Daughter;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="285" y="10" width="170" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-5" value="RDPViewer" style="image;html=1;image=img/lib/clip_art/computers/iPad_128x128.png;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Comic Sans MS;fontSize=20;imageBorder=default;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-40" y="240" width="80" height="80" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-6" value="RDPSession" style="image;html=1;image=img/lib/clip_art/computers/iPad_128x128.png;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Comic Sans MS;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="870" y="240" width="80" height="80" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-7" value="管理员" style="image;html=1;image=img/lib/clip_art/people/Suit_Man_128x128.png;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-30" y="80" width="80" height="80" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-8" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" source="osB9R2kQAUtgP8P5AnCK-49" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="280" y="830" as="sourcePoint" /> | ||||
|             <mxPoint x="280" y="320" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-10" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" source="osB9R2kQAUtgP8P5AnCK-53" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="640" y="840" as="sourcePoint" /> | ||||
|             <mxPoint x="640" y="320" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-12" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-7" target="osB9R2kQAUtgP8P5AnCK-1" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="70" y="230" as="sourcePoint" /> | ||||
|             <mxPoint x="260" y="140" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-14" value="发起共享,以B为共享端,A为访问端" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="100" y="100" width="280" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-17" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" source="osB9R2kQAUtgP8P5AnCK-22" target="osB9R2kQAUtgP8P5AnCK-1" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="460" y="840" as="sourcePoint" /> | ||||
|             <mxPoint x="500" y="420" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-19" value="开启共享,获取连接串" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Architects Daughter;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="690" y="250" width="160" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-20" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="620" y="400" width="40" height="60" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-23" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" source="osB9R2kQAUtgP8P5AnCK-51" target="osB9R2kQAUtgP8P5AnCK-22" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="460" y="840" as="sourcePoint" /> | ||||
|             <mxPoint x="460" y="160" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-22" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="440" y="400" width="40" height="60" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-24" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-3" target="osB9R2kQAUtgP8P5AnCK-6" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="840" y="460" as="sourcePoint" /> | ||||
|             <mxPoint x="890" y="410" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-25" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="700" y="120" as="sourcePoint" /> | ||||
|             <mxPoint x="700" y="120" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-26" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="437" y="240" width="40" height="60" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-27" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.375;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-26" target="osB9R2kQAUtgP8P5AnCK-3" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="500" y="370" as="sourcePoint" /> | ||||
|             <mxPoint x="550" y="320" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-28" value="通知B" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="510" y="240" width="60" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-29" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-20" target="osB9R2kQAUtgP8P5AnCK-22" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="830" y="470" as="sourcePoint" /> | ||||
|             <mxPoint x="880" y="420" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-30" value="通知A" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="527" y="400" width="60" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-31" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="260" y="400" width="40" height="60" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-32" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-22" target="osB9R2kQAUtgP8P5AnCK-31" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="380" y="560" as="sourcePoint" /> | ||||
|             <mxPoint x="430" y="510" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-33" value="通知A" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="340" y="400" width="60" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-34" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" source="osB9R2kQAUtgP8P5AnCK-38" target="osB9R2kQAUtgP8P5AnCK-5" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint y="850" as="sourcePoint" /> | ||||
|             <mxPoint x="30" y="460" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-35" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-20" y="400" width="40" height="60" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-36" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-31" target="osB9R2kQAUtgP8P5AnCK-35" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="120" y="520" as="sourcePoint" /> | ||||
|             <mxPoint x="170" y="470" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-37" value="开启rdpviewer访问程序" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="70" y="390" width="160" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-39" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" source="osB9R2kQAUtgP8P5AnCK-47" target="osB9R2kQAUtgP8P5AnCK-38" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint y="850" as="sourcePoint" /> | ||||
|             <mxPoint y="320" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-38" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-20" y="520" width="40" height="60" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-42" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;entryX=0.625;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-43" target="osB9R2kQAUtgP8P5AnCK-6" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="920" y="880" as="sourcePoint" /> | ||||
|             <mxPoint x="1020" y="540" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-44" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;entryX=0.625;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-73" target="osB9R2kQAUtgP8P5AnCK-43" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="920" y="960" as="sourcePoint" /> | ||||
|             <mxPoint x="920" y="320" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-43" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="900" y="520" width="40" height="60" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-45" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#00CC00;" parent="1" source="osB9R2kQAUtgP8P5AnCK-38" target="osB9R2kQAUtgP8P5AnCK-43" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="-150" y="670" as="sourcePoint" /> | ||||
|             <mxPoint x="-100" y="620" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-46" value="通过连接串直接连接B" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="50" y="510" width="200" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-48" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" target="osB9R2kQAUtgP8P5AnCK-47" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint y="960" as="sourcePoint" /> | ||||
|             <mxPoint y="580" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-47" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-20" y="640" width="40" height="120" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-50" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" target="osB9R2kQAUtgP8P5AnCK-49" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="280" y="960" as="sourcePoint" /> | ||||
|             <mxPoint x="280" y="320" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-49" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="260" y="640" width="40" height="120" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-52" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" source="osB9R2kQAUtgP8P5AnCK-69" target="osB9R2kQAUtgP8P5AnCK-51" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="460" y="960" as="sourcePoint" /> | ||||
|             <mxPoint x="460" y="460" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-51" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="440" y="640" width="40" height="50" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-54" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" source="osB9R2kQAUtgP8P5AnCK-71" target="osB9R2kQAUtgP8P5AnCK-53" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="640" y="960" as="sourcePoint" /> | ||||
|             <mxPoint x="640" y="320" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-53" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="620" y="640" width="40" height="120" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-55" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="900" y="640" width="40" height="120" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-57" value="连接A自己的监听" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Architects Daughter;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="60" y="660" width="160" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-58" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-49" target="osB9R2kQAUtgP8P5AnCK-51" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="380" y="850" as="sourcePoint" /> | ||||
|             <mxPoint x="430" y="800" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-59" value="<font style="font-size: 14px;">通知B来连接A</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="340" y="630" width="60" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-60" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-51" target="osB9R2kQAUtgP8P5AnCK-53" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="540" y="760" as="sourcePoint" /> | ||||
|             <mxPoint x="590" y="710" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-61" value="<font style="font-size: 14px;">通知B去连接A</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="530" y="630" width="60" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-62" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#00CC00;" parent="1" source="osB9R2kQAUtgP8P5AnCK-53" target="osB9R2kQAUtgP8P5AnCK-55" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="770" y="880" as="sourcePoint" /> | ||||
|             <mxPoint x="820" y="830" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-63" value="<font style="font-size: 14px;">连接共享</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="760" y="660" width="60" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-64" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;entryX=-0.025;entryY=0.825;entryDx=0;entryDy=0;entryPerimeter=0;exitX=1.25;exitY=0.833;exitDx=0;exitDy=0;exitPerimeter=0;strokeColor=#00CC00;" parent="1" source="osB9R2kQAUtgP8P5AnCK-49" target="osB9R2kQAUtgP8P5AnCK-53" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="500" y="890" as="sourcePoint" /> | ||||
|             <mxPoint x="550" y="840" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-65" value="<font style="font-size: 14px;">B去连接A</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="510" y="700" width="70" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-66" value="第一次尝试" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontFamily=Architects Daughter;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-190" y="520" width="110" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-67" value="第二次尝试" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontFamily=Architects Daughter;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-190" y="640" width="110" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-68" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-20" y="840" width="40" height="120" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-70" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" target="osB9R2kQAUtgP8P5AnCK-69" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="460" y="960" as="sourcePoint" /> | ||||
|             <mxPoint x="460" y="690" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-69" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="440" y="840" width="40" height="120" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-72" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" target="osB9R2kQAUtgP8P5AnCK-71" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="640" y="960" as="sourcePoint" /> | ||||
|             <mxPoint x="640" y="760" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-71" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="620" y="840" width="40" height="120" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-74" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;entryX=0.625;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" target="osB9R2kQAUtgP8P5AnCK-73" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="920" y="960" as="sourcePoint" /> | ||||
|             <mxPoint x="925" y="580" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-73" value="" style="rounded=1;whiteSpace=wrap;html=1;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="900" y="840" width="40" height="120" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-76" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;" parent="1" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="280" y="960" as="sourcePoint" /> | ||||
|             <mxPoint x="280" y="960" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-77" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1.1;exitY=0.388;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.388;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=#00CC00;" parent="1" source="osB9R2kQAUtgP8P5AnCK-47" target="osB9R2kQAUtgP8P5AnCK-49" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="150" y="780" as="sourcePoint" /> | ||||
|             <mxPoint x="200" y="730" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-78" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1.063;exitY=0.338;exitDx=0;exitDy=0;exitPerimeter=0;entryX=-0.125;entryY=0.325;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=#00CC00;" parent="1" source="osB9R2kQAUtgP8P5AnCK-68" target="osB9R2kQAUtgP8P5AnCK-69" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="100" y="900" as="sourcePoint" /> | ||||
|             <mxPoint x="150" y="850" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-79" value="连接服务器的监听" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Architects Daughter;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="80" y="850" width="160" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-80" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" parent="1" source="osB9R2kQAUtgP8P5AnCK-69" target="osB9R2kQAUtgP8P5AnCK-71" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="500" y="870" as="sourcePoint" /> | ||||
|             <mxPoint x="550" y="820" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-81" value="<font style="font-size: 14px;">通知B去连接服务器</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="520" y="830" width="70" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-82" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=#00CC00;" parent="1" source="osB9R2kQAUtgP8P5AnCK-71" target="osB9R2kQAUtgP8P5AnCK-73" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="670" y="864.5" as="sourcePoint" /> | ||||
|             <mxPoint x="910" y="864.5" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-83" value="<font style="font-size: 14px;">连接共享</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="760" y="840" width="60" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-84" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1.075;exitY=0.696;exitDx=0;exitDy=0;exitPerimeter=0;entryX=-0.075;entryY=0.663;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=#00CC00;" parent="1" source="osB9R2kQAUtgP8P5AnCK-69" target="osB9R2kQAUtgP8P5AnCK-71" edge="1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="560" y="1030" as="sourcePoint" /> | ||||
|             <mxPoint x="610" y="980" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-85" value="<font style="font-size: 14px;">B去连接服务器</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Comic Sans MS;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="500" y="885" width="100" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-86" value="第三次尝试" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontFamily=Architects Daughter;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-197.5" y="840" width="110" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-87" value="由访问段直接连接共享端" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Architects Daughter;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-182.5" y="560" width="95" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-88" value="以访问端自身为代理,共享端反向连接,形成链路" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Architects Daughter;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-210" y="680" width="162.5" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="osB9R2kQAUtgP8P5AnCK-89" value="以服务端为代理,共享端反向连接,形成链路" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Architects Daughter;" parent="1" vertex="1"> | ||||
|           <mxGeometry x="-223.75" y="880" width="162.5" height="30" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-1" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ViewerApiController</b><br></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;</p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+ Update(ViewerUpdateParamInfo info): bool</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=20;fontFamily=Helvetica;html=1;whiteSpace=wrap;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="203.75" y="1340" width="421.25" height="150" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-2" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ViewerServerMessenger</b><br></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;</p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+ HeartNotify(ViewerRunningConfigInfo info): void</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ProxyNotify(ViewerProxyInfo viewerProxyInfo): void</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=20;fontFamily=Helvetica;html=1;whiteSpace=wrap;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="403.75" y="2050" width="490" height="180" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-3" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ViewerClientMessenger</b><br></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;</p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+ Server(ViewerRunningConfigInfo info): void</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;Heart(ViewerRunningConfigInfo info): void</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ProxyFromClient(ViewerProxyInfo viewerProxyInfo): void<br></p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ProxyFromServer(ViewerProxyInfo viewerProxyInfo): void<br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=20;fontFamily=Helvetica;html=1;whiteSpace=wrap;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="403.75" y="1530" width="560" height="210" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-4" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ViewerReport</b><br></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;</p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+ Server(ViewerRunningConfigInfo info): void</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;Heart(ViewerRunningConfigInfo info): void</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=20;fontFamily=Helvetica;html=1;whiteSpace=wrap;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="403.75" y="1820" width="450" height="160" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-5" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ViewerProxyClient /&nbsp;</b><b style="background-color: initial;">ViewerProxyServer</b></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;</p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+ Connect(string name, uint connectId): void</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;Connect(ViewerProxyInfo viewerProxyInfo): void</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=20;fontFamily=Helvetica;html=1;whiteSpace=wrap;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="403.75" y="2370" width="560" height="170" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-6" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ViewerProxyInfo</b><br></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ConnectId: int</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ViewerMachine: string</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ProxyEP: string</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;TargetEP: string</p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=20;fontFamily=Helvetica;html=1;whiteSpace=wrap;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="-240" y="1010" width="250" height="210" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-7" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ViewerRunningConfigInfo</b><br></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;Mode: enum</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;Open: bool</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ShareId: string</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ServerMachine: string</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ClientMachines: string[]</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ConnectStr: string</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ConnectEP: string</p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=20;fontFamily=Helvetica;html=1;whiteSpace=wrap;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="80" y="1010" width="270" height="270" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-8" value="管理员" style="image;html=1;image=img/lib/clip_art/people/Suit_Man_128x128.png;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=20;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="-116.25" y="1400" width="80" height="80" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-9" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ViewerUpdateParamInfo</b><br></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;"><span style="background-color: initial;">+&nbsp;Open: bool</span></p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ShareId: string</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;Server: string</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;Clients: string[]<br></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=20;fontFamily=Helvetica;html=1;whiteSpace=wrap;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="405" y="1010" width="270" height="200" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-10" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-8" target="XBUbmlRP-4RHgawcbSf2-1"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="-106.25" y="1610" as="sourcePoint" /> | ||||
|             <mxPoint x="-56.25" y="1560" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-25" value="1、开启共享" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Comic Sans MS;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-10"> | ||||
|           <mxGeometry x="-0.1281" relative="1" as="geometry"> | ||||
|             <mxPoint as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-13" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.715;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-1" target="XBUbmlRP-4RHgawcbSf2-3"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="203.75" y="1460" as="sourcePoint" /> | ||||
|             <mxPoint x="113.75" y="1690" as="targetPoint" /> | ||||
|             <Array as="points"> | ||||
|               <mxPoint x="53.75" y="1580" /> | ||||
|             </Array> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-14" value="2、通知共享服务端开启共享" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Comic Sans MS;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-13"> | ||||
|           <mxGeometry x="-0.1219" y="2" relative="1" as="geometry"> | ||||
|             <mxPoint x="-36" y="-2" as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-15" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;entryX=-0.007;entryY=0.64;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-3" target="XBUbmlRP-4RHgawcbSf2-4"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="133.75" y="1670" as="sourcePoint" /> | ||||
|             <mxPoint x="197.75" y="1670" as="targetPoint" /> | ||||
|             <Array as="points"> | ||||
|               <mxPoint x="313.75" y="1790" /> | ||||
|             </Array> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-16" value="3、开启共享" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Comic Sans MS;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-15"> | ||||
|           <mxGeometry x="-0.0752" y="3" relative="1" as="geometry"> | ||||
|             <mxPoint y="-1" as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-18" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=-0.006;exitY=0.639;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.611;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-4" target="XBUbmlRP-4RHgawcbSf2-2"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="193.75" y="1920" as="sourcePoint" /> | ||||
|             <mxPoint x="143.75" y="2160" as="targetPoint" /> | ||||
|             <Array as="points"> | ||||
|               <mxPoint x="223.75" y="2020" /> | ||||
|             </Array> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-19" value="4、向服务器通知其它共享客户端,我已开启共享" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Comic Sans MS;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-18"> | ||||
|           <mxGeometry x="-0.0149" relative="1" as="geometry"> | ||||
|             <mxPoint x="49" y="-13" as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-21" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=-0.003;exitY=0.595;exitDx=0;exitDy=0;exitPerimeter=0;entryX=-0.001;entryY=0.641;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-2" target="XBUbmlRP-4RHgawcbSf2-3"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="372.2800000000002" y="2156.82" as="sourcePoint" /> | ||||
|             <mxPoint x="333.75" y="1650" as="targetPoint" /> | ||||
|             <Array as="points"> | ||||
|               <mxPoint x="-36.25" y="2140" /> | ||||
|               <mxPoint x="-36.25" y="2025.5" /> | ||||
|               <mxPoint x="-26.25" y="1765.5" /> | ||||
|             </Array> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-22" value="5、通知共享客户端" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Comic Sans MS;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-21"> | ||||
|           <mxGeometry x="-0.0152" y="1" relative="1" as="geometry"> | ||||
|             <mxPoint x="16" as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-23" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=0.002;exitY=0.642;exitDx=0;exitDy=0;exitPerimeter=0;entryX=-0.004;entryY=0.802;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-3" target="XBUbmlRP-4RHgawcbSf2-4"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="-246.25" y="1920" as="sourcePoint" /> | ||||
|             <mxPoint x="73.75" y="1940" as="targetPoint" /> | ||||
|             <Array as="points"> | ||||
|               <mxPoint x="153.75" y="1780" /> | ||||
|               <mxPoint x="223.75" y="1870" /> | ||||
|             </Array> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-24" value="6、客户端开启共享" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Comic Sans MS;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-23"> | ||||
|           <mxGeometry x="0.0589" y="2" relative="1" as="geometry"> | ||||
|             <mxPoint x="21" as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-26" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ViewerClientMessenger</b><br></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;</p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+ Server(ViewerRunningConfigInfo info): void</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;Heart(ViewerRunningConfigInfo info): void</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ProxyFromClient(ViewerProxyInfo viewerProxyInfo): void<br></p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ProxyFromServer(ViewerProxyInfo viewerProxyInfo): void<br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=20;fontFamily=Helvetica;html=1;whiteSpace=wrap;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="330.75" y="2930" width="560" height="210" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-27" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ViewerServerMessenger</b><br></p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;</p><hr style="font-size: 20px;"><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+ HeartNotify(ViewerRunningConfigInfo info): void</p><p style="margin: 0px 0px 0px 4px; font-size: 20px;">+&nbsp;ProxyNotify(ViewerProxyInfo viewerProxyInfo): void</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=20;fontFamily=Helvetica;html=1;whiteSpace=wrap;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="403.75" y="2650" width="490" height="180" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-28" value="RdpViewer" style="image;html=1;image=img/lib/clip_art/people/Suit_Man_128x128.png;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Comic Sans MS;fontSize=20;" vertex="1" parent="1"> | ||||
|           <mxGeometry x="-170" y="2360" width="80" height="80" as="geometry" /> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-29" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=-0.004;entryY=0.655;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=#000000;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-28" target="XBUbmlRP-4RHgawcbSf2-5"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="23.75" y="2600" as="sourcePoint" /> | ||||
|             <mxPoint x="73.75" y="2550" as="targetPoint" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-30" value="连接到客户端/服务端共享代理" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Architects Daughter;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-29"> | ||||
|           <mxGeometry x="-0.135" y="1" relative="1" as="geometry"> | ||||
|             <mxPoint as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-31" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=-0.006;exitY=0.685;exitDx=0;exitDy=0;exitPerimeter=0;fillColor=#f8cecc;strokeColor=#b85450;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-5" target="XBUbmlRP-4RHgawcbSf2-27"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="353.75" y="2510" as="sourcePoint" /> | ||||
|             <mxPoint x="193.75" y="2720" as="targetPoint" /> | ||||
|             <Array as="points"> | ||||
|               <mxPoint x="253.75" y="2580" /> | ||||
|               <mxPoint x="253.75" y="2720" /> | ||||
|             </Array> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-32" value="来自客户端代理,<br>向服务端通知共享服务端,<br>让它连接客户端" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Architects Daughter;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-31"> | ||||
|           <mxGeometry x="-0.0931" y="-3" relative="1" as="geometry"> | ||||
|             <mxPoint x="23" y="37" as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-33" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;entryX=-0.001;entryY=0.734;entryDx=0;entryDy=0;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryPerimeter=0;fillColor=#f8cecc;strokeColor=#b85450;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-27" target="XBUbmlRP-4RHgawcbSf2-26"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="373.75" y="2800" as="sourcePoint" /> | ||||
|             <mxPoint x="290.75" y="3092.5" as="targetPoint" /> | ||||
|             <Array as="points"> | ||||
|               <mxPoint x="263.75" y="2850" /> | ||||
|               <mxPoint x="263.75" y="3040" /> | ||||
|             </Array> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-34" value="来自客户端代理,<br>通知共享服务端,<br>让它连接客户端" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Architects Daughter;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-33"> | ||||
|           <mxGeometry x="-0.0821" relative="1" as="geometry"> | ||||
|             <mxPoint y="6" as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-35" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=0;exitY=0.75;exitDx=0;exitDy=0;fillColor=#f8cecc;strokeColor=#b85450;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-26"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="293.75" y="3100" as="sourcePoint" /> | ||||
|             <mxPoint x="403.75" y="2500" as="targetPoint" /> | ||||
|             <Array as="points"> | ||||
|               <mxPoint x="123.75" y="3000" /> | ||||
|               <mxPoint x="123.75" y="2650" /> | ||||
|             </Array> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-36" value="两个socket,<br>一个连接客户端,<br>一个连接RdpSession" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Comic Sans MS;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-35"> | ||||
|           <mxGeometry x="-0.0291" relative="1" as="geometry"> | ||||
|             <mxPoint as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-37" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;exitX=-0.001;exitY=0.627;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.001;entryY=0.877;entryDx=0;entryDy=0;entryPerimeter=0;fillColor=#e1d5e7;strokeColor=#9673a6;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-5" target="XBUbmlRP-4RHgawcbSf2-26"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="143.75" y="2640" as="sourcePoint" /> | ||||
|             <mxPoint x="193.75" y="3110" as="targetPoint" /> | ||||
|             <Array as="points"> | ||||
|               <mxPoint x="-6.25" y="2610" /> | ||||
|               <mxPoint x="-6.25" y="2990" /> | ||||
|             </Array> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-38" value="来自服务端代理,<br>通知共享服务端,<br>让它连接客户端" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Architects Daughter;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-37"> | ||||
|           <mxGeometry x="-0.1578" y="-3" relative="1" as="geometry"> | ||||
|             <mxPoint x="23" y="15" as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-39" value="" style="endArrow=classic;html=1;rounded=0;sketch=1;hachureGap=4;jiggle=2;curveFitting=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=16;fillColor=#e1d5e7;strokeColor=#9673a6;exitX=-0.002;exitY=0.889;exitDx=0;exitDy=0;exitPerimeter=0;entryX=-0.003;entryY=0.8;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="XBUbmlRP-4RHgawcbSf2-26" target="XBUbmlRP-4RHgawcbSf2-5"> | ||||
|           <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||||
|             <mxPoint x="303.75" y="3140" as="sourcePoint" /> | ||||
|             <mxPoint x="243.75" y="2500" as="targetPoint" /> | ||||
|             <Array as="points"> | ||||
|               <mxPoint x="-116.25" y="3030" /> | ||||
|               <mxPoint x="-116.25" y="2580" /> | ||||
|             </Array> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|         <mxCell id="XBUbmlRP-4RHgawcbSf2-40" value="两个socket,<br>一个连接客户端,<br>一个连接RdpSession" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=20;fontFamily=Comic Sans MS;" vertex="1" connectable="0" parent="XBUbmlRP-4RHgawcbSf2-39"> | ||||
|           <mxGeometry x="-0.0291" relative="1" as="geometry"> | ||||
|             <mxPoint as="offset" /> | ||||
|           </mxGeometry> | ||||
|         </mxCell> | ||||
|       </root> | ||||
|     </mxGraphModel> | ||||
|   </diagram> | ||||
| </mxfile> | ||||
| @@ -1,6 +1,7 @@ | ||||
| using cmonitor.api; | ||||
| using cmonitor.plugins.signIn.messenger; | ||||
| using cmonitor.plugins.viewer.messenger; | ||||
| using cmonitor.plugins.viewer.proxy; | ||||
| using cmonitor.plugins.viewer.report; | ||||
| using cmonitor.server; | ||||
| using common.libs.extends; | ||||
| @@ -12,28 +13,39 @@ namespace cmonitor.plugins.viewer | ||||
|     { | ||||
|         private readonly MessengerSender messengerSender; | ||||
|         private readonly SignCaching signCaching; | ||||
|         public ViewerApiController(MessengerSender messengerSender, SignCaching signCaching) | ||||
|         private readonly ViewerProxyCaching viewerProxyCaching; | ||||
|  | ||||
|         public ViewerApiController(MessengerSender messengerSender, SignCaching signCaching, ViewerProxyCaching viewerProxyCaching) | ||||
|         { | ||||
|             this.messengerSender = messengerSender; | ||||
|             this.signCaching = signCaching; | ||||
|             this.viewerProxyCaching = viewerProxyCaching; | ||||
|         } | ||||
|         public bool Update(ApiControllerParamsInfo param) | ||||
|         { | ||||
|             ViewerUpdateParamInfo viewer = param.Content.DeJson<ViewerUpdateParamInfo>(); | ||||
|             //去掉服务端 | ||||
|             //去掉服务端, | ||||
|             var list = viewer.Clients.ToList(); | ||||
|             list.Remove(viewer.Server); | ||||
|             viewer.Clients = list.ToArray(); | ||||
|             viewerProxyCaching.Remove(viewer.ShareId); | ||||
|  | ||||
|             if (signCaching.Get(viewer.Server, out SignCacheInfo cache) && cache.Connected) | ||||
|             { | ||||
|                 byte[] serverBytes = MemoryPackSerializer.Serialize(new ViewerConfigInfo | ||||
|                 ViewerRunningConfigInfo info = new ViewerRunningConfigInfo | ||||
|                 { | ||||
|                     Clients = viewer.Clients, | ||||
|                     ServerMachine = viewer.Server, | ||||
|                     ClientMachines = viewer.Clients, | ||||
|                     ConnectStr = string.Empty, | ||||
|                     Mode = ViewerMode.Server, | ||||
|                     Open = viewer.Open | ||||
|                 }); | ||||
|                 }; | ||||
|                 if (info.Open) | ||||
|                 { | ||||
|                     info.ShareId = viewerProxyCaching.Set(viewer.Server); | ||||
|                 } | ||||
|  | ||||
|                 byte[] serverBytes = MemoryPackSerializer.Serialize(info); | ||||
|                 _ = messengerSender.SendOnly(new MessageRequestWrap | ||||
|                 { | ||||
|                     Connection = cache.Connection, | ||||
| @@ -48,6 +60,8 @@ namespace cmonitor.plugins.viewer | ||||
|             public bool Open { get; set; } | ||||
|             public string Server { get; set; } = string.Empty; | ||||
|             public string[] Clients { get; set; } = Array.Empty<string>(); | ||||
|  | ||||
|             public string ShareId { get; set; } = string.Empty; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using cmonitor.config; | ||||
| using cmonitor.plugins.viewer.messenger; | ||||
| using cmonitor.plugins.viewer.proxy; | ||||
| using cmonitor.plugins.viewer.report; | ||||
| using cmonitor.startup; | ||||
| using common.libs; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using System.Reflection; | ||||
|  | ||||
| @@ -18,20 +20,30 @@ namespace cmonitor.plugins.viewer | ||||
|  | ||||
|             serviceCollection.AddSingleton<ViewerClientMessenger>(); | ||||
|  | ||||
|  | ||||
|             serviceCollection.AddSingleton<ViewerProxySignInArgs>(); | ||||
|             serviceCollection.AddSingleton<ViewerProxyClient>(); | ||||
|         } | ||||
|  | ||||
|         public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|              | ||||
|             serviceCollection.AddSingleton<ViewerProxyCaching>(); | ||||
|             serviceCollection.AddSingleton<ViewerServerMessenger>(); | ||||
|             serviceCollection.AddSingleton<ViewerApiController>(); | ||||
|             serviceCollection.AddSingleton<ViewerProxyServer>(); | ||||
|         } | ||||
|  | ||||
|         public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|             Logger.Instance.Info($"use viewer proxy server in client mode"); | ||||
|             ViewerProxyClient viewerProxyServer = serviceProvider.GetService<ViewerProxyClient>(); | ||||
|         } | ||||
|  | ||||
|         public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|             Logger.Instance.Info($"use viewer proxy server in server mode"); | ||||
|             ViewerProxyServer viewerProxyServer = serviceProvider.GetService<ViewerProxyServer>(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,8 @@ | ||||
| using cmonitor.plugins.signIn.messenger; | ||||
| using cmonitor.client; | ||||
| using cmonitor.client.running; | ||||
| using cmonitor.config; | ||||
| using cmonitor.plugins.signIn.messenger; | ||||
| using cmonitor.plugins.viewer.proxy; | ||||
| using cmonitor.plugins.viewer.report; | ||||
| using cmonitor.server; | ||||
| using MemoryPack; | ||||
| @@ -8,36 +12,54 @@ namespace cmonitor.plugins.viewer.messenger | ||||
|     public sealed class ViewerClientMessenger : IMessenger | ||||
|     { | ||||
|         private readonly ViewerReport viewerReport; | ||||
|         private readonly ViewerProxyClient viewerProxyClient; | ||||
|         private readonly Config config; | ||||
|         private readonly ClientSignInState clientSignInState; | ||||
|         private readonly RunningConfig runningConfig; | ||||
|  | ||||
|         public ViewerClientMessenger(ViewerReport viewerReport) | ||||
|         public ViewerClientMessenger(ViewerReport viewerReport, ViewerProxyClient viewerProxyClient, Config config, ClientSignInState clientSignInState, RunningConfig runningConfig) | ||||
|         { | ||||
|             this.viewerReport = viewerReport; | ||||
|             this.viewerProxyClient = viewerProxyClient; | ||||
|             this.config = config; | ||||
|             this.clientSignInState = clientSignInState; | ||||
|             this.runningConfig = runningConfig; | ||||
|         } | ||||
|  | ||||
|         [MessengerId((ushort)ViewerMessengerIds.Server)] | ||||
|         public void Server(IConnection connection) | ||||
|         { | ||||
|             ViewerConfigInfo viewerConfigInfo = MemoryPackSerializer.Deserialize<ViewerConfigInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             ViewerRunningConfigInfo viewerConfigInfo = MemoryPackSerializer.Deserialize<ViewerRunningConfigInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             viewerReport.Server(viewerConfigInfo); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         [MessengerId((ushort)ViewerMessengerIds.Client)] | ||||
|         public void Client(IConnection connection) | ||||
|         { | ||||
|             ViewerConfigInfo viewerConfigInfo = MemoryPackSerializer.Deserialize<ViewerConfigInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             viewerReport.Client(viewerConfigInfo); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         [MessengerId((ushort)ViewerMessengerIds.Heart)] | ||||
|         public void Heart(IConnection connection) | ||||
|         { | ||||
|             string connectStr = MemoryPackSerializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             viewerReport.Heart(connectStr); | ||||
|             ViewerRunningConfigInfo viewerConfigInfo = MemoryPackSerializer.Deserialize<ViewerRunningConfigInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             viewerReport.Heart(viewerConfigInfo); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         [MessengerId((ushort)ViewerMessengerIds.ProxyFromClient)] | ||||
|         public async Task ProxyFromClient(IConnection connection) | ||||
|         { | ||||
|             ViewerProxyInfo proxy = MemoryPackSerializer.Deserialize<ViewerProxyInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             proxy.TargetEP = runningConfig.Data.Viewer.ConnectEP; | ||||
|             await viewerProxyClient.Connect(proxy); | ||||
|         } | ||||
|  | ||||
|         [MessengerId((ushort)ViewerMessengerIds.ProxyFromServer)] | ||||
|         public async Task ProxyFromServer(IConnection connection) | ||||
|         { | ||||
|             ViewerProxyInfo proxy = MemoryPackSerializer.Deserialize<ViewerProxyInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             proxy.ProxyEP = $"{clientSignInState.Connection.Address.Address}:{config.Data.Client.Viewer.ProxyPort}"; | ||||
|             proxy.TargetEP = runningConfig.Data.Viewer.ConnectEP; | ||||
|             await viewerProxyClient.Connect(proxy); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public sealed class ViewerServerMessenger : IMessenger | ||||
|     { | ||||
|         private readonly MessengerSender messengerSender; | ||||
| @@ -50,35 +72,12 @@ namespace cmonitor.plugins.viewer.messenger | ||||
|         } | ||||
|  | ||||
|  | ||||
|         [MessengerId((ushort)ViewerMessengerIds.NotifyClient)] | ||||
|         public void NotifyClient(IConnection connection) | ||||
|         { | ||||
|             ViewerConfigInfo viewerConfigInfo = MemoryPackSerializer.Deserialize<ViewerConfigInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             string[] usernames = viewerConfigInfo.Clients; | ||||
|             viewerConfigInfo.Clients = Array.Empty<string>(); | ||||
|             viewerConfigInfo.Mode = ViewerMode.Client; | ||||
|  | ||||
|             byte[] bytes = MemoryPackSerializer.Serialize(viewerConfigInfo); | ||||
|             foreach (var item in usernames) | ||||
|             { | ||||
|                 if (signCaching.Get(item, out SignCacheInfo cache) && cache.Connected) | ||||
|                 { | ||||
|                     _ = messengerSender.SendOnly(new MessageRequestWrap | ||||
|                     { | ||||
|                         Connection = cache.Connection, | ||||
|                         MessengerId = (ushort)ViewerMessengerIds.Client, | ||||
|                         Payload = bytes | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [MessengerId((ushort)ViewerMessengerIds.NotifyHeart)] | ||||
|         public void NotifyHeart(IConnection connection) | ||||
|         [MessengerId((ushort)ViewerMessengerIds.HeartNotify)] | ||||
|         public void HeartNotify(IConnection connection) | ||||
|         { | ||||
|             ViewerConfigInfo viewerConfigInfo = MemoryPackSerializer.Deserialize<ViewerConfigInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             string[] usernames = viewerConfigInfo.Clients; | ||||
|             byte[] bytes = MemoryPackSerializer.Serialize(viewerConfigInfo.ConnectStr); | ||||
|             ViewerRunningConfigInfo viewerConfigInfo = MemoryPackSerializer.Deserialize<ViewerRunningConfigInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             string[] usernames = viewerConfigInfo.ClientMachines; | ||||
|             foreach (var item in usernames) | ||||
|             { | ||||
|                 if (signCaching.Get(item, out SignCacheInfo cache) && cache.Connected) | ||||
| @@ -87,10 +86,25 @@ namespace cmonitor.plugins.viewer.messenger | ||||
|                     { | ||||
|                         Connection = cache.Connection, | ||||
|                         MessengerId = (ushort)ViewerMessengerIds.Heart, | ||||
|                         Payload = bytes | ||||
|                         Payload = connection.ReceiveRequestWrap.Payload | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [MessengerId((ushort)ViewerMessengerIds.ProxyNotify)] | ||||
|         public void ProxyNotify(IConnection connection) | ||||
|         { | ||||
|             ViewerProxyInfo proxy = MemoryPackSerializer.Deserialize<ViewerProxyInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             if (signCaching.Get(proxy.ViewerMachine, out SignCacheInfo cache) && cache.Connected) | ||||
|             { | ||||
|                 _ = messengerSender.SendOnly(new MessageRequestWrap | ||||
|                 { | ||||
|                     Connection = cache.Connection, | ||||
|                     MessengerId = (ushort)ViewerMessengerIds.ProxyFromClient, | ||||
|                     Payload = connection.ReceiveRequestWrap.Payload | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,10 +3,13 @@ | ||||
|     public enum ViewerMessengerIds : ushort | ||||
|     { | ||||
|         Server = 1800, | ||||
|         Client = 1801, | ||||
|         NotifyClient = 1802, | ||||
|         Heart = 1803, | ||||
|         NotifyHeart = 1804, | ||||
|         Heart = 1801, | ||||
|         HeartNotify = 1802, | ||||
|  | ||||
|         ProxyFromClient = 1803, | ||||
|         ProxyFromServer = 1804, | ||||
|         ProxyNotify = 1805, | ||||
|  | ||||
|         None = 1899 | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										474
									
								
								cmonitor/plugins/viewer/proxy/ViewerProxy.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										474
									
								
								cmonitor/plugins/viewer/proxy/ViewerProxy.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,474 @@ | ||||
| using common.libs; | ||||
| using common.libs.extends; | ||||
| using MemoryPack; | ||||
| using System.Buffers; | ||||
| using System.Collections.Concurrent; | ||||
| using System.Net; | ||||
| using System.Net.Sockets; | ||||
| using System.Text; | ||||
|  | ||||
| namespace cmonitor.plugins.viewer.proxy | ||||
| { | ||||
|     public class ViewerProxy | ||||
|     { | ||||
|         private readonly WheelTimer<ConnectServerCache> wheelTimer = new WheelTimer<ConnectServerCache>(); | ||||
|         private readonly ConcurrentDictionary<uint, ConnectServerCache> connects = new ConcurrentDictionary<uint, ConnectServerCache>(); | ||||
|         private NumberSpaceUInt32 ns = new NumberSpaceUInt32(); | ||||
|         private SocketAsyncEventArgs acceptEventArg; | ||||
|  | ||||
|         Socket socket; | ||||
|  | ||||
|         public IPEndPoint LocalEndpoint => socket?.LocalEndPoint as IPEndPoint ?? new IPEndPoint(IPAddress.Any, 0); | ||||
|  | ||||
|         public ViewerProxy() | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         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); | ||||
|  | ||||
|                 acceptEventArg = new SocketAsyncEventArgs | ||||
|                 { | ||||
|                     UserToken = new AsyncUserToken | ||||
|                     { | ||||
|                         SourceSocket = socket | ||||
|                     }, | ||||
|                     SocketFlags = SocketFlags.None, | ||||
|                 }; | ||||
|  | ||||
|                 acceptEventArg.Completed += IO_Completed; | ||||
|                 StartAccept(acceptEventArg); | ||||
|  | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|             } | ||||
|         } | ||||
|         private void StartAccept(SocketAsyncEventArgs acceptEventArg) | ||||
|         { | ||||
|             acceptEventArg.AcceptSocket = null; | ||||
|             AsyncUserToken token = (AsyncUserToken)acceptEventArg.UserToken; | ||||
|             try | ||||
|             { | ||||
|                 if (token.SourceSocket.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 | ||||
|                 { | ||||
|                     SourceSocket = socket | ||||
|                 }; | ||||
|  | ||||
|                 SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs | ||||
|                 { | ||||
|                     UserToken = userToken, | ||||
|                     SocketFlags = SocketFlags.None, | ||||
|                 }; | ||||
|                 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) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 AsyncUserToken token = (AsyncUserToken)e.UserToken; | ||||
|  | ||||
|                 if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) | ||||
|                 { | ||||
|                     int offset = e.Offset; | ||||
|                     int length = e.BytesTransferred; | ||||
|                     if (token.Step == ViewerProxyStep.Request) | ||||
|                     { | ||||
|                         await ReadPacket(e, token, e.Buffer.AsMemory(0, length)); | ||||
|                         return; | ||||
|                     } | ||||
|                     await token.TargetSocket.SendAsync(e.Buffer.AsMemory(0, length), SocketFlags.None); | ||||
|                     if (token.SourceSocket.Available > 0) | ||||
|                     { | ||||
|                         while (token.SourceSocket.Available > 0) | ||||
|                         { | ||||
|                             length = token.SourceSocket.Receive(e.Buffer); | ||||
|                             if (length > 0) | ||||
|                             { | ||||
|                                 await token.TargetSocket.SendAsync(e.Buffer.AsMemory(0, length), SocketFlags.None); | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 CloseClientSocket(e); | ||||
|                                 return; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     if (token.SourceSocket.Connected == false) | ||||
|                     { | ||||
|                         CloseClientSocket(e); | ||||
|                         return; | ||||
|                     } | ||||
|  | ||||
|                     if (token.SourceSocket.ReceiveAsync(e) == false) | ||||
|                     { | ||||
|                         ProcessReceive(e); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     CloseClientSocket(e); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG) | ||||
|                     Logger.Instance.Error(ex); | ||||
|  | ||||
|                 CloseClientSocket(e); | ||||
|             } | ||||
|         } | ||||
|         private async Task ReadPacket(SocketAsyncEventArgs e, AsyncUserToken token, Memory<byte> data) | ||||
|         { | ||||
|             if (GetMachineName(data, out string machine)) | ||||
|             { | ||||
|                 uint id = ns.Increment(); | ||||
|                 byte[] tempData = new byte[data.Length]; | ||||
|                 data.CopyTo(tempData); | ||||
|                 ConnectServerCache cache = new ConnectServerCache { Id = id, Saea = e, Data = tempData }; | ||||
|                 connects.TryAdd(id, cache); | ||||
|  | ||||
|                 WheelTimerTimeout<ConnectServerCache> timeout = wheelTimer.NewTimeout(new WheelTimerTimeoutTask<ConnectServerCache> { State = cache, Callback = ConnectTimeout, }, 3000); | ||||
|                 cache.Timeout = timeout; | ||||
|  | ||||
|                 await Connect(machine, cache.Id); | ||||
|             } | ||||
|             else if (GetConnectId(data, out uint connectId)) | ||||
|             { | ||||
|                 if (connects.TryRemove(connectId, out ConnectServerCache cache)) | ||||
|                 { | ||||
|                     cache.Timeout.Cancel(); | ||||
|                     AsyncUserToken sourceToken = cache.Saea.UserToken as AsyncUserToken; | ||||
|                     sourceToken.Step = ViewerProxyStep.Forward; | ||||
|                     sourceToken.TargetSocket = token.SourceSocket; | ||||
|                     sourceToken.TargetSocket.KeepAlive(); | ||||
|  | ||||
|                     await sourceToken.TargetSocket.SendAsync(cache.Data, SocketFlags.None); | ||||
|  | ||||
|                     cache.Clear(); | ||||
|  | ||||
|                     if (sourceToken.SourceSocket.ReceiveAsync(cache.Saea) == false) | ||||
|                     { | ||||
|                         ProcessReceive(cache.Saea); | ||||
|                     } | ||||
|                     BindReceiveTarget(sourceToken); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 CloseClientSocket(e); | ||||
|             } | ||||
|         } | ||||
|         private void ConnectTimeout(WheelTimerTimeout<ConnectServerCache> timeout) | ||||
|         { | ||||
|             if (timeout.IsCanceled == false) | ||||
|             { | ||||
|                 if (connects.TryRemove(timeout.Task.State.Id, out ConnectServerCache cache)) | ||||
|                 { | ||||
|                     CloseClientSocket(cache.Saea); | ||||
|                     cache.Clear(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public virtual async Task Connect(string name, uint connectId) | ||||
|         { | ||||
|             await Task.CompletedTask; | ||||
|         } | ||||
|         public async Task Connect(ViewerProxyInfo viewerProxyInfo) | ||||
|         { | ||||
|             Socket proxySocket = null; | ||||
|             Socket targetSocket = null; | ||||
|             try | ||||
|             { | ||||
|                 if (IPEndPoint.TryParse(viewerProxyInfo.ProxyEP, out IPEndPoint proxyEP) == false) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|                 if (IPEndPoint.TryParse(viewerProxyInfo.TargetEP, out IPEndPoint targetEP) == false) | ||||
|                 { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 proxySocket = new Socket(proxyEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | ||||
|                 proxySocket.KeepAlive(); | ||||
|                 await proxySocket.ConnectAsync(proxyEP); | ||||
|  | ||||
|                 targetSocket = new Socket(targetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | ||||
|                 targetSocket.KeepAlive(); | ||||
|                 await targetSocket.ConnectAsync(targetEP); | ||||
|  | ||||
|                 int length = responseBytes.Length + 4; | ||||
|                 byte[] data = ArrayPool<byte>.Shared.Rent(length); | ||||
|                 responseBytes.AsMemory().CopyTo(data); | ||||
|                 viewerProxyInfo.ConnectId.ToBytes(data.AsMemory(responseBytes.Length)); | ||||
|                 await proxySocket.SendAsync(data.AsMemory(0, length)); | ||||
|                 ArrayPool<byte>.Shared.Return(data); | ||||
|  | ||||
|                 BindReceiveTarget(new AsyncUserToken { SourceSocket = proxySocket, TargetSocket = targetSocket }); | ||||
|                 BindReceiveTarget(new AsyncUserToken { SourceSocket = targetSocket, TargetSocket = proxySocket }); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|                 proxySocket?.SafeClose(); | ||||
|                 targetSocket?.SafeClose(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         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.TargetSocket.ReceiveAsync(readEventArgs) == false) | ||||
|                 { | ||||
|                     ProcessReceiveTarget(readEventArgs); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG) | ||||
|                     Logger.Instance.Error(ex); | ||||
|             } | ||||
|         } | ||||
|         private async void ProcessReceiveTarget(SocketAsyncEventArgs e) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 AsyncUserToken token = (AsyncUserToken)e.UserToken; | ||||
|  | ||||
|                 if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) | ||||
|                 { | ||||
|                     int offset = e.Offset; | ||||
|                     int length = e.BytesTransferred; | ||||
|  | ||||
|                     await token.SourceSocket.SendAsync(e.Buffer.AsMemory(0, length), SocketFlags.None); | ||||
|  | ||||
|                     if (token.TargetSocket.Available > 0) | ||||
|                     { | ||||
|                         while (token.TargetSocket.Available > 0) | ||||
|                         { | ||||
|                             length = token.TargetSocket.Receive(e.Buffer); | ||||
|                             if (length > 0) | ||||
|                             { | ||||
|                                 await token.SourceSocket.SendAsync(e.Buffer.AsMemory(0, length), SocketFlags.None); | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 CloseClientSocket(e); | ||||
|                                 return; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     if (token.TargetSocket.Connected == false) | ||||
|                     { | ||||
|                         CloseClientSocket(e); | ||||
|                         return; | ||||
|                     } | ||||
|  | ||||
|                     if (token.TargetSocket.ReceiveAsync(e) == false) | ||||
|                     { | ||||
|                         ProcessReceiveTarget(e); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     CloseClientSocket(e); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG) | ||||
|                     Logger.Instance.Error(ex); | ||||
|  | ||||
|                 CloseClientSocket(e); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         private void CloseClientSocket(SocketAsyncEventArgs e) | ||||
|         { | ||||
|             if (e == null) return; | ||||
|             AsyncUserToken token = e.UserToken as AsyncUserToken; | ||||
|             if (token.SourceSocket != null) | ||||
|             { | ||||
|                 token.Clear(); | ||||
|                 e.Dispose(); | ||||
|             } | ||||
|         } | ||||
|         public void Stop() | ||||
|         { | ||||
|             CloseClientSocket(acceptEventArg); | ||||
|         } | ||||
|  | ||||
|         private readonly byte[] endBytes = Encoding.UTF8.GetBytes("\r\n"); | ||||
|         private readonly byte[] startBytes = Encoding.UTF8.GetBytes("mstshash="); | ||||
|         private byte[] responseBytes = Encoding.UTF8.GetBytes("snltty="); | ||||
|         private bool GetMachineName(Memory<byte> memory, out string machine) | ||||
|         { | ||||
|             machine = string.Empty; | ||||
|  | ||||
|             int start = memory.Span.IndexOf(startBytes); | ||||
|             if (start < 0) return false; | ||||
|  | ||||
|             memory = memory.Slice(start); | ||||
|             int end = memory.Span.IndexOf(endBytes); | ||||
|             if (end < 0) return false; | ||||
|  | ||||
|             machine = Encoding.UTF8.GetString(memory.Span.Slice(startBytes.Length, end - startBytes.Length)); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|         private bool GetConnectId(Memory<byte> memory, out uint id) | ||||
|         { | ||||
|             var span = memory.Span; | ||||
|             id = 0; | ||||
|             if (span.Length != responseBytes.Length + 4 || span.Slice(0, responseBytes.Length).SequenceEqual(responseBytes) == false) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|             id = span.Slice(responseBytes.Length).ToUInt32(); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     [MemoryPackable] | ||||
|     public sealed partial class ViewerProxyInfo | ||||
|     { | ||||
|         public uint ConnectId { get; set; } | ||||
|  | ||||
|         public string ViewerMachine { get; set; } | ||||
|  | ||||
|         public string ProxyEP { get; set; } | ||||
|  | ||||
|         public string TargetEP { get; set; } | ||||
|     } | ||||
|  | ||||
|     public sealed class ConnectServerCache | ||||
|     { | ||||
|         public uint Id { get; set; } | ||||
|         public SocketAsyncEventArgs Saea { get; set; } | ||||
|         public WheelTimerTimeout<ConnectServerCache> Timeout { get; set; } | ||||
|  | ||||
|         public Memory<byte> Data { get; set; } | ||||
|  | ||||
|         public void Clear() | ||||
|         { | ||||
|         } | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public sealed class AsyncUserToken | ||||
|     { | ||||
|         public Socket SourceSocket { get; set; } | ||||
|         public Socket TargetSocket { get; set; } | ||||
|         public ViewerProxyStep Step { get; set; } = ViewerProxyStep.Request; | ||||
|  | ||||
|         public void Clear() | ||||
|         { | ||||
|             SourceSocket?.SafeClose(); | ||||
|             SourceSocket = null; | ||||
|  | ||||
|             TargetSocket?.SafeClose(); | ||||
|             TargetSocket = null; | ||||
|  | ||||
|             GC.Collect(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public enum ViewerProxyStep : byte | ||||
|     { | ||||
|         Request = 1, | ||||
|         Forward = 2 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										56
									
								
								cmonitor/plugins/viewer/proxy/ViewerProxyCaching.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								cmonitor/plugins/viewer/proxy/ViewerProxyCaching.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| using cmonitor.plugins.signIn.messenger; | ||||
| using cmonitor.server; | ||||
| using common.libs.extends; | ||||
| using System.Collections.Concurrent; | ||||
|  | ||||
| namespace cmonitor.plugins.viewer.proxy | ||||
| { | ||||
|     public sealed class ViewerProxyCaching | ||||
|     { | ||||
|         private readonly ConcurrentDictionary<string, string> viewerCache = new ConcurrentDictionary<string, string>(); | ||||
|  | ||||
|  | ||||
|         private readonly SignCaching signCaching; | ||||
|         public ViewerProxyCaching(SignCaching signCaching) | ||||
|         { | ||||
|             this.signCaching = signCaching; | ||||
|         } | ||||
|  | ||||
|         public string Set(string serverMachineName) | ||||
|         { | ||||
|             while (true) | ||||
|             { | ||||
|                 string id = GenerateUniqueId(); | ||||
|                 if (viewerCache.TryAdd(id, serverMachineName)) | ||||
|                 { | ||||
|                     return id; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         public bool Remove(string id) | ||||
|         { | ||||
|             return viewerCache.TryRemove(id, out _); | ||||
|         } | ||||
|  | ||||
|         public bool Get(string id, out IConnection connection) | ||||
|         { | ||||
|             connection = null; | ||||
|             if (viewerCache.TryGetValue(id, out string serverMachineName)) | ||||
|             { | ||||
|                 if (signCaching.Get(serverMachineName, out SignCacheInfo info)) | ||||
|                 { | ||||
|                     connection = info.Connection; | ||||
|                     return connection != null && connection.Connected; | ||||
|                 } | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         private string GenerateUniqueId() | ||||
|         { | ||||
|             byte[] bytes = Guid.NewGuid().ToByteArray(); | ||||
|             return Convert.ToBase64String(bytes).SubStr(0, 9); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										42
									
								
								cmonitor/plugins/viewer/proxy/ViewerProxyClient.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								cmonitor/plugins/viewer/proxy/ViewerProxyClient.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| using cmonitor.client; | ||||
| using cmonitor.client.running; | ||||
| using cmonitor.config; | ||||
| using cmonitor.plugins.viewer.messenger; | ||||
| using cmonitor.server; | ||||
| using MemoryPack; | ||||
|  | ||||
| namespace cmonitor.plugins.viewer.proxy | ||||
| { | ||||
|     public sealed class ViewerProxyClient : ViewerProxy | ||||
|     { | ||||
|         private readonly MessengerSender messengerSender; | ||||
|         private readonly ClientSignInState clientSignInState; | ||||
|         private readonly Config config; | ||||
|         private readonly RunningConfig runningConfig; | ||||
|  | ||||
|         public ViewerProxyClient(MessengerSender messengerSender, ClientSignInState clientSignInState, Config config, RunningConfig runningConfig) | ||||
|         { | ||||
|             this.messengerSender = messengerSender; | ||||
|             this.clientSignInState = clientSignInState; | ||||
|             this.config = config; | ||||
|             this.runningConfig = runningConfig; | ||||
|  | ||||
|             Start(0); | ||||
|         } | ||||
|  | ||||
|         public override async Task Connect(string name, uint connectId) | ||||
|         { | ||||
|             await messengerSender.SendOnly(new MessageRequestWrap | ||||
|             { | ||||
|                 Connection = clientSignInState.Connection, | ||||
|                 MessengerId = (ushort)ViewerMessengerIds.ProxyNotify, | ||||
|                 Payload = MemoryPackSerializer.Serialize(new ViewerProxyInfo | ||||
|                 { | ||||
|                     ConnectId = connectId, | ||||
|                     ProxyEP = $"{clientSignInState.Connection.LocalAddress.Address}:{LocalEndpoint.Port}", | ||||
|                     ViewerMachine = runningConfig.Data.Viewer.ServerMachine | ||||
|                 }) | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								cmonitor/plugins/viewer/proxy/ViewerProxyServer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								cmonitor/plugins/viewer/proxy/ViewerProxyServer.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| using cmonitor.config; | ||||
| using cmonitor.plugins.viewer.messenger; | ||||
| using cmonitor.server; | ||||
| using MemoryPack; | ||||
|  | ||||
| namespace cmonitor.plugins.viewer.proxy | ||||
| { | ||||
|     public sealed class ViewerProxyServer : ViewerProxy | ||||
|     { | ||||
|         private readonly MessengerSender messengerSender; | ||||
|         private readonly ViewerProxyCaching viewerProxyCaching; | ||||
|  | ||||
|         public ViewerProxyServer(MessengerSender messengerSender, Config config, ViewerProxyCaching viewerProxyCaching) | ||||
|         { | ||||
|             this.messengerSender = messengerSender; | ||||
|             this.viewerProxyCaching = viewerProxyCaching; | ||||
|  | ||||
|             Start(config.Data.Server.Viewer.ProxyPort); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public override async Task Connect(string name, uint connectId) | ||||
|         { | ||||
|             if (viewerProxyCaching.Get(name, out IConnection connection)) | ||||
|             { | ||||
|                 await messengerSender.SendOnly(new MessageRequestWrap | ||||
|                 { | ||||
|                     Connection = connection, | ||||
|                     MessengerId = (ushort)ViewerMessengerIds.ProxyFromServer, | ||||
|                     Payload = MemoryPackSerializer.Serialize(new ViewerProxyInfo | ||||
|                     { | ||||
|                         ConnectId = connectId, | ||||
|                         ProxyEP = string.Empty, | ||||
|                         ViewerMachine = string.Empty | ||||
|                     }) | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										24
									
								
								cmonitor/plugins/viewer/proxy/ViewerProxySignInArgs.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								cmonitor/plugins/viewer/proxy/ViewerProxySignInArgs.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| using cmonitor.client.args; | ||||
| using cmonitor.plugins.viewer.report; | ||||
| using common.libs.winapis; | ||||
|  | ||||
| namespace cmonitor.plugins.viewer.proxy | ||||
| { | ||||
|     public sealed class ViewerProxySignInArgs : ISignInArgs | ||||
|     { | ||||
|         public void Invoke(Dictionary<string, string> args) | ||||
|         { | ||||
|             string userName = GetUserName(); | ||||
|             args[ViewerConfigInfo.userNameKey] = userName; | ||||
|         } | ||||
|  | ||||
|         private string GetUserName() | ||||
|         { | ||||
|             if (OperatingSystem.IsWindows()) | ||||
|             { | ||||
|                 return Win32Interop.GetUserName(); | ||||
|             } | ||||
|             return string.Empty; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,22 +1,56 @@ | ||||
| using MemoryPack; | ||||
| using cmonitor.plugins.viewer.report; | ||||
| using MemoryPack; | ||||
| using System.Net; | ||||
| using System.Text.Json.Serialization; | ||||
|  | ||||
| namespace cmonitor.plugins.viewer.report | ||||
| { | ||||
|     public interface IViewer | ||||
|     { | ||||
|         public void Open(bool value, ViewerMode mode); | ||||
|         public void Open(bool value, ParamInfo info); | ||||
|         public string GetConnectString(); | ||||
|         public void SetConnectString(string connectStr); | ||||
|         public string GetConnectEP(string connectStr) | ||||
|         { | ||||
|             return string.Empty; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public sealed class ViewerConfigInfo | ||||
|     { | ||||
|         [JsonIgnore] | ||||
|         public const string userNameKey = "viewer-username"; | ||||
|  | ||||
|         public int ProxyPort { get; set; } = 1803; | ||||
|     } | ||||
|  | ||||
|     [MemoryPackable] | ||||
|     public sealed partial class ViewerConfigInfo | ||||
|     public sealed partial class ViewerRunningConfigInfo | ||||
|     { | ||||
|         public ViewerMode Mode { get; set; } | ||||
|         public bool Open { get; set; } | ||||
|         public string[] Clients { get; set; } = Array.Empty<string>(); | ||||
|  | ||||
|         public string ShareId { get; set; } = string.Empty; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 共享服务端机器名,在通知消息和代理时需要 | ||||
|         /// </summary> | ||||
|         public string ServerMachine { get; set; } = string.Empty; | ||||
|         /// <summary> | ||||
|         /// 共享客户端机器名列表 | ||||
|         /// </summary> | ||||
|         public string[] ClientMachines { get; set; } = Array.Empty<string>(); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 共享连接串,提供给客户端的共享桌面工具,去连接服务 | ||||
|         /// </summary> | ||||
|         public string ConnectStr { get; set; } = string.Empty; | ||||
|         /// <summary> | ||||
|         /// 共享服务的连接地址,在代理时需要 | ||||
|         /// 比如 B 是共享服务端,A是共享客户端 | ||||
|         /// 当连不上时,会需要代理,由B去连接A或者B去连接服务器,形成通道,那B这边还需要手动连接共享服务,就用这个去连 | ||||
|         /// </summary> | ||||
|         public string ConnectEP { get; set; } = string.Empty; | ||||
|     } | ||||
|  | ||||
|     public enum ViewerMode : byte | ||||
| @@ -24,4 +58,44 @@ namespace cmonitor.plugins.viewer.report | ||||
|         Client = 0, | ||||
|         Server = 1, | ||||
|     } | ||||
|  | ||||
|     public sealed class ParamInfo | ||||
|     { | ||||
|         public string ShareMkey { get; set; } = "cmonitor/share"; | ||||
|         public int ShareMLength { get; set; } = 10; | ||||
|         public int ShareItemMLength { get; set; } = 1024; | ||||
|         public int ShareIndex { get; set; } = 5; | ||||
|         public ViewerMode Mode { get; set; } = ViewerMode.Server; | ||||
|         public string GroupName { get; set; } = "snltty"; | ||||
|         public string ProxyServers { get; set; } = "127.0.0.1:1803"; | ||||
|     } | ||||
| } | ||||
|  | ||||
| namespace cmonitor.config | ||||
| { | ||||
|     public sealed partial class ConfigClientInfo | ||||
|     { | ||||
|         public ViewerConfigInfo Viewer { get; set; } = new ViewerConfigInfo(); | ||||
|     } | ||||
|  | ||||
|     public sealed partial class ConfigServerInfo | ||||
|     { | ||||
|         public ViewerConfigInfo Viewer { get; set; } = new ViewerConfigInfo(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| namespace cmonitor.client.running | ||||
| { | ||||
|     public sealed partial class RunningConfigInfo | ||||
|     { | ||||
|         private ViewerRunningConfigInfo viewer = new ViewerRunningConfigInfo(); | ||||
|         public ViewerRunningConfigInfo Viewer | ||||
|         { | ||||
|             get => viewer; set | ||||
|             { | ||||
|                 Updated++; | ||||
|                 viewer = value; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| namespace cmonitor.plugins.viewer.report | ||||
| using System.Net; | ||||
|  | ||||
| namespace cmonitor.plugins.viewer.report | ||||
| { | ||||
|     public sealed class ViewerLinux : IViewer | ||||
|     { | ||||
|         public void Open(bool value, ViewerMode mode) | ||||
|         public void Open(bool value, ParamInfo info) | ||||
|         { | ||||
|         } | ||||
|         public string GetConnectString() | ||||
| @@ -13,5 +15,10 @@ | ||||
|         { | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public string GetConnectEP(string connectStr) | ||||
|         { | ||||
|             return string.Empty; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| namespace cmonitor.plugins.viewer.report | ||||
| using System.Net; | ||||
|  | ||||
| namespace cmonitor.plugins.viewer.report | ||||
| { | ||||
|     public sealed class ViewerMacOS : IViewer | ||||
|     { | ||||
|         public void Open(bool value, ViewerMode mode) | ||||
|         public void Open(bool value, ParamInfo info) | ||||
|         { | ||||
|         } | ||||
|         public string GetConnectString() | ||||
| @@ -13,5 +15,10 @@ | ||||
|         { | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public string GetConnectEP(string connectStr) | ||||
|         { | ||||
|             return string.Empty; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| using cmonitor.client; | ||||
| using cmonitor.client.runningConfig; | ||||
| using cmonitor.client.report; | ||||
| using cmonitor.config; | ||||
| using cmonitor.libs; | ||||
| @@ -7,6 +6,10 @@ using cmonitor.plugins.viewer.messenger; | ||||
| using cmonitor.server; | ||||
| using common.libs; | ||||
| using MemoryPack; | ||||
| using cmonitor.client.running; | ||||
| using System.Net; | ||||
| using System.Text.Json; | ||||
| using cmonitor.plugins.viewer.proxy; | ||||
|  | ||||
| namespace cmonitor.plugins.viewer.report | ||||
| { | ||||
| @@ -20,22 +23,24 @@ namespace cmonitor.plugins.viewer.report | ||||
|         public string Name => "Viewer"; | ||||
|  | ||||
|         private ViewerReportInfo report = new ViewerReportInfo(); | ||||
|         private readonly IRunningConfig clientConfig; | ||||
|         private readonly RunningConfig runningConfig; | ||||
|         private readonly IViewer viewer; | ||||
|         private readonly ShareMemory shareMemory; | ||||
|         private ViewerConfigInfo viewerConfigInfo; | ||||
|         private readonly MessengerSender messengerSender; | ||||
|         private readonly ClientSignInState clientSignInState; | ||||
|         private readonly Config config; | ||||
|         private readonly ViewerProxyClient viewerProxyClient; | ||||
|  | ||||
|         public ViewerReport(Config config, IRunningConfig clientConfig, IViewer viewer, ShareMemory shareMemory, ClientSignInState clientSignInState, MessengerSender messengerSender) | ||||
|         public ViewerReport(Config config, RunningConfig runningConfig, IViewer viewer, ShareMemory shareMemory, ClientSignInState clientSignInState, MessengerSender messengerSender, ViewerProxyClient viewerProxyClient) | ||||
|         { | ||||
|             this.clientConfig = clientConfig; | ||||
|             this.config = config; | ||||
|             this.runningConfig = runningConfig; | ||||
|             this.viewer = viewer; | ||||
|             this.shareMemory = shareMemory; | ||||
|             this.clientSignInState = clientSignInState; | ||||
|             this.messengerSender = messengerSender; | ||||
|             this.viewerProxyClient = viewerProxyClient; | ||||
|  | ||||
|             viewerConfigInfo = clientConfig.Get(new ViewerConfigInfo { }); | ||||
|             clientSignInState.NetworkFirstEnabledHandle += () => | ||||
|             { | ||||
|                 Update(); | ||||
| @@ -46,7 +51,8 @@ namespace cmonitor.plugins.viewer.report | ||||
|         public object GetReports(ReportType reportType) | ||||
|         { | ||||
|             report.Value = Running(); | ||||
|             report.Mode = viewerConfigInfo.Mode; | ||||
|             report.Mode = runningConfig.Data.Viewer.Mode; | ||||
|             report.ShareId = runningConfig.Data.Viewer.ShareId; | ||||
|             if (reportType == ReportType.Full || report.Updated() || shareMemory.ReadVersionUpdated((int)ShareMemoryIndexs.Viewer)) | ||||
|             { | ||||
|                 return report; | ||||
| @@ -54,63 +60,68 @@ namespace cmonitor.plugins.viewer.report | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         private void Update() | ||||
|         { | ||||
|             if (viewerConfigInfo.Mode == ViewerMode.Server && viewerConfigInfo.Open && Running() == false) | ||||
|             { | ||||
|                 Server(viewerConfigInfo); | ||||
|             } | ||||
|         } | ||||
|         public void Server(ViewerConfigInfo info) | ||||
|         public void Server(ViewerRunningConfigInfo info) | ||||
|         { | ||||
|             if (info.Open) | ||||
|             { | ||||
|                 viewerConfigInfo = info; | ||||
|                 runningConfig.Data.Viewer = info; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 viewerConfigInfo.Open = info.Open; | ||||
|                 runningConfig.Data.Viewer.Open = info.Open; | ||||
|             } | ||||
|             runningConfig.Data.Update(); | ||||
|  | ||||
|             clientConfig.Set(viewerConfigInfo); | ||||
|             viewerConfigInfo.ConnectStr = string.Empty; | ||||
|             viewer.SetConnectString(viewerConfigInfo.ConnectStr); | ||||
|  | ||||
|             Task.Run(async () => | ||||
|             { | ||||
|                 shareMemory.AddAttribute((int)ShareMemoryIndexs.Viewer, ShareMemoryAttribute.Closed); | ||||
|                 shareMemory.RemoveAttribute((int)ShareMemoryIndexs.Viewer, ShareMemoryAttribute.Running); | ||||
|                 await Task.Delay(200); | ||||
|                 Close(); | ||||
|                 await HeartNotify(false); | ||||
|                 await Task.Delay(500); | ||||
|                 Open(); | ||||
|  | ||||
|                 viewer.Open(viewerConfigInfo.Open, viewerConfigInfo.Mode); | ||||
|                 if (viewerConfigInfo.Open) | ||||
|                 if (runningConfig.Data.Viewer.Open) | ||||
|                 { | ||||
|                     try | ||||
|                     runningConfig.Data.Viewer.ConnectStr = await GetNewConnectStr(); | ||||
|                     if (string.IsNullOrWhiteSpace(runningConfig.Data.Viewer.ConnectStr) == false) | ||||
|                     { | ||||
|                         for (int i = 0; i < 300; i++) | ||||
|                         { | ||||
|                             var attr = shareMemory.ReadAttribute((int)ShareMemoryIndexs.Viewer); | ||||
|                             if (shareMemory.ReadAttributeEqual((int)ShareMemoryIndexs.Viewer, ShareMemoryAttribute.Running)) | ||||
|                             { | ||||
|                                 viewerConfigInfo.ConnectStr = viewer.GetConnectString(); | ||||
|                                 if (string.IsNullOrWhiteSpace(viewerConfigInfo.ConnectStr) == false) | ||||
|                                 { | ||||
|                                     NotifyHeart(); | ||||
|                                     break; | ||||
|                                 } | ||||
|                             } | ||||
|                             await Task.Delay(100); | ||||
|                         } | ||||
|                     } | ||||
|                     catch (Exception ex) | ||||
|                     { | ||||
|                         Logger.Instance.Error(ex); | ||||
|                         UpdateConnectEP(); | ||||
|                         await HeartNotify(runningConfig.Data.Viewer.Open); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     NotifyClient(); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|         public void Heart(ViewerRunningConfigInfo info) | ||||
|         { | ||||
|             if (info.ConnectStr != runningConfig.Data.Viewer.ConnectStr) | ||||
|             { | ||||
|                 viewer.SetConnectString(ReplaceProxy(info.ConnectStr)); | ||||
|             } | ||||
|  | ||||
|             //未运行,或者不是client模式,或者状态不对,都需要重启一下 | ||||
|             bool restart = Running() != true | ||||
|                 || runningConfig.Data.Viewer.Mode != ViewerMode.Client | ||||
|                 || runningConfig.Data.Viewer.Open != info.Open; | ||||
|  | ||||
|             runningConfig.Data.Viewer = info; | ||||
|             runningConfig.Data.Update(); | ||||
|  | ||||
|             if (restart) | ||||
|             { | ||||
|                 RestartClient(); | ||||
|             } | ||||
|         } | ||||
|         private async Task HeartNotify(bool open) | ||||
|         { | ||||
|             ViewerRunningConfigInfo info = JsonSerializer.Deserialize<ViewerRunningConfigInfo>(JsonSerializer.Serialize(runningConfig.Data.Viewer)); | ||||
|             info.Mode = ViewerMode.Client; | ||||
|             info.Open = open; | ||||
|  | ||||
|             await messengerSender.SendOnly(new MessageRequestWrap | ||||
|             { | ||||
|                 Connection = clientSignInState.Connection, | ||||
|                 MessengerId = (ushort)ViewerMessengerIds.HeartNotify, | ||||
|                 Payload = MemoryPackSerializer.Serialize(info) | ||||
|             }); | ||||
|         } | ||||
|  | ||||
| @@ -118,58 +129,87 @@ namespace cmonitor.plugins.viewer.report | ||||
|         { | ||||
|             Task.Run(async () => | ||||
|             { | ||||
|                 shareMemory.AddAttribute((int)ShareMemoryIndexs.Viewer, ShareMemoryAttribute.Closed); | ||||
|                 shareMemory.RemoveAttribute((int)ShareMemoryIndexs.Viewer, ShareMemoryAttribute.Running); | ||||
|                 Close(); | ||||
|                 await Task.Delay(500); | ||||
|                 viewer.Open(viewerConfigInfo.Open, viewerConfigInfo.Mode); | ||||
|                 Open(); | ||||
|             }); | ||||
|         } | ||||
|         public void Client(ViewerConfigInfo info) | ||||
|         private void Update() | ||||
|         { | ||||
|             viewerConfigInfo = info; | ||||
|             clientConfig.Set(viewerConfigInfo); | ||||
|             viewer.SetConnectString(viewerConfigInfo.ConnectStr); | ||||
|             RestartClient(); | ||||
|         } | ||||
|         private void NotifyClient() | ||||
|         { | ||||
|             _ = messengerSender.SendOnly(new MessageRequestWrap | ||||
|             if (runningConfig.Data.Viewer.Mode == ViewerMode.Server && runningConfig.Data.Viewer.Open && Running() == false) | ||||
|             { | ||||
|                 Connection = clientSignInState.Connection, | ||||
|                 MessengerId = (ushort)ViewerMessengerIds.NotifyClient, | ||||
|                 Payload = MemoryPackSerializer.Serialize(viewerConfigInfo) | ||||
|             }); | ||||
|                 Server(runningConfig.Data.Viewer); | ||||
|             } | ||||
|         } | ||||
|         public void Heart(string connectStr) | ||||
|         { | ||||
|             bool restart = Running() == false || viewerConfigInfo.Mode == ViewerMode.Server; | ||||
|             viewerConfigInfo.ConnectStr = connectStr; | ||||
|             viewerConfigInfo.Mode = ViewerMode.Client; | ||||
|             viewerConfigInfo.Open = true; | ||||
|             clientConfig.Set(viewerConfigInfo); | ||||
|             viewer.SetConnectString(viewerConfigInfo.ConnectStr); | ||||
|  | ||||
|             if (restart) | ||||
|             { | ||||
|                 RestartClient(); | ||||
|             } | ||||
|         } | ||||
|         private void NotifyHeart() | ||||
|  | ||||
|         private async Task<string> GetNewConnectStr() | ||||
|         { | ||||
|             if (string.IsNullOrWhiteSpace(viewerConfigInfo.ConnectStr)) | ||||
|             try | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             if (viewerConfigInfo.Open && viewerConfigInfo.Mode == ViewerMode.Server && Running()) | ||||
|             { | ||||
|                 _ = messengerSender.SendOnly(new MessageRequestWrap | ||||
|                 for (int i = 0; i < 300; i++) | ||||
|                 { | ||||
|                     Connection = clientSignInState.Connection, | ||||
|                     MessengerId = (ushort)ViewerMessengerIds.NotifyHeart, | ||||
|                     Payload = MemoryPackSerializer.Serialize(viewerConfigInfo) | ||||
|                     if (shareMemory.ReadAttributeEqual((int)ShareMemoryIndexs.Viewer, ShareMemoryAttribute.Running)) | ||||
|                     { | ||||
|                         string connectStr = viewer.GetConnectString(); | ||||
|                         if (string.IsNullOrWhiteSpace(connectStr) == false) return connectStr; | ||||
|                     } | ||||
|                     await Task.Delay(100); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|             } | ||||
|             return string.Empty; | ||||
|         } | ||||
|         private string ReplaceProxy(string connectStr) | ||||
|         { | ||||
|             if (IPAddress.IsLoopback(clientSignInState.Connection.LocalAddress.Address)) | ||||
|             { | ||||
|                 Logger.Instance.Warning($"use Loopback address【{clientSignInState.Connection.LocalAddress.Address}】 as  viewer proxy,may fail"); | ||||
|                 Logger.Instance.Warning($"connect to the local or external network address of the cmonitor server,to fix this"); | ||||
|             } | ||||
|  | ||||
|             return connectStr | ||||
|                 .Replace("{ip}", clientSignInState.Connection.LocalAddress.Address.ToString()) | ||||
|             //.Replace("{port}", "12345"); | ||||
|                 .Replace("{port}", viewerProxyClient.LocalEndpoint.Port.ToString()); | ||||
|  | ||||
|         } | ||||
|         private void UpdateConnectEP() | ||||
|         { | ||||
|             string connectEP = viewer.GetConnectEP(runningConfig.Data.Viewer.ConnectStr); | ||||
|             runningConfig.Data.Viewer.ConnectEP = connectEP; | ||||
|             runningConfig.Data.Update(); | ||||
|         } | ||||
|  | ||||
|         private void Open() | ||||
|         { | ||||
|             if (runningConfig.Data.Viewer.Open) | ||||
|             { | ||||
|                 viewer.Open(runningConfig.Data.Viewer.Open, new ParamInfo | ||||
|                 { | ||||
|                     GroupName = runningConfig.Data.Viewer.ShareId, | ||||
|                     Mode = runningConfig.Data.Viewer.Mode, | ||||
|                     ProxyServers = string.Join(",", new string[] { | ||||
|                            $"{clientSignInState.Connection.Address.Address}:{config.Data.Client.Viewer.ProxyPort}" | ||||
|                     }), | ||||
|                     ShareIndex = (int)ShareMemoryIndexs.Viewer, | ||||
|                     ShareMkey = config.Data.Client.ShareMemoryKey, | ||||
|                     ShareMLength = config.Data.Client.ShareMemoryCount, | ||||
|                     ShareItemMLength = config.Data.Client.ShareMemorySize | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|         private void Close() | ||||
|         { | ||||
|             shareMemory.AddAttribute((int)ShareMemoryIndexs.Viewer, ShareMemoryAttribute.Closed); | ||||
|             shareMemory.RemoveAttribute((int)ShareMemoryIndexs.Viewer, ShareMemoryAttribute.Running); | ||||
|             runningConfig.Data.Viewer.ConnectStr = string.Empty; | ||||
|             viewer.SetConnectString(runningConfig.Data.Viewer.ConnectStr); | ||||
|             runningConfig.Data.Update(); | ||||
|         } | ||||
|  | ||||
|         private bool Running() | ||||
|         { | ||||
| @@ -183,20 +223,35 @@ namespace cmonitor.plugins.viewer.report | ||||
|             { | ||||
|                 while (true) | ||||
|                 { | ||||
|                     NotifyHeart(); | ||||
|                     bool heart = string.IsNullOrWhiteSpace(runningConfig.Data.Viewer.ConnectStr) == false | ||||
|                      && runningConfig.Data.Viewer.Open && runningConfig.Data.Viewer.Mode == ViewerMode.Server && Running(); | ||||
|  | ||||
|                     if (heart) | ||||
|                     { | ||||
|                         await HeartNotify(runningConfig.Data.Viewer.Open); | ||||
|                     } | ||||
|  | ||||
|                     await Task.Delay(5000); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     [MemoryPackable] | ||||
|     public sealed partial class ViewerHeartInfo | ||||
|     { | ||||
|         public string Server { get; set; } | ||||
|         public string ConnectStr { get; set; } | ||||
|     } | ||||
|  | ||||
|     public sealed class ViewerReportInfo : ReportInfo | ||||
|     { | ||||
|         public bool Value { get; set; } | ||||
|         public ViewerMode Mode { get; set; } | ||||
|         public string ShareId { get; set; } = string.Empty; | ||||
|         public override int HashCode() | ||||
|         { | ||||
|             return Value.GetHashCode() ^ Mode.GetHashCode(); | ||||
|             return Value.GetHashCode() ^ Mode.GetHashCode() ^ ShareId.GetHashCode(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| using cmonitor.config; | ||||
| using common.libs; | ||||
| using Microsoft.Win32; | ||||
| using System.Net; | ||||
| using System.Runtime.Versioning; | ||||
| using System.Text.Json; | ||||
| using System.Xml; | ||||
|  | ||||
| namespace cmonitor.plugins.viewer.report | ||||
| { | ||||
| @@ -13,17 +16,14 @@ namespace cmonitor.plugins.viewer.report | ||||
|         { | ||||
|             this.config = config; | ||||
|         } | ||||
|         public void Open(bool value, ViewerMode mode) | ||||
|         public void Open(bool value, ParamInfo info) | ||||
|         { | ||||
|             if (value) | ||||
|             { | ||||
|                 string command = $"start cmonitor.viewer.server.win.exe {config.Client.ShareMemoryKey} {config.Client.ShareMemoryCount} {config.Client.ShareMemorySize} {(int)ShareMemoryIndexs.Viewer} {(byte)mode}"; | ||||
|                 string str = JsonSerializer.Serialize(info); | ||||
|                 string command = $"start cmonitor.viewer.server.win.exe \"{str.Replace("\"","\\\"")}\""; | ||||
|                 CommandHelper.Windows(string.Empty, new string[] { command }, false); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 //CommandHelper.Windows(string.Empty, new string[] { $"taskkill /f /im cmonitor.viewer.server.win.exe" }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public string GetConnectString() | ||||
| @@ -34,5 +34,27 @@ namespace cmonitor.plugins.viewer.report | ||||
|         { | ||||
|             Registry.SetValue("HKEY_CURRENT_USER\\SOFTWARE\\Cmonitor", "viewerConnectStr", connectStr); | ||||
|         } | ||||
|  | ||||
|         public string GetConnectEP(string connectStr) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 XmlDocument xmlDoc = new XmlDocument(); | ||||
|                 xmlDoc.LoadXml(connectStr); | ||||
|  | ||||
|                 var nodes = xmlDoc.DocumentElement["C"]["T"].ChildNodes; | ||||
|  | ||||
|                 var node = nodes[nodes.Count - 3]; | ||||
|                 var p = node.Attributes["P"].Value; | ||||
|                 var n = node.Attributes["N"].Value; | ||||
|  | ||||
|                 return $"{n}:{p}"; | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|             } | ||||
|             return string.Empty; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using cmonitor.client.report; | ||||
| using cmonitor.config; | ||||
| using cmonitor.plugins.volume.report; | ||||
|  | ||||
| namespace cmonitor.plugins.volume.report | ||||
| { | ||||
| @@ -9,13 +10,11 @@ namespace cmonitor.plugins.volume.report | ||||
|         private VolumeReportInfo report = new VolumeReportInfo(); | ||||
|  | ||||
|         private readonly IVolume volume; | ||||
|         private VolumeConfigInfo config; | ||||
|         private Config config; | ||||
|  | ||||
|         public VolumeReport(Config config, IVolume volume) | ||||
|         { | ||||
|             this.config = config.Get(this.Name, new VolumeConfigInfo()); | ||||
|             config.Set(this.Name, this.config); | ||||
|  | ||||
|             this.config = config; | ||||
|             this.volume = volume; | ||||
|         } | ||||
|  | ||||
| @@ -23,7 +22,7 @@ namespace cmonitor.plugins.volume.report | ||||
|         { | ||||
|             report.Value = volume.GetVolume(); | ||||
|             report.Mute = volume.GetMute(); | ||||
|             if (config.MasterPeak) | ||||
|             if (config.Data.Client.Volume.MasterPeak) | ||||
|             { | ||||
|                 report.MasterPeak = volume.GetMasterPeak(); | ||||
|             } | ||||
| @@ -66,4 +65,13 @@ namespace cmonitor.plugins.volume.report | ||||
|     { | ||||
|         public bool MasterPeak { get; set; } | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| namespace cmonitor.config | ||||
| { | ||||
|     public sealed partial class ConfigClientInfo | ||||
|     { | ||||
|         public VolumeConfigInfo Volume { get; set; } = new VolumeConfigInfo(); | ||||
|     } | ||||
| } | ||||
| @@ -1,4 +1,5 @@ | ||||
| using MemoryPack; | ||||
| using cmonitor.plugins.wallpaper.report; | ||||
| using MemoryPack; | ||||
|  | ||||
| namespace cmonitor.plugins.wallpaper.report | ||||
| { | ||||
| @@ -14,3 +15,19 @@ namespace cmonitor.plugins.wallpaper.report | ||||
|         public string ImgUrl { get; set; } | ||||
|     } | ||||
| } | ||||
|  | ||||
| namespace cmonitor.client.running | ||||
| { | ||||
|     public sealed partial class RunningConfigInfo | ||||
|     { | ||||
|         private WallpaperConfigInfo wallpaper = new WallpaperConfigInfo(); | ||||
|         public WallpaperConfigInfo Wallpaper | ||||
|         { | ||||
|             get => wallpaper; set | ||||
|             { | ||||
|                 Updated++; | ||||
|                 wallpaper = value; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,9 +1,9 @@ | ||||
| using cmonitor.client; | ||||
| using cmonitor.client.runningConfig; | ||||
| using cmonitor.client.report; | ||||
| using cmonitor.config; | ||||
| using cmonitor.libs; | ||||
| using common.libs; | ||||
| using cmonitor.client.running; | ||||
|  | ||||
| namespace cmonitor.plugins.wallpaper.report | ||||
| { | ||||
| @@ -12,21 +12,19 @@ namespace cmonitor.plugins.wallpaper.report | ||||
|         public string Name => "Wallpaper"; | ||||
|  | ||||
|         private WallpaperReportInfo report = new WallpaperReportInfo(); | ||||
|         private readonly IRunningConfig clientConfig; | ||||
|         private readonly RunningConfig  runningConfig; | ||||
|         private readonly IWallpaper wallpaper; | ||||
|         private readonly ShareMemory shareMemory; | ||||
|         private WallpaperConfigInfo wallpaperConfig; | ||||
|  | ||||
|         public WallpaperReport(Config config, IRunningConfig clientConfig, IWallpaper wallpaper, ShareMemory shareMemory, ClientSignInState clientSignInState) | ||||
|         public WallpaperReport(Config config, RunningConfig runningConfig, IWallpaper wallpaper, ShareMemory shareMemory, ClientSignInState clientSignInState) | ||||
|         { | ||||
|             this.clientConfig = clientConfig; | ||||
|             this.runningConfig = runningConfig; | ||||
|             this.wallpaper = wallpaper; | ||||
|             this.shareMemory = shareMemory; | ||||
|  | ||||
|             wallpaperConfig = clientConfig.Get(new WallpaperConfigInfo { }); | ||||
|             clientSignInState.NetworkFirstEnabledHandle += () => | ||||
|             { | ||||
|                 Update(wallpaperConfig); | ||||
|                 Update(runningConfig.Data.Wallpaper); | ||||
|                 WallpaperTask(); | ||||
|             }; | ||||
|         } | ||||
| @@ -43,13 +41,12 @@ namespace cmonitor.plugins.wallpaper.report | ||||
|  | ||||
|         public void Update(WallpaperConfigInfo info) | ||||
|         { | ||||
|             wallpaperConfig = info; | ||||
|             runningConfig.Data.Wallpaper = info; | ||||
|             Task.Run(async () => | ||||
|             { | ||||
|                 clientConfig.Set(wallpaperConfig); | ||||
|                 shareMemory.AddAttribute((int)ShareMemoryIndexs.Wallpaper, ShareMemoryAttribute.Closed); | ||||
|                 await Task.Delay(100); | ||||
|                 wallpaper.Set(wallpaperConfig); | ||||
|                 wallpaper.Set(runningConfig.Data.Wallpaper); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
| @@ -65,11 +62,11 @@ namespace cmonitor.plugins.wallpaper.report | ||||
|             { | ||||
|                 while (true) | ||||
|                 { | ||||
|                     if (wallpaperConfig.Open) | ||||
|                     if (runningConfig.Data.Wallpaper.Open) | ||||
|                     { | ||||
|                         if (Running() == false) | ||||
|                         { | ||||
|                             Update(wallpaperConfig); | ||||
|                             Update(runningConfig.Data.Wallpaper); | ||||
|                         } | ||||
|                     } | ||||
|                     await Task.Delay(5000); | ||||
|   | ||||
| @@ -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.Client.ShareMemoryKey} {config.Client.ShareMemoryCount} {config.Client.ShareMemorySize} {(int)ShareMemoryIndexs.Keyboard} {(int)ShareMemoryIndexs.Wallpaper}" | ||||
|                         $"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}" | ||||
|                     },false); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -28,7 +28,6 @@ namespace cmonitor.plugins.wlan | ||||
|  | ||||
|         public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|             serviceProvider.GetServices<WlanReport>(); | ||||
|         } | ||||
|  | ||||
|         public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies) | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| using ManagedNativeWifi; | ||||
| using System.Net.NetworkInformation; | ||||
|  | ||||
| namespace cmonitor.plugins.wlan.report | ||||
| { | ||||
|   | ||||
| @@ -11,7 +11,7 @@ namespace cmonitor.server | ||||
|     /// </summary> | ||||
|     public interface IConnection | ||||
|     { | ||||
|         public string Name{ get; set; } | ||||
|         public string Name { get; set; } | ||||
|         /// <summary> | ||||
|         /// <summary> | ||||
|         /// 已连接 | ||||
| @@ -19,6 +19,7 @@ namespace cmonitor.server | ||||
|         public bool Connected { get; } | ||||
|  | ||||
|         public IPEndPoint Address { get; } | ||||
|         public IPEndPoint LocalAddress { get; } | ||||
|  | ||||
|         #region 接收数据 | ||||
|         /// <summary> | ||||
| @@ -77,10 +78,6 @@ namespace cmonitor.server | ||||
|         public void Return(); | ||||
|         #endregion | ||||
|  | ||||
|  | ||||
|         public Task WaitOne(); | ||||
|         public void Release(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public abstract class Connection : IConnection | ||||
| @@ -98,6 +95,7 @@ namespace cmonitor.server | ||||
|         /// 地址 | ||||
|         /// </summary> | ||||
|         public IPEndPoint Address { get; protected set; } | ||||
|         public IPEndPoint LocalAddress { get; protected set; } | ||||
|  | ||||
|  | ||||
|         #region 接收数据 | ||||
| @@ -210,61 +208,9 @@ namespace cmonitor.server | ||||
|         /// </summary> | ||||
|         public virtual void Disponse() | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 if (Semaphore != null) | ||||
|                 { | ||||
|                     if (locked) | ||||
|                     { | ||||
|                         locked = false; | ||||
|                         Semaphore.Release(); | ||||
|                     } | ||||
|                     Semaphore.Dispose(); | ||||
|                 } | ||||
|                 Semaphore = null; | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|             } | ||||
|             //ReceiveRequestWrap = null; | ||||
|             //ReceiveResponseWrap = null; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         SemaphoreSlim Semaphore = new SemaphoreSlim(1); | ||||
|         bool locked = false; | ||||
|         public virtual async Task WaitOne() | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 if (Semaphore != null) | ||||
|                 { | ||||
|                     locked = true; | ||||
|                     await Semaphore.WaitAsync(); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|         public virtual void Release() | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 if (Semaphore != null) | ||||
|                 { | ||||
|                     locked = false; | ||||
|                     Semaphore.Release(); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Instance.Error(ex); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -280,6 +226,13 @@ namespace cmonitor.server | ||||
|                 address = new IPEndPoint(new IPAddress(address.Address.GetAddressBytes()[^4..]), address.Port); | ||||
|             } | ||||
|             Address = address; | ||||
|  | ||||
|             IPEndPoint localaddress = TcpSocket.LocalEndPoint as IPEndPoint ?? new IPEndPoint(IPAddress.Any, 0); | ||||
|             if (localaddress.Address.AddressFamily == AddressFamily.InterNetworkV6 && localaddress.Address.IsIPv4MappedToIPv6) | ||||
|             { | ||||
|                 localaddress = new IPEndPoint(new IPAddress(localaddress.Address.GetAddressBytes()[^4..]), localaddress.Port); | ||||
|             } | ||||
|             LocalAddress = localaddress; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|   | ||||
| @@ -30,11 +30,16 @@ namespace cmonitor.server | ||||
|             this.serviceProvider = serviceProvider; | ||||
|         } | ||||
|  | ||||
|         public void LoadMessenger(Assembly[] assemblys) | ||||
|         public void LoadMessenger(Assembly[] assemblys, string[] pluginNames) | ||||
|         { | ||||
|             Type voidType = typeof(void); | ||||
|             Type midType = typeof(MessengerIdAttribute); | ||||
|             var types = ReflectionHelper.GetInterfaceSchieves(assemblys, typeof(IMessenger)).Distinct(); | ||||
|             if (pluginNames.Length > 0) | ||||
|             { | ||||
|                 types = types.Where(c => pluginNames.Any(d => c.FullName.Contains(d))); | ||||
|             } | ||||
|  | ||||
|             foreach (Type type in types) | ||||
|             { | ||||
|                 object obj = serviceProvider.GetService(type); | ||||
|   | ||||
| @@ -35,7 +35,7 @@ namespace cmonitor.server | ||||
|             if (loaded == false) | ||||
|             { | ||||
|                 MessengerResolver messengerResolver = serviceProvider.GetService<MessengerResolver>(); | ||||
|                 messengerResolver.LoadMessenger(assemblies); | ||||
|                 messengerResolver.LoadMessenger(assemblies, config.Data.Common.PluginNames); | ||||
|                 loaded = true; | ||||
|             } | ||||
|         } | ||||
| @@ -45,7 +45,7 @@ namespace cmonitor.server | ||||
|             if (loaded == false) | ||||
|             { | ||||
|                 MessengerResolver messengerResolver = serviceProvider.GetService<MessengerResolver>(); | ||||
|                 messengerResolver.LoadMessenger(assemblies); | ||||
|                 messengerResolver.LoadMessenger(assemblies, config.Data.Common.PluginNames); | ||||
|                 loaded = true; | ||||
|             } | ||||
|  | ||||
| @@ -53,7 +53,7 @@ namespace cmonitor.server | ||||
|             //服务 | ||||
|             TcpServer tcpServer = serviceProvider.GetService<TcpServer>(); | ||||
|             tcpServer.Start(); | ||||
|             Logger.Instance.Info($"server listen:{config.Server.ServicePort}"); | ||||
|             Logger.Instance.Info($"server listen:{config.Data.Server.ServicePort}"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -31,7 +31,7 @@ namespace cmonitor.server | ||||
|  | ||||
|         private Socket BindAccept() | ||||
|         { | ||||
|             IPEndPoint localEndPoint = new IPEndPoint(NetworkHelper.IPv6Support ? IPAddress.IPv6Any : IPAddress.Any, config.Server.ServicePort); | ||||
|             IPEndPoint localEndPoint = new IPEndPoint(NetworkHelper.IPv6Support ? IPAddress.IPv6Any : IPAddress.Any, config.Data.Server.ServicePort); | ||||
|             Socket socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | ||||
|             socket.IPv6Only(localEndPoint.AddressFamily, false); | ||||
|             socket.ReuseBind(localEndPoint); | ||||
| @@ -48,7 +48,7 @@ namespace cmonitor.server | ||||
|             acceptEventArg.Completed += IO_Completed; | ||||
|             StartAccept(acceptEventArg); | ||||
|  | ||||
|             socketUdp = new UdpClient(new IPEndPoint(IPAddress.Any, config.Server.ServicePort)); | ||||
|             socketUdp = new UdpClient(new IPEndPoint(IPAddress.Any, config.Data.Server.ServicePort)); | ||||
|             //socketUdp.JoinMulticastGroup(config.BroadcastIP); | ||||
|             socketUdp.Client.EnableBroadcast = true; | ||||
|             socketUdp.Client.WindowsUdpBug(); | ||||
| @@ -74,9 +74,9 @@ namespace cmonitor.server | ||||
|                     { | ||||
|                         dic.Add(item, new BroadcastEndpointInfo | ||||
|                         { | ||||
|                             Web = config.Server.WebPort, | ||||
|                             Api = config.Server.ApiPort, | ||||
|                             Service = config.Server.ServicePort | ||||
|                             Web = config.Data.Server.WebPort, | ||||
|                             Api = config.Data.Server.ApiPort, | ||||
|                             Service = config.Data.Server.ServicePort | ||||
|                         }); | ||||
|                     } | ||||
|  | ||||
|   | ||||
							
								
								
									
										14
									
								
								cmonitor/server/config/Config.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								cmonitor/server/config/Config.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| namespace cmonitor.config | ||||
| { | ||||
|     public sealed partial class ConfigInfo | ||||
|     { | ||||
|         public ConfigServerInfo Server { get; set; } = new ConfigServerInfo(); | ||||
|     } | ||||
|     public sealed partial class ConfigServerInfo | ||||
|     { | ||||
|         public int WebPort { get; set; } = 1800; | ||||
|         public string WebRoot { get; set; } = "./web/"; | ||||
|         public int ApiPort { get; set; } = 1801; | ||||
|         public int ServicePort { get; set; } = 1802; | ||||
|     } | ||||
| } | ||||
| @@ -8,18 +8,23 @@ namespace cmonitor.startup | ||||
|     public static class StartupTransfer | ||||
|     { | ||||
|         static List<IStartup> startups; | ||||
|         public static void Init() | ||||
|         public static void Init(Config config) | ||||
|         { | ||||
|             startups = ReflectionHelper.GetInterfaceSchieves(typeof(IStartup)).Select(c => Activator.CreateInstance(c) as IStartup).ToList(); | ||||
|             var types = ReflectionHelper.GetInterfaceSchieves(typeof(IStartup)); | ||||
|             if (config.Data.Common.PluginNames.Length > 0) | ||||
|             { | ||||
|                 types = types.Where(c => config.Data.Common.PluginNames.Any(d => c.FullName.Contains(d))); | ||||
|             } | ||||
|             startups = types.Select(c => Activator.CreateInstance(c) as IStartup).ToList(); | ||||
|         } | ||||
|  | ||||
|         public static void Add(ServiceCollection serviceCollection, Config config, Assembly[] assemblies) | ||||
|         { | ||||
|             foreach (var startup in startups) | ||||
|             { | ||||
|                 if (config.Common.Modes.Contains("client")) | ||||
|                 if (config.Data.Common.Modes.Contains("client")) | ||||
|                     startup.AddClient(serviceCollection, config, assemblies); | ||||
|                 if (config.Common.Modes.Contains("server")) | ||||
|                 if (config.Data.Common.Modes.Contains("server")) | ||||
|                     startup.AddServer(serviceCollection, config, assemblies); | ||||
|             } | ||||
|         } | ||||
| @@ -27,9 +32,9 @@ namespace cmonitor.startup | ||||
|         { | ||||
|             foreach (var startup in startups) | ||||
|             { | ||||
|                 if (config.Common.Modes.Contains("client")) | ||||
|                 if (config.Data.Common.Modes.Contains("client")) | ||||
|                     startup.UseClient(serviceProvider, config, assemblies); | ||||
|                 if (config.Common.Modes.Contains("server")) | ||||
|                 if (config.Data.Common.Modes.Contains("server")) | ||||
|                     startup.UseServer(serviceProvider, config, assemblies); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -26,7 +26,7 @@ namespace cmonitor.web | ||||
|                 { | ||||
|                     HttpListener http = new HttpListener(); | ||||
|                     http.IgnoreWriteExceptions = true; | ||||
|                     http.Prefixes.Add($"http://+:{config.Server.WebPort}/"); | ||||
|                     http.Prefixes.Add($"http://+:{config.Data.Server.WebPort}/"); | ||||
|                     http.Start(); | ||||
|  | ||||
|                     http.BeginGetContext(Callback, http); | ||||
| @@ -53,7 +53,7 @@ namespace cmonitor.web | ||||
|                 if (path == "/") path = "index.html"; | ||||
|  | ||||
|  | ||||
|                 path = Path.Join(config.Server.WebRoot, path); | ||||
|                 path = Path.Join(config.Data.Server.WebRoot, path); | ||||
|                 if (File.Exists(path)) | ||||
|                 { | ||||
|                     byte[] bytes = File.ReadAllBytes(path); | ||||
|   | ||||
| @@ -25,7 +25,7 @@ namespace cmonitor.web | ||||
|         { | ||||
|             IWebServer webServer = serviceProvider.GetService<IWebServer>(); | ||||
|             webServer.Start(); | ||||
|             Logger.Instance.Info($"web listen:{config.Server.WebPort}"); | ||||
|             Logger.Instance.Info($"web listen:{config.Data.Server.WebPort}"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -31,7 +31,9 @@ namespace common.libs | ||||
|  | ||||
|         private static void Windows(string fileName) | ||||
|         { | ||||
|             string content = $@"@echo off | ||||
|             try | ||||
|             { | ||||
|                 string content = $@"@echo off | ||||
| cd  ""%CD%"" | ||||
| for /f ""tokens=4,5 delims=. "" %%a in ('ver') do if %%a%%b geq 60 goto new | ||||
|  | ||||
| @@ -49,9 +51,13 @@ 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"); | ||||
|                 System.IO.File.WriteAllText("firewall.bat", content); | ||||
|                 CommandHelper.Execute("firewall.bat", string.Empty, new string[0]); | ||||
|                 System.IO.File.Delete("firewall.bat"); | ||||
|             } | ||||
|             catch (Exception) | ||||
|             { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -10,6 +10,7 @@ using System.Runtime.Serialization; | ||||
| using System.Security.Principal; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using static cmonitor.libs.winapis.WTSAPI32; | ||||
| using static common.libs.winapis.ADVAPI32; | ||||
| using static common.libs.winapis.Kernel32; | ||||
| using static common.libs.winapis.NetApi32; | ||||
| @@ -397,6 +398,24 @@ namespace common.libs.winapis | ||||
|             return currentUsername == "NT AUTHORITY\\SYSTEM"; | ||||
|         } | ||||
|  | ||||
|         public static string GetUserName() | ||||
|         { | ||||
|             // 获取活动的控制台会话 ID | ||||
|             uint sessionId = WTSGetActiveConsoleSessionId(); | ||||
|  | ||||
|             IntPtr buffer; | ||||
|             uint bytesReturned; | ||||
|             string userName = ""; | ||||
|  | ||||
|             // 获取用户名 | ||||
|             if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSUserName, out buffer, out bytesReturned)) | ||||
|             { | ||||
|                 userName = Marshal.PtrToStringAnsi(buffer); | ||||
|                 WTSFreeMemory(buffer); | ||||
|             } | ||||
|  | ||||
|             return userName; | ||||
|         } | ||||
|  | ||||
|         public static void SetHandleBlockKill(IntPtr handle) | ||||
|         { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 snltty
					snltty