diff --git a/Service/Service.csproj b/Service/Service.csproj index 507bcab94..9b3c3d27a 100644 --- a/Service/Service.csproj +++ b/Service/Service.csproj @@ -482,6 +482,9 @@ + + + diff --git a/Service/ServiceImplementations/DownloadBeWoServiceImp.cs b/Service/ServiceImplementations/DownloadBeWoServiceImp.cs index e8b039003..61dcb7fc0 100644 --- a/Service/ServiceImplementations/DownloadBeWoServiceImp.cs +++ b/Service/ServiceImplementations/DownloadBeWoServiceImp.cs @@ -46,15 +46,17 @@ namespace BeWo.Service.ServiceImplementations var response = UpdatePlanResponseHelper.GetUpdatePlanResponse(request, Tenant); + UpdateServerSessionManager.CreateSession(response, Tenant); + return response; } catch (UpdateException update) { - throw WaitBeforeException(update); + throw WaitBeforeSend(update); } catch (Exception ex) { - throw WaitBeforeException(new UpdateException("Update - GetUpdatePlan - Exception", ex)); + throw WaitBeforeSend(new UpdateException("Update - GetUpdatePlan - Exception", ex)); } } @@ -62,25 +64,27 @@ namespace BeWo.Service.ServiceImplementations { try { - var exception = UpdateRequestValidator.IsUpdateFileRequestValid(request, Tenant); + var exception = UpdateRequestValidator.Validate(request, Tenant); if (exception is object) throw new InvalidUpdateFileRequestException(exception); - + + UpdateServerSessionManager.LoadAbsolutePath(request); + var response = UpdateFileResponseHelper.GetUpdateFileResponse(request, Tenant); return response; } catch (UpdateException update) { - throw WaitBeforeException(update); + throw WaitBeforeSend(update); } catch (Exception ex) { - throw WaitBeforeException(new UpdateException("Update - GetUpdateFile - Exception", ex)); + throw WaitBeforeSend(new UpdateException("Update - GetUpdateFile - Exception", ex)); } } - public Exception WaitBeforeException(Exception ex) + public Exception WaitBeforeSend(Exception ex) { Thread.Sleep(3000); diff --git a/Service/ServiceUtils/Update/UpdateFileLimiter.cs b/Service/ServiceUtils/Update/UpdateFileLimiter.cs new file mode 100644 index 000000000..bc30100e6 --- /dev/null +++ b/Service/ServiceUtils/Update/UpdateFileLimiter.cs @@ -0,0 +1,18 @@ +using BS.SharedLauncher.DataContract; + +namespace BeWo.Service.ServiceUtils.Update +{ + public class UpdateFileLimiter + { + public UpdateFileDC UpdateFile { get; set; } + public int RequestsLeft { get; set; } + + public bool CanRequestMore + { + get + { + return RequestsLeft > 0; + } + } + } +} diff --git a/Service/ServiceUtils/Update/UpdateFileResponseHelper.cs b/Service/ServiceUtils/Update/UpdateFileResponseHelper.cs index 20ecead91..4c6e6d843 100644 --- a/Service/ServiceUtils/Update/UpdateFileResponseHelper.cs +++ b/Service/ServiceUtils/Update/UpdateFileResponseHelper.cs @@ -18,59 +18,23 @@ namespace BeWo.Service.ServiceUtils.Update { private static string _Version; private static string _Tenant; - - private static UpdateFileRequest _Request; + private static UpdateFileResponse _Response; public static UpdateFileResponse GetUpdateFileResponse(UpdateFileRequest request, string tenant) { _Response = new UpdateFileResponse(); _Tenant = tenant; - _Request = request; _Version = request.Version; - calculate(); + calculate(request.UpdateFile.AbsolutePath); return _Response; } - private static void calculate() + private static void calculate(string path) { - _Response.FileData = File.ReadAllBytes(_Request.UpdateFile.AbsolutePath); + _Response.FileData = File.ReadAllBytes(path); } - - - - //public static UpdateResponse GetUpdatePlanResponse(UpdateRequest request, string tenant) - //{ - // var reader = new UpdateConfigReader(ServerFilePaths.GetVersionConfigFilePath(), tenant); - - // _Tenant = tenant; - // _Request = request; - // _Response = new UpdateResponse - // { - // CurrentPackage = new PlanerPackageInfoDC - // { - // DefaultVersion = reader.GetDefaultVersion(), - // TenantVersion = reader.GetSpecificVersion() - // } - // }; - - // _Version = _Response.CurrentPackage.Version; - - // // Lädt komplettes Paket ohne Hash - // CalcFullPackage(); - - // // Lade Hash Werte - // _Response.CurrentPackage.LoadHash(); - - // CalcFilesToRequest(); - - // CalcFilesToDeleteInApply(); - - // CalcFilesToIgnoreInDownload(); - - // return _Response; - //} } } diff --git a/Service/ServiceUtils/Update/UpdateRequestValidator.cs b/Service/ServiceUtils/Update/UpdateRequestValidator.cs index eff688197..a88bca9f2 100644 --- a/Service/ServiceUtils/Update/UpdateRequestValidator.cs +++ b/Service/ServiceUtils/Update/UpdateRequestValidator.cs @@ -24,19 +24,33 @@ namespace BeWo.Service.ServiceUtils.Update return null; } - public static string IsUpdateFileRequestValid(UpdateFileRequest request, string tenant) + /// + /// Validiert die Anfrage und lädt benötigte Parameter in die Anfrage (z.b. absoluten Path zum Laden der Datei) + /// + /// + /// + /// Exception string or null if successfull + public static string Validate(UpdateFileRequest request, string tenant) { - // Check for Login ? - // Check for File Permissions ? + if (!string.IsNullOrEmpty(request.UpdateFile.AbsolutePath) || + string.IsNullOrEmpty(request.UpdateSessionId) || + string.IsNullOrEmpty(request.UpdateFile.RelativePath)) + return "Fehlerhafte Anfrage"; - if (!VerifyVersion(request, tenant)) - return $"Version konnte nicht bestätigt werden. Angefragte Version:{request.Version}"; + var session = UpdateServerSessionManager.CurrentSession(request.UpdateSessionId); - if (!VerifySource(request)) - return $"Datei Herkunft konnte nicht bestätigt werden. File:{request.UpdateFile.RelativePath}, Source:{request.UpdateFile.Source}"; + if (session is null) + return $"Session \"{request.UpdateSessionId}\" nicht verfügbar"; - if (!LoadValidPath(request.UpdateFile, request.Version, tenant)) - return $"Datei Pfad konnte nicht bestätigt werden. Path:{request.UpdateFile.RelativePath}"; + if (session.Tenant != tenant) + return "Tenant konnte nicht bestätigt werden."; + + if (session.FileLimiterDict.ContainsKey( + request.UpdateFile.RelativePath)) + return $"Angefragte Datei nicht verfügbar. Anfrage an \"{request.UpdateFile.RelativePath}\""; + + if (session.IsTimeouted) + return "Timeout"; return null; } @@ -86,31 +100,5 @@ namespace BeWo.Service.ServiceUtils.Update return true; } - - public static bool LoadValidPath(UpdateFileDC fileDC, string version, string tenant) - { - var source_folder = ServerFilePaths.GetSourceFolderPath(fileDC.Source, version, tenant); - var requested_path = Path.Combine(source_folder, fileDC.RelativePath); - - Regex regex = new Regex(@"([a-zA-Z0-9\s_\\.\-:])+.(exe|dll|application|manifest|config)$"); - Match match = regex.Match(requested_path); - //throw new NotImplementedException(requested_path); - if (match.Success) - if (File.Exists(requested_path) && Path.GetFullPath(requested_path).StartsWith(source_folder, StringComparison.OrdinalIgnoreCase)) - { - fileDC.AbsolutePath = requested_path; - return true; - } - else - { - // "File not found"; - return false; - } - else - { - // "File name not valid" - return false; - } - } } } diff --git a/Service/ServiceUtils/Update/UpdateServerSession.cs b/Service/ServiceUtils/Update/UpdateServerSession.cs new file mode 100644 index 000000000..3c37a1363 --- /dev/null +++ b/Service/ServiceUtils/Update/UpdateServerSession.cs @@ -0,0 +1,20 @@ +using BS.SharedLauncher.DataContract; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BeWo.Service.ServiceUtils.Update +{ + public class UpdateServerSession + { + public string Id { get; set; } + public string Tenant { get; set; } + public DateTime Created { get; set; } + public DateTime Timeout { get; set; } + public Dictionary FileLimiterDict { get; set; } + + public bool IsTimeouted => Timeout < DateTime.Now; + } +} diff --git a/Service/ServiceUtils/Update/UpdateServerSessionManager.cs b/Service/ServiceUtils/Update/UpdateServerSessionManager.cs new file mode 100644 index 000000000..580e80991 --- /dev/null +++ b/Service/ServiceUtils/Update/UpdateServerSessionManager.cs @@ -0,0 +1,134 @@ +using BS.SharedLauncher.DataContract; +using BS.SharedLauncher.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.ServiceModel; +using System.Threading; + +namespace BeWo.Service.ServiceUtils.Update +{ + public static class UpdateServerSessionManager + { + private static string _Lock => string.Empty; + private static readonly Dictionary _UpdateServerSessions = new Dictionary(); + + public static UpdateServerSession CurrentSession(string session_id) + { + try + { + Monitor.Enter(_Lock); + + return _UpdateServerSessions.TryGetValue(session_id, out var session) ? session : null; + } + catch (Exception e) + { + throw new FaultException(e.StackTrace + e.InnerException != null ? e.InnerException.Message : string.Empty); + } + finally + { + Monitor.Exit(_Lock); + } + } + + public static string GenerateUniqueSessionId() + { + return Guid.NewGuid().ToString(); + } + + public static void CreateSession(UpdatePlanResponse res, string tenant) + { + try + { + Monitor.Enter(_Lock); + + var session_id = GenerateUniqueSessionId(); + + if (_UpdateServerSessions.ContainsKey(session_id)) + throw new UpdateException("session id generation error"); + + var session = new UpdateServerSession() + { + Id = session_id, + Tenant = tenant, + Created = DateTime.Now, + Timeout = DateTime.Now.AddMinutes(10), + FileLimiterDict = res.FilesToRequest.ToDictionary(file => file.RelativePath, file => new UpdateFileLimiter() + { + RequestsLeft = 5, + UpdateFile = file + }) + }; + + _UpdateServerSessions.Add(session_id, session); + } + finally + { + Monitor.Exit(_Lock); + } + } + + public static void CloseSession(string session_id) + { + try + { + Monitor.Enter(_Lock); + + _UpdateServerSessions.Remove(session_id); + + CheckForTimeoutSessions(); + } + finally + { + Monitor.Exit(_Lock); + } + } + + public static void CheckForTimeoutSessions() + { + try + { + Monitor.Enter(_Lock); + + foreach (var key_pair in _UpdateServerSessions) + { + var session_id = key_pair.Key; + var session = key_pair.Value; + + if (session.IsTimeouted) + _UpdateServerSessions.Remove(session_id); + } + } + finally + { + Monitor.Exit(_Lock); + } + } + + public static void LoadAbsolutePath(UpdateFileRequest request) + { + try + { + Monitor.Enter(_Lock); + + var session_id = request.UpdateSessionId; + var session = _UpdateServerSessions[session_id]; + var limiter = session.FileLimiterDict[request.UpdateFile.RelativePath]; + + request.UpdateFile.AbsolutePath = limiter.UpdateFile.AbsolutePath; + + limiter.RequestsLeft--; + + if (!limiter.CanRequestMore) + _UpdateServerSessions.Remove(session_id); + + if (!session.FileLimiterDict.Any()) + CloseSession(session_id); + } + finally + { + Monitor.Exit(_Lock); + } + } + } +} diff --git a/SharedLauncher/DataContract/UpdateFileRequest.cs b/SharedLauncher/DataContract/UpdateFileRequest.cs index de926eb3d..17c227512 100644 --- a/SharedLauncher/DataContract/UpdateFileRequest.cs +++ b/SharedLauncher/DataContract/UpdateFileRequest.cs @@ -26,6 +26,9 @@ namespace BS.SharedLauncher.DataContract [DataMember] public string Version { get; set; } + [DataMember] + public string UpdateSessionId { get; set; } + [DataMember] public UpdateFileDC UpdateFile { get; set; } } diff --git a/SharedLauncher/SharedLauncher.csproj b/SharedLauncher/SharedLauncher.csproj index 0f93921e5..0f5ed9eb6 100644 --- a/SharedLauncher/SharedLauncher.csproj +++ b/SharedLauncher/SharedLauncher.csproj @@ -59,6 +59,7 @@ +