Browse Source

add Ssh client to egmessage protocol tools

master
jkpete 6 months ago
parent
commit
b644bf006c
  1. 1
      EGFramework.csproj
  2. 47
      Example/UsingTest/Script/EGSaveTest.cs
  3. 3
      addons/EGFramework/Module/EGMessage.cs
  4. 179
      addons/EGFramework/Module/ProtocolTools/EGSsh.cs

1
EGFramework.csproj

@ -18,5 +18,6 @@ @@ -18,5 +18,6 @@
<PackageReference Include="BACnet" Version="2.0.4" />
<PackageReference Include="MySql.Data" Version="9.1.0" />
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
</ItemGroup>
</Project>

47
Example/UsingTest/Script/EGSaveTest.cs

@ -3,6 +3,7 @@ using System.Linq; @@ -3,6 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using Godot;
using LiteDB;
using Renci.SshNet;
namespace EGFramework.Examples.Test{
public partial class EGSaveTest : Node,IEGFramework
@ -11,10 +12,23 @@ namespace EGFramework.Examples.Test{ @@ -11,10 +12,23 @@ namespace EGFramework.Examples.Test{
public override void _Ready()
{
this.Label = this.GetNode<Label>("Label");
this.EGEnabledThread();
this.ExecuteAfterSecond(TestMainThreadFunc,2.0f);
// this.EGEnabledThread();
// this.ExecuteAfterSecond(TestMainThreadFunc,2.0f);new PrivateKeyFile("../../../.ssh/id_ed25519")
//base._Ready();
//TestCode();
this.EGEnabledProtocolTool<EGSsh>();
this.EGOnMessage<EasyMessage>();
// this.EGRegisterMessageEvent<EasyMessage>((e,sender)=>{
// });
TestSsh();
}
public async void TestSsh(){
await this.EGSsh().ConnectSsh("127.0.0.1","jkpete",new PrivateKeyFile("../../../.ssh/id_ed25519"));
this.EGSendMessage(new EasyMessage(){sendString = "ls -la"},"127.0.0.1",ProtocolType.SSHClient);
}
public async void TestThread(){
@ -161,6 +175,35 @@ namespace EGFramework.Examples.Test{ @@ -161,6 +175,35 @@ namespace EGFramework.Examples.Test{
return false;
}
}
}
public class EasyMessage : IResponse, IRequest
{
public byte[] sendByte = null;
public string sendString = null;
public byte[] ToProtocolByteData()
{
return sendByte;
}
public string ToProtocolData()
{
return sendString;
}
public bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
GD.Print("[String]"+protocolData);
GD.Print("[Bytes]"+protocolBytes);
return true;
}
catch (System.Exception)
{
throw;
}
}
}
}

3
addons/EGFramework/Module/EGMessage.cs

@ -321,7 +321,8 @@ namespace EGFramework @@ -321,7 +321,8 @@ namespace EGFramework
FileStream = 0x50,
MemoryStream = 0x60,
MQTTClient = 0x70,
Bacnet = 0x80
Bacnet = 0x80,
SSHClient = 0x90
//MQTT,SSH,etc...
}
}

179
addons/EGFramework/Module/ProtocolTools/EGSsh.cs

@ -0,0 +1,179 @@ @@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Godot;
using Renci.SshNet;
namespace EGFramework{
public class EGSsh : IModule, IProtocolSend, IProtocolReceived
{
public Dictionary<string,SshClient> SshClientDevices { set; get; } = new Dictionary<string, SshClient>();
public string ErrorLogs { set; get; }
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public Queue<ResponseMsg> ResponseMsgs { set; get; } = new Queue<ResponseMsg>();
public int TimeOutDelay = 5000;
public void Init()
{
this.EGRegisterSendAction(request=>{
if(request.protocolType == ProtocolType.SSHClient){
if(request.req.ToProtocolData() != null && request.req.ToProtocolData() != ""){
this.SendStringData(request.sender,request.req.ToProtocolData());
}else if(request.req.ToProtocolByteData() != null && request.req.ToProtocolByteData().Length > 0){
this.SendByteData(request.sender,request.req.ToProtocolByteData());
}
}
});
}
/// <summary>
/// Connect Ssh Server by using username and passwd
/// </summary>
public async Task<bool> ConnectSsh(string host,string username,string password){
try{
//Reconnect
if(SshClientDevices.ContainsKey(host)){
if(SshClientDevices[host].IsConnected){
return true;
}else{
CancellationTokenSource sourceReconnect = new CancellationTokenSource();
CancellationToken tokenReconnect = sourceReconnect.Token;
tokenReconnect.Register(() => Godot.GD.Print("Ssh connect timeout!"));
await SshClientDevices[host].ConnectAsync(tokenReconnect);
if(!SshClientDevices[host].IsConnected){
return false;
}else{
return true;
}
}
}
//First Connect
SshClient client = new SshClient(host, username, password);
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
token.Register(() => Godot.GD.Print("Ssh connect timeout!"));
source.CancelAfter(TimeOutDelay);
await client.ConnectAsync(token);
if(!client.IsConnected){
return false;
}else{
SshClientDevices.Add(host,client);
}
return true;
}
catch(Exception e){
ErrorLogs = "[ssh connect error]" + e.ToString();
return false;
}
}
/// <summary>
/// Connect Ssh Server by using private key file
/// </summary>
public async Task<bool> ConnectSsh(string host,string username,PrivateKeyFile keyFile){
try{
//Reconnect
if(SshClientDevices.ContainsKey(host)){
if(SshClientDevices[host].IsConnected){
return true;
}else{
CancellationTokenSource sourceReconnect = new CancellationTokenSource();
CancellationToken tokenReconnect = sourceReconnect.Token;
tokenReconnect.Register(() => Godot.GD.Print("Ssh connect timeout!"));
await SshClientDevices[host].ConnectAsync(tokenReconnect);
if(!SshClientDevices[host].IsConnected){
return false;
}else{
return true;
}
}
}
//First Connect
SshClient client = new SshClient(host, username, keyFile);
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
token.Register(() => Godot.GD.Print("Ssh connect timeout!"));
source.CancelAfter(TimeOutDelay);
await client.ConnectAsync(token);
if(!client.IsConnected){
return false;
}else{
SshClientDevices.Add(host,client);
}
return true;
}
catch(Exception e){
ErrorLogs = "[ssh connect error]" + e.ToString();
return false;
}
}
public void DisconnectSsh(string host){
if(SshClientDevices.ContainsKey(host)){
if (SshClientDevices[host].IsConnected)
{
SshClientDevices[host].Disconnect();
SshClientDevices[host].Dispose();
SshClientDevices.Remove(host);
}
}
}
public Queue<ResponseMsg> GetReceivedMsg()
{
return ResponseMsgs;
}
public void SendByteData(string destination, byte[] data)
{
if(SshClientDevices.ContainsKey(destination)){
if (SshClientDevices[destination].IsConnected)
{
SshCommand cmd = SshClientDevices[destination].RunCommand(StringEncoding.GetString(data));
ResponseMsg receivedMsgs = new ResponseMsg(cmd.Result,StringEncoding.GetBytes(cmd.Result),destination, ProtocolType.SSHClient);
ResponseMsgs.Enqueue(receivedMsgs);
}
}
}
public void SendStringData(string destination, string data)
{
if(SshClientDevices.ContainsKey(destination)){
if (SshClientDevices[destination].IsConnected)
{
SshCommand cmd = SshClientDevices[destination].RunCommand(data);
ResponseMsg receivedMsgs = new ResponseMsg(cmd.Result,StringEncoding.GetBytes(cmd.Result),destination, ProtocolType.SSHClient);
ResponseMsgs.Enqueue(receivedMsgs);
}
}
}
public void SetEncoding(Encoding textEncoding)
{
this.StringEncoding = textEncoding;
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
//throw new System.NotImplementedException();
}
}
public static class CanGetEGSShClientExtension{
public static EGSsh EGSsh(this IEGFramework self){
return self.GetModule<EGSsh>();
}
public static SshClient EGGetSshClient(this IEGFramework self,string host){
return self.GetModule<EGSsh>().SshClientDevices[host];
}
}
}
Loading…
Cancel
Save