using System.Diagnostics; using System.Runtime.InteropServices; using System.Text.Json; using Common; namespace LocalServer; // enum StateWhenMsg // { // Authority = 0, // ConfigInfo = 1, // LocalPackAndUpload = 2, // RemoteUnPackAndRelease = 3, // } public abstract class StateHelpBase( LocalSyncServer context, SyncProcessStep step = SyncProcessStep.Connect ) { protected readonly LocalSyncServer Context = context; protected readonly SyncProcessStep Step = step; public SyncMsg CreateErrMsg(string Body) { return new SyncMsg(SyncMsgType.Error, Step, Body); } public SyncMsg CreateMsg(string body, SyncMsgType type = SyncMsgType.General) { return new SyncMsg(type, Step, body); } public bool ReceiveLocalMsg(byte[] msg) { var syncMsg = JsonSerializer.Deserialize(msg) ?? throw new NullReferenceException("msg is null"); if (syncMsg.Step != Step) { throw new Exception("Sync step error!"); } HandleLocalMsg(syncMsg); return true; } public bool ReceiveRemoteMsg(byte[] bytes) { var msg = AESHelper.DecryptStringFromBytes_Aes(bytes); var syncMsg = JsonSerializer.Deserialize(msg) ?? throw new NullReferenceException("msg is null"); if (syncMsg.Step != Step) { throw new Exception("Sync step error!"); } HandleLocalMsg(syncMsg); return true; } protected abstract void HandleRemoteMsg(SyncMsg msg); protected abstract void HandleLocalMsg(SyncMsg msg); } /// /// 0. 链接验证 /// /// public class ConnectAuthorityHelper(LocalSyncServer context) : StateHelpBase(context, SyncProcessStep.Connect) { // 如果密码错误,那么就直接关闭连接,不会进入这个方法 protected override void HandleRemoteMsg(SyncMsg msg) { //将remote的消息传递到前端界面 Context.LocalPipe.SendMsg(msg); //下一步 var deployHelper = new DeployHelper(Context); Context.StateHelper = deployHelper; deployHelper.DeployProcess(); } protected override void HandleLocalMsg(SyncMsg msg) { //收到配置文件 var config = JsonSerializer.Deserialize(msg.Body); Context.SyncConfig = config; Task.Run(async () => { var rs = Context.RemotePipe.Work( (byte[] b) => { return Context.StateHelper.ReceiveRemoteMsg(b); }, Context.NotNullSyncConfig.RemoteUrl + "/websoc" ); await foreach (var r in rs) { if (r == 0) { await Context.RemotePipe.SendMsg( CreateMsg(Context.NotNullSyncConfig.RemotePwd) ); } } }); } } /// /// 1. 执行发布步骤 /// /// public class DeployHelper(LocalSyncServer context) : StateHelpBase(context, SyncProcessStep.DeployProject) { public void DeployProcess() { if (Context.NotNullSyncConfig.IsDeployProject == false) { Context.LocalPipe.SendMsg(CreateMsg("配置为不发布跳过此步骤")).Wait(); var h = new DiffFileAndPackHelper(Context); Context.StateHelper = h; h.DiffProcess(); } else { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { ProcessStartInfo startInfo = new() { FileName = "cmd.exe", // The command to execute (can be any command line tool) Arguments = $"msdeploy.exe -verb:sync -source:contentPath={Context.NotNullSyncConfig.LocalProjectAbsolutePath} -dest:contentPath={Context.NotNullSyncConfig.LocalRootPath} -disablerule:BackupRule", // The arguments to pass to the command (e.g., list directory contents) RedirectStandardOutput = true, // Redirect the standard output to a string UseShellExecute = false, // Do not use the shell to execute the command CreateNoWindow = true // Do not create a new window for the command }; using Process process = new() { StartInfo = startInfo }; // Start the process process.Start(); // Read the output from the process string output = process.StandardOutput.ReadToEnd(); // Wait for the process to exit process.WaitForExit(); if (process.ExitCode == 0) { Context.LocalPipe.SendMsg(CreateMsg("发布成功!")).Wait(); var h = new DiffFileAndPackHelper(Context); Context.StateHelper = h; h.DiffProcess(); } else { Context.LocalPipe.SendMsg(CreateErrMsg(output)).Wait(); throw new Exception("执行发布错误,错误信息参考上一条消息!"); } } else { throw new NotSupportedException("只支持windows!"); } } } protected override void HandleRemoteMsg(SyncMsg msg) { } protected override void HandleLocalMsg(SyncMsg msg) { } } public class DiffFileAndPackHelper(LocalSyncServer context) : StateHelpBase(context, SyncProcessStep.DiffFileAndPack) { public void DiffProcess() { //提取本地文件的信息 Context.NotNullSyncConfig.DirFileConfigs.ForEach(e => { e.LocalDirInfo = new Dir(Context.NotNullSyncConfig.LocalRootPath + e.DirPath); e.LocalDirInfo.ExtractInfo(e.CherryPicks, e.Excludes); }); //将配置信息发送到remoteServer Context .RemotePipe.SendMsg(CreateMsg(JsonSerializer.Serialize(Context.NotNullSyncConfig))) .Wait(); } protected override void HandleLocalMsg(SyncMsg msg) { } protected override void HandleRemoteMsg(SyncMsg msg) { } } // /// // /// 0. 发布源验证密码 // /// // /// // public class LocalAuthorityState(LocalSyncServer context) : StateHelpBase(context) // { // public override void HandleRemoteMsg(SyncMsg? msg) // { // throw new NotImplementedException("error usage!"); // } // public override void HandleLocalMsg(SyncMsg? msg) // { // if (msg == null) // { // return; // } // else // { // string Pwd = msg.Body; // if (Pwd == "Xfs1%$@_fdYU.>>") // { // Context.LocalSocketSendMsg(new SyncMsg(SyncMsgType.Success, "源服务密码校验成功!")); // Context.StateHelper = new WaitingConfigInfoState(Context); // } // else // { // throw new UnauthorizedAccessException("pwd error!"); // } // } // } // } // /// // /// 1. 获取配置信息,它包含目标的服务器的配置信息 // /// // /// // public class WaitingConfigInfoState(LocalSyncServer context) : StateHelpBase(context) // { // public override void HandleRemoteMsg(SyncMsg? msg) { } // public override void HandleLocalMsg(SyncMsg? msg) // { // if (msg == null) // { // return; // } // else // { // string ConfigInfo = msg.Body; // Context.SyncConfig = // JsonSerializer.Deserialize(ConfigInfo) // ?? throw new NullReferenceException("ConfigInfo is null"); // var task = Context.RemoteSocket.ConnectAsync( // new Uri(Context.SyncConfig.RemoteUrl), // CancellationToken.None // ); // if (task.Wait(10000)) // { // if (Context.RemoteSocket.State == WebSocketState.Open) // { // var state = new RemoteAuthorityState(Context); // state.SendPwdToRemoteServer(); // Context.StateHelper = state; // } // else // { // throw new Exception("connect remote server failed!"); // } // } // else // { // throw new TimeoutException("connect remote server timeout"); // } // } // } // } // /// // /// 2. 目标服务器权限校验 // /// // /// // public class RemoteAuthorityState(LocalSyncServer context) : StateHelpBase(context) // { // public override void HandleRemoteMsg(SyncMsg? msg) // { // if (msg == null) // { // return; // } // else // { // if (msg.Type == SyncMsgType.Success) // { // Context.LocalSocketSendMsg(new SyncMsg(SyncMsgType.Success, "远程服务器校验成功!")); // var diffState = new DirFilesDiffState(Context); // diffState.SendSyncConfigToRemote(); // Context.StateHelper = diffState; // } // else // { // throw new Exception("远程服务器权限校验失败,请检查Local Server 的Mac地址是否在 Remote Server 的允许列表内!"); // } // } // } // public override void HandleLocalMsg(SyncMsg? msg) { } // public void SendPwdToRemoteServer() // { // var authorityInfo = new // { // Pwd = "xfs@#123hd??1>>|12#4", // MacAdr = new LocalServer.Controllers.LocalServerController( // Context.Factory // ).GetMacAddress() // }; // Context.RemoteSocketSendMsg(authorityInfo); // } // } // /// // /// 3. 文件比较 // /// // /// // public class DirFilesDiffState(LocalSyncServer context) : StateHelpBase(context) // { // public override void HandleRemoteMsg(SyncMsg? msg) // { // if (msg == null) // { // return; // } // else // { // if (msg.IsSuccess) // { // var state = new LocalPackAndUploadState(Context); // state.PackDiffDir(msg); // Context.StateHelper = state; // } // else // { // throw new Exception(msg.Body); // } // } // } // public override void HandleLocalMsg(SyncMsg? msg) { } // public void SendSyncConfigToRemote() // { // Context.RemoteSocketSendMsg( // Context.SyncConfig // ?? throw new NullReferenceException("SyncConfig should't be null here!") // ); // } // } // /// // /// 4. 本地打包并上传 // /// // /// // public class LocalPackAndUploadState(LocalSyncServer context) : StateHelpBase(context) // { // public override void HandleRemoteMsg(SyncMsg? msg) // { // if (msg == null) // { // return; // } // else { } // } // public override void HandleLocalMsg(SyncMsg? msg) { } // /// // /// 打包文件 // /// // /// // /// // public void PackDiffDir(SyncMsg msg) // { // if (msg.IsSuccess) // { // var diff = JsonSerializer.Deserialize(msg.Body); // Context.LocalSocketSendMsg(new SyncMsg(SyncMsgType.Success, "文件打包完成!")); // Context.LocalSocketSendMsg(new SyncMsg(SyncMsgType.Success, "文件上传完成!")); // } // else // { // throw new Exception(msg.Body); // } // } // private void UploadPackedFiles(string absolutePath) // { // //TODO 传递上传进度到前端。 // } // } // /// // /// 5. 目标服务器解包并发布 // /// // /// // public class RemoteUnPackAndReleaseState(LocalSyncServer context) : StateHelpBase(context) // { // public override void HandleRemoteMsg(SyncMsg? msg) // { // if (msg == null) // { // return; // } // else { } // } // public override void HandleLocalMsg(SyncMsg? msg) { } // }