From d33c19b3ac6803de4b5c8d475832efef131c1a45 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 30 Dec 2020 15:11:34 +0000 Subject: Revert "Hope it is fine" --- .../FileSystem/DefaultFileSystemService.cs | 433 +++++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs (limited to 'Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs') diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs new file mode 100644 index 000000000..8272ea34d --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs @@ -0,0 +1,433 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Core.DI; +using Tango.Core.IO; +using Tango.FileSystem; +using Tango.FileSystem.Network; +using Tango.Integration.ExternalBridge; +using Tango.Integration.Operation; +using Tango.Logging; +using Tango.PPC.Common.ExternalBridge; +using Tango.PPC.Shared.Logs; +using Tango.Settings; +using Tango.Transport; +using Tango.Transport.Transporters; +using Tango.WebRTC; + +namespace Tango.PPC.Common.FileSystem +{ + /// + /// Represents the default implementation. + /// + /// + /// + /// + [TangoCreateWhenRegistered] + public class DefaultFileSystemService : ExtendedObject, IFileSystemService, IExternalBridgeRequestHandler + { + private FileSystemManager _manager; + private Dictionary _operations; + private Dictionary _webRtcClients; + private PPCSettings _settings; + + public bool Enabled { get; set; } = true; + public bool EnableWebRTC { get; set; } = true; + + public DefaultFileSystemService(IPPCExternalBridgeService externalBridge) + { + _webRtcClients = new Dictionary(); + _manager = new FileSystemManager(); + _operations = new Dictionary(); + externalBridge.RegisterRequestHandler(this); + _settings = SettingsManager.Default.GetOrCreate(); + } + + [ExternalBridgeRequestHandlerMethod(typeof(InitWebRtcRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnInitWebRtcRequest(InitWebRtcRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + try + { + if (!EnableWebRTC) + { + await receiver.SendErrorResponse(new InvalidOperationException("The file system service WebRTC channel is disabled on this machine."), token); + return; + } + + LogManager.Log("Initializing WebRTC channel for file system service."); + + if (_webRtcClients.ContainsKey(receiver)) + { + _webRtcClients[receiver].Dispose(); + } + + LogManager.Log("Initializing WebRTC transport adapter on 'Passive' mode."); + var webRtcAdapter = new WebRtcTransportAdapter(receiver, WebRtcTransportAdapterMode.Passive, request.DataChannelName) + { + EnableCompression = receiver.Adapter.EnableCompression + }; + webRtcAdapter.Ready += (x, e) => + { + LogManager.Log("The file system service WebRTC channel is ready."); + }; + + BasicTransporter webRtcTransporter = new BasicTransporter(webRtcAdapter); + webRtcTransporter.GenericProtocol = receiver.GenericProtocol; + webRtcTransporter.ComponentName = "File System Passive WebRTC Transporter"; + webRtcTransporter.UseKeepAlive = false; + webRtcTransporter.RegisterRequestHandler(WebRtcChunkDownloadRequestReceived); + webRtcTransporter.RegisterRequestHandler(WebRtcChunkUploadRequestReceived); + await webRtcTransporter.Connect(); + + LogManager.Log("Sending WebRTC initialization response..."); + + await receiver.SendGenericResponse(new InitWebRtcResponse(), token); + _webRtcClients[receiver] = webRtcTransporter; + } + catch (Exception ex) + { + LogManager.Log(ex, "Error initializing WebRTC channel for file system service."); + await receiver.SendErrorResponse(ex, token); + } + } + + private async void WebRtcChunkDownloadRequestReceived(ITransporter transporter, ChunkDownloadRequest request, string token) + { + await OnChunkDownloadRequest(request, token, transporter); + } + + private async void WebRtcChunkUploadRequestReceived(ITransporter transporter, ChunkUploadRequest request, string token) + { + await OnChunkUploadRequest(request, token, transporter); + } + + [ExternalBridgeRequestHandlerMethod(typeof(GetFileSystemItemRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnGetFileSystemItemRequest(GetFileSystemItemRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + FileSystemItemDTO dto = _manager.GetFolder(request); + await receiver.SendGenericResponse(new GetFileSystemItemResponse() { FileSystemItem = dto }, token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(FileUploadRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnFileUploadRequest(FileUploadRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + var tempFile = TemporaryManager.CreateFile(); + using (var stream = new FileStream(tempFile, FileMode.Create)) { } + + FileSystemOperation operation = new FileSystemOperation(FileSystemOperationMode.Upload, tempFile) { UploadPostPath = request.Path }; + _operations.Add(operation.Id, operation); + + await receiver.SendGenericResponse(new FileUploadResponse() { OperationId = operation.Id }, token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(FolderUploadRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnFolderUploadRequest(FolderUploadRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + var tempFile = TemporaryManager.CreateFile(); + using (var stream = new FileStream(tempFile, FileMode.Create)) { } + + FileSystemOperation operation = new FileSystemOperation(FileSystemOperationMode.Upload, tempFile) { UploadPostPath = request.Path, IsPathTempZip = true }; + _operations.Add(operation.Id, operation); + + await receiver.SendGenericResponse(new FolderUploadResponse() { OperationId = operation.Id }, token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(FileDownloadRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnFileDownloadRequest(FileDownloadRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + if (!File.Exists(request.Path)) + { + throw new FileNotFoundException("Could not find the specified file."); + } + + FileSystemOperation operation = new FileSystemOperation(FileSystemOperationMode.Download, request.Path); + + _operations.Add(operation.Id, operation); + + await receiver.SendGenericResponse(new FileDownloadResponse() + { + OperationId = operation.Id, + Length = new FileInfo(request.Path).Length + }, token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(FolderDownloadRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnFolderDownloadRequest(FolderDownloadRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + if (!Directory.Exists(request.Path)) + { + throw new FileNotFoundException("Could not find the specified directory."); + } + + var tempFile = TemporaryManager.CreateImaginaryFile(); + + ZipFile.CreateFromDirectory(request.Path, tempFile); + + FileSystemOperation operation = new FileSystemOperation(FileSystemOperationMode.Download, tempFile); + operation.IsPathTempZip = true; + + _operations.Add(operation.Id, operation); + + await receiver.SendGenericResponse(new FolderDownloadResponse() + { + OperationId = operation.Id, + Length = new FileInfo(tempFile).Length + }, token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(ChunkUploadRequest))] + public async Task OnChunkUploadRequest(ChunkUploadRequest request, String token, ITransporter receiver) + { + this.ThrowIfDisabled(); + + FileSystemOperation operation; + _operations.TryGetValue(request.OperationId, out operation); + + if (operation == null) + { + throw new ArgumentException("Invalid operation id."); + } + + using (var stream = new FileStream(operation.Path, FileMode.Append)) + { + stream.Write(request.Data, 0, request.Data.Length); + } + + if (request.IsCompleted) + { + if (!operation.IsPathTempZip) + { + File.Copy(operation.Path, operation.UploadPostPath, true); + try + { + File.Delete(operation.Path); + } + catch { } + } + else + { + using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(operation.Path)) + { + zip.ExtractAll(operation.UploadPostPath, Ionic.Zip.ExtractExistingFileAction.OverwriteSilently); + } + + try + { + File.Delete(operation.Path); + } + catch { } + } + } + + await receiver.SendGenericResponse(new ChunkUploadResponse(), token, new TransportResponseConfig() { Priority = QueuePriority.Low }); + } + + [ExternalBridgeRequestHandlerMethod(typeof(ChunkDownloadRequest))] + public async Task OnChunkDownloadRequest(ChunkDownloadRequest request, String token, ITransporter receiver) + { + this.ThrowIfDisabled(); + + FileSystemOperation operation; + _operations.TryGetValue(request.OperationId, out operation); + + if (operation == null) + { + throw new ArgumentException("Invalid operation id."); + } + + FileStream stream = null; + bool removeTempZipFile = false; + + try + { + stream = new FileStream(operation.Path, FileMode.Open); + stream.Position = request.Position; + byte[] data = new byte[Math.Min(request.MaxChunkSize, stream.Length - stream.Position)]; + + if (stream.Position + data.Length == stream.Length) + { + removeTempZipFile = true; + } + + await stream.ReadAsync(data, 0, data.Length); + stream.Dispose(); + stream = null; + await receiver.SendGenericResponse(new ChunkDownloadResponse() + { + Data = data + }, token, new TransportResponseConfig() { Priority = QueuePriority.Low }); + } + catch (Exception ex) + { + stream?.Dispose(); + throw ex; + } + finally + { + if (operation.IsPathTempZip && removeTempZipFile) + { + try + { + if (File.Exists(operation.Path)) + { + File.Delete(operation.Path); + } + } + catch { } + } + } + } + + [ExternalBridgeRequestHandlerMethod(typeof(AbortOperationRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnAbortOperationRequest(AbortOperationRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + FileSystemOperation operation; + _operations.TryGetValue(request.OperationId, out operation); + + if (operation == null) + { + throw new ArgumentException("Invalid operation id."); + } + + if (operation.Mode == FileSystemOperationMode.Upload) + { + if (File.Exists(operation.Path)) + { + File.Delete(operation.Path); + } + } + else if (operation.IsPathTempZip) + { + if (File.Exists(operation.Path)) + { + File.Delete(operation.Path); + } + } + + await receiver.SendGenericResponse(new AbortOperationResponse(), token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(MoveRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnMoveRequest(MoveRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + _manager.Move(request); + await receiver.SendGenericResponse(new MoveResponse(), token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(CopyRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnCopyRequest(CopyRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + _manager.Copy(request); + await receiver.SendGenericResponse(new CopyResponse(), token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(DeleteRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnDeleteRequest(DeleteRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + _manager.Delete(request.Path); + await receiver.SendGenericResponse(new DeleteResponse(), token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(CreateFolderRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnCreateFolderRequest(CreateFolderRequest request, String token, ExternalBridgeReceiver receiver) + { + this.ThrowIfDisabled(); + + var dto = _manager.CreateFolder(request.Path, request.FolderName); + await receiver.SendGenericResponse(new CreateFolderResponse() { FolderItem = dto }, token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(PerformDiskSpaceOptimizationRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnPerformDiskSpaceOptimizationRequest(PerformDiskSpaceOptimizationRequest request, String token, ExternalBridgeReceiver receiver) + { + var deletedBytes = _manager.PerformDiskSpaceOptimization(); + await receiver.SendGenericResponse(new PerformDiskSpaceOptimizationResponse() { DeletedBytes = deletedBytes }, token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(GetLogFilesRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] + public async Task OnGetLogFilesRequest(GetLogFilesRequest request, String token, ExternalBridgeReceiver receiver) + { + FolderItem folder = null; + + if (request.LogFileType == RemoteLogFileType.Application) + { + var fileLogger = LogManager.RegisteredLoggers.SingleOrDefault(x => x.GetType() == typeof(FileLogger)) as FileLogger; + + if (fileLogger == null) + { + throw new InvalidOperationException("Could not locate the application file logger."); + } + + folder = await _manager.GetFolder(fileLogger.Folder, false, "*.log") as FolderItem; + } + else + { + if (MachineOperator.EmbeddedLogsFolder == null) + { + throw new InvalidOperationException("The firmware file logger folder could not be read."); + } + + folder = await _manager.GetFolder(MachineOperator.EmbeddedLogsFolder, false, "*.log") as FolderItem; + } + + GetLogFilesResponse response = new GetLogFilesResponse(); + + foreach (var file in folder.Items.OfType().OrderByDescending(x => x.DateCreated).DistinctBy(x => x.Name)) + { + response.LogFiles.Add(new RemoteLogFile() + { + DateModified = file.DateModified, + DateCreated = file.DateCreated, + Name = file.Name, + Path = file.Path, + Length = new FileInfo(file.Path).Length + }); + } + + await receiver.SendGenericResponse(response, token); + } + + public void OnReceiverDisconnected(ExternalBridgeReceiver receiver) + { + if (_webRtcClients.ContainsKey(receiver)) + { + try + { + LogManager.Log("External bridge receiver disconnected. Disposing file system service WebRTC channel..."); + var webRtcTransporter = _webRtcClients[receiver]; + _webRtcClients.Remove(receiver); + webRtcTransporter.Dispose(); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error disposing the WebRTC channel."); + } + } + } + } +} -- cgit v1.3.1