aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Utilities/Tango.RemoteRunner.UI/MainWindowVM.cs
diff options
context:
space:
mode:
authorRoy Ben-Shabat <Roy@Twine-s.com>2018-06-03 18:01:27 +0300
committerRoy Ben-Shabat <Roy@Twine-s.com>2018-06-03 18:01:27 +0300
commit69343c64b63e2ae675332df10a8ad786cbda7094 (patch)
tree4d6510feaeeba2adad0e2257586ffe1582b2831d /Software/Visual_Studio/Utilities/Tango.RemoteRunner.UI/MainWindowVM.cs
parent34b3f33ec9ccb682c430b3c9e206507d0a396e1c (diff)
downloadTango-69343c64b63e2ae675332df10a8ad786cbda7094.tar.gz
Tango-69343c64b63e2ae675332df10a8ad786cbda7094.zip
Implemented RemoteRunner!
Diffstat (limited to 'Software/Visual_Studio/Utilities/Tango.RemoteRunner.UI/MainWindowVM.cs')
-rw-r--r--Software/Visual_Studio/Utilities/Tango.RemoteRunner.UI/MainWindowVM.cs251
1 files changed, 251 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Utilities/Tango.RemoteRunner.UI/MainWindowVM.cs b/Software/Visual_Studio/Utilities/Tango.RemoteRunner.UI/MainWindowVM.cs
new file mode 100644
index 000000000..d0108a499
--- /dev/null
+++ b/Software/Visual_Studio/Utilities/Tango.RemoteRunner.UI/MainWindowVM.cs
@@ -0,0 +1,251 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Tango.Logging;
+using Tango.PMR;
+using Tango.PMR.Common;
+using Tango.PMR.IO;
+using Tango.SharedUI;
+using Tango.Transport;
+using Tango.Transport.Adapters;
+using Tango.Transport.Servers;
+using Tango.Transport.Transporters;
+
+namespace Tango.RemoteRunner.UI
+{
+ public class MainWindowVM : ViewModel
+ {
+ private TcpServer _server;
+ private ITransporter _transporter;
+ private const int PORT = 9595;
+ private List<FileUpload> _uploads;
+ private const long MAX_CHUNK_LENGTH = 1024;
+
+ private Action<String> _notificationAction;
+ private ObservableCollection<RunningProcess> _runningProcesses;
+ public ObservableCollection<RunningProcess> RunningProcesses
+ {
+ get { return _runningProcesses; }
+ set { _runningProcesses = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _log;
+ public String Log
+ {
+ get { return _log; }
+ set { _log = value; RaisePropertyChangedAuto(); }
+ }
+
+ public MainWindowVM()
+ {
+ RunningProcesses = new ObservableCollection<RunningProcess>();
+ _uploads = new List<FileUpload>();
+
+ var logger = new SimpleStringLogger() { Enabled = true };
+ logger.LogReceived += (_, log) =>
+ {
+ Log += String.Format("{0}: {1}", log.TimeStamp.ToShortTimeString(), log.Message) + Environment.NewLine;
+ };
+ LogManager.RegisterLogger(logger);
+ }
+
+ public void ViewLoaded()
+ {
+ LogManager.Log("Application Started!");
+ LogManager.Log("Initializing TCP listener on port " + PORT + "...");
+ _server = new TcpServer(PORT);
+ _server.ClientConnected += _server_ClientConnected;
+ _server.Start();
+
+ LogManager.Log("Initializing basic transporter...");
+ _transporter = new BasicTransporter();
+ _transporter.FailsWithAdapter = false;
+ _transporter.RequestReceived += _transporter_RequestReceived;
+ }
+
+ private void _transporter_RequestReceived(object sender, MessageContainer container)
+ {
+ try
+ {
+ switch (container.Type)
+ {
+ case MessageType.FileUploadRequest:
+ HandleFileUploadRequest(MessageFactory.ParseTangoMessageFromContainer<FileUploadRequest>(container));
+ break;
+ case MessageType.FileChunkUploadRequest:
+ HandleFileChunkUploadRequest(MessageFactory.ParseTangoMessageFromContainer<FileChunkUploadRequest>(container));
+ break;
+ case MessageType.ExecuteProcessRequest:
+ HandleExecuteProcessRequest(MessageFactory.ParseTangoMessageFromContainer<ExecuteProcessRequest>(container));
+ break;
+ case MessageType.KillProcessRequest:
+ HandleKillProcessRequest(MessageFactory.ParseTangoMessageFromContainer<KillProcessRequest>(container));
+ break;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex);
+ _transporter.SendErrorResponse(ex, container.Token);
+ }
+ }
+
+ #region Request Handlers
+
+ private void HandleFileUploadRequest(TangoMessage<FileUploadRequest> request)
+ {
+ LogManager.Log("File upload request received " + request.Message.FileName);
+
+ Notify("Upload request " + request.Message.FileName);
+
+ var tempFolder = TemporaryManager.CreateFolder();
+ LogManager.Log("Created temporary upload folder " + tempFolder.Path);
+
+ String uploadID = Guid.NewGuid().ToString();
+
+ _uploads.Add(new FileUpload()
+ {
+ Folder = tempFolder,
+ UploadID = uploadID,
+ FileName = request.Message.FileName,
+ Length = request.Message.Length,
+ });
+
+ _transporter.SendResponse<FileUploadResponse>(new FileUploadResponse()
+ {
+ UploadID = uploadID,
+ MaxChunkLength = MAX_CHUNK_LENGTH,
+ }, request.Container.Token);
+ }
+
+ private void HandleFileChunkUploadRequest(TangoMessage<FileChunkUploadRequest> request)
+ {
+ FileUpload upload = _uploads.SingleOrDefault(x => x.UploadID == request.Message.UploadID);
+ if (upload == null)
+ {
+ _transporter.SendResponse<FileChunkUploadResponse>(new FileChunkUploadResponse() { IsCanceled = true }, request.Container.Token, true, ErrorCode.InvalidUploadId);
+ return;
+ }
+
+ if (upload.CurrentLength + request.Message.Buffer.Length > upload.Length)
+ {
+ _transporter.SendResponse<FileChunkUploadResponse>(new FileChunkUploadResponse() { IsCanceled = true }, request.Container.Token, true, ErrorCode.FileLengthOutOfRange);
+ return;
+ }
+
+ using (FileStream fs = new FileStream(upload.FullPath, FileMode.Append))
+ {
+ byte[] buffer = request.Message.Buffer.ToByteArray();
+ fs.Write(buffer, 0, buffer.Length);
+ upload.CurrentLength = fs.Length;
+
+ if (fs.Length == upload.Length)
+ {
+ upload.Completed = true;
+ LogManager.Log("File upload completed " + upload.FileName);
+ }
+ }
+
+ _transporter.SendResponse<FileChunkUploadResponse>(new FileChunkUploadResponse(), request.Container.Token);
+ }
+
+ private void HandleExecuteProcessRequest(TangoMessage<ExecuteProcessRequest> request)
+ {
+ LogManager.Log("Execute process request received " + request.Message.FileName);
+
+ Notify("Execute request " + request.Message.FileName);
+
+ FileUpload upload = _uploads.SingleOrDefault(x => x.UploadID == request.Message.UploadID);
+ if (upload == null || !upload.Completed)
+ {
+ _transporter.SendResponse<ExecuteProcessResponse>(new ExecuteProcessResponse(), request.Container.Token, true, ErrorCode.InvalidUploadId);
+ return;
+ }
+
+ if (Path.GetExtension(upload.FileName).ToLower() == ".zip" && !upload.Expanded)
+ {
+ LogManager.Log("Extracting zip file to " + upload.Folder.Path);
+ ZipFile.ExtractToDirectory(upload.FullPath, upload.Folder.Path);
+ }
+
+ upload.Expanded = true;
+
+ RunningProcess process = new RunningProcess();
+ process.Process = Process.Start(Path.Combine(upload.Folder.Path, Path.GetFileName(request.Message.FileName)));
+
+ LogManager.Log("Process started " + process.ProcessName + ", " + process.ProcessID);
+
+ InvokeUINow(() =>
+ {
+ RunningProcesses.Add(process);
+ });
+
+ _transporter.SendResponse<ExecuteProcessResponse>(new ExecuteProcessResponse() { ProcessID = process.ProcessID }, request.Container.Token);
+ }
+
+ private void HandleKillProcessRequest(TangoMessage<KillProcessRequest> request)
+ {
+ LogManager.Log("Kill process request received " + request.Message.ProcessID);
+ Notify("Kill request " + request.Message.ProcessID);
+
+ var process = RunningProcesses.SingleOrDefault(x => x.ProcessID == request.Message.ProcessID);
+
+ if (process == null)
+ {
+ _transporter.SendResponse<KillProcessResponse>(new KillProcessResponse(), request.Container.Token, true, ErrorCode.InvalidProcessId);
+ return;
+ }
+
+ process.Process.Kill();
+ LogManager.Log("Process killed " + process.ProcessName + ", " + process.ProcessID);
+ _transporter.SendResponse<KillProcessResponse>(new KillProcessResponse(), request.Container.Token);
+ }
+
+ #endregion
+
+ private void _server_ClientConnected(object sender, ClientConnectedEventArgs e)
+ {
+ Task.Factory.StartNew(async () =>
+ {
+ try
+ {
+ Stopwatch watch = new Stopwatch();
+ watch.Start();
+
+ LogManager.Log("Remote client connection from " + e.Socket.GetIPAddress());
+ LogManager.Log("Initializing transporter with a new TCP adapter...");
+
+ Notify("Client connected from " + e.Socket.GetIPAddress());
+
+ await _transporter.Disconnect();
+ TcpTransportAdapter adapter = new TcpTransportAdapter(e.Socket);
+ _transporter.Adapter = adapter;
+ await _transporter.Connect();
+
+ LogManager.Log(watch.Elapsed.Milliseconds + " milliseconds");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex);
+ }
+ });
+ }
+
+ public void SetNotificationAction(Action<String> notificationAction)
+ {
+ _notificationAction = notificationAction;
+ }
+
+ private void Notify(String text)
+ {
+ _notificationAction?.Invoke(text);
+ }
+ }
+}