using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; using Vinno.IUS.Common.Log; using Vinno.IUS.Common.Utilities; using Vinno.vCloud.Common.FIS.Remedicals; namespace Vinno.vCloud.Common.FIS.vStation { internal class Security { public static string Salt(string input) { return $"V1NN0{input}vStation"; } public static string Hash(string input) { return HashEngine.GetHashString(input, Encoding.Unicode).ToLower(); } } public class vStation : IvStation { private readonly ConcurrentDictionary _uploadingvStationVidDatas = new ConcurrentDictionary(); private HttpClient _httpClient; private string _token; private bool _disposed; private CancellationTokenSource _cancellationTokenSource; private string _ipAddress; private string _port; /// ///senconds /// private int _timeOut; internal static string FolderPath; public string IpAddress { get => _ipAddress; set { if (_ipAddress != value) { _ipAddress = value; } } } public string Port { get => _port; set { if (_port != value) { _port = value; } } } public int TimeOut { get => _timeOut; set { if (_timeOut != value) { _timeOut = value; } } } /// /// Raised when a vStation Vid Data changed. /// public event EventHandler vStationVidDataChanged; public vStation(string ipAddress, string port, int timeout, string folderPath = null) { _ipAddress = ipAddress; _port = port; _timeOut = timeout; if (string.IsNullOrEmpty(folderPath)) { FolderPath = AppDomain.CurrentDomain.BaseDirectory; } else { FolderPath = folderPath; } _cancellationTokenSource = new CancellationTokenSource(); } /// /// /// Gets all vStation Vid datas. /// /// The uploading and failed scan datas. public IEnumerable GetvStationVidDatas() { return _uploadingvStationVidDatas.Values; } public vStationVidData CreatevStationVidData(string filePath, UploadStatus status) { var id = Guid.NewGuid().ToString("N").ToUpper(); var vStationVidData = new vStationVidData(id, filePath, status); return vStationVidData; } public void LoadvStationVidData() { var vStationFolder = Path.Combine(FolderPath, "vStation"); if (Directory.Exists(vStationFolder)) { foreach (var storeFolder in Directory.GetDirectories(vStationFolder)) { var storeFiles = Directory.GetFiles(storeFolder, "*.vd"); foreach (var storeFile in storeFiles) { if (string.IsNullOrEmpty(Path.GetFileNameWithoutExtension(storeFile))) { continue; } var vidData = vStationVidDataSerializer.Deserialize(storeFile); if (vidData != null) { _uploadingvStationVidDatas.AddOrUpdate(vidData.Id, a => { OnvStationVidDataChanged(new vStationVidDataChangedEventArgs(vidData, ScanDataChangeType.Added)); return vidData; } , (s, exist) => { exist.StatusChanged -= OnvStationVidDataStatusChanged; exist.Dispose(); OnvStationVidDataChanged(new vStationVidDataChangedEventArgs(vidData, ScanDataChangeType.Update)); return vidData; }); vidData.StatusChanged += OnvStationVidDataStatusChanged; } } } } } private void OnvStationVidDataChanged(vStationVidDataChangedEventArgs e) { vStationVidDataChanged?.Invoke(this, e); } private void OnvStationVidDataStatusChanged(object sender, EventArgs e) { var vidData = (vStationVidData)sender; OnvStationVidDataChanged(new vStationVidDataChangedEventArgs(vidData, ScanDataChangeType.Update)); if (vidData.Status == UploadStatus.Uploaded) { if (_uploadingvStationVidDatas.TryRemove(vidData.Id, out var removedData)) { removedData.StatusChanged -= OnvStationVidDataStatusChanged; OnvStationVidDataChanged(new vStationVidDataChangedEventArgs(removedData, ScanDataChangeType.Removed)); removedData.Dispose(); } } if (vidData.Status == UploadStatus.Deleted) { if (_uploadingvStationVidDatas.TryRemove(vidData.Id, out var removedData)) { removedData.StatusChanged -= OnvStationVidDataStatusChanged; } } } private bool Connect() { try { if (_httpClient != null) { _httpClient.Dispose(); _httpClient = null; } var validateString = $"Connect{DateTime.Now.ToString("yyyyMMdd")}"; _httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(_timeOut) }; var content = new StringContent(Security.Hash(Security.Salt(validateString))); content.Headers.Add("Action", "Connect"); var response = Task.Run(() => _httpClient.PostAsync(new Uri($"http://{_ipAddress}:{_port}/"), content, _cancellationTokenSource.Token).GetAwaiter().GetResult()).GetAwaiter().GetResult(); if (response.StatusCode == HttpStatusCode.OK) { var data = Task.Run(() => response.Content.ReadAsStringAsync().GetAwaiter().GetResult()).GetAwaiter().GetResult(); var spliters = data.Split(';'); if (spliters.Count() == 2 && spliters[0] == "ConnectSuccess") { _token = spliters[1]; return true; } } } catch (Exception ex) { _httpClient?.Dispose(); _httpClient = null; Logger.WriteLineError($"Connect to vStation server error: {ex}"); } return false; } private bool Disconnect() { try { _httpClient?.Dispose(); _httpClient = null; return true; } catch (Exception ex) { Logger.WriteLineError($"DisConnect to vStation server error: {ex}"); } return false; } /// /// Test whether the network is ok or not. /// /// public bool TestConnection() { try { var validateString = $"TestConnection{DateTime.Now.ToString("yyyyMMdd")}"; if (_httpClient == null) { _httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(_timeOut) }; } var content = new StringContent(Security.Hash(Security.Salt(validateString))); content.Headers.Add("Action", "TestConnection"); var response = Task.Run(() => _httpClient.PostAsync(new Uri($"http://{_ipAddress}:{_port}/"), content, _cancellationTokenSource.Token).GetAwaiter().GetResult()).GetAwaiter().GetResult(); if (response.StatusCode == HttpStatusCode.OK) { var data = Task.Run(() => response.Content.ReadAsStringAsync().GetAwaiter().GetResult()).GetAwaiter().GetResult(); if (!string.IsNullOrEmpty(data) && data == Security.Hash(Security.Salt("TestConnectionSuccess"))) { return true; } } } catch (Exception ex) { _httpClient?.Dispose(); _httpClient = null; Logger.WriteLineError($"Connect to vStation error: {ex}"); } return false; } public void UploadFiles(IEnumerable vidDatas) { try { foreach (var vidData in vidDatas) { _uploadingvStationVidDatas.AddOrUpdate(vidData.Id, a => vidData, (s, exist) => { exist.StatusChanged -= OnvStationVidDataStatusChanged; exist.Dispose(); return vidData; }); vidData.StatusChanged += OnvStationVidDataStatusChanged; OnvStationVidDataChanged(new vStationVidDataChangedEventArgs(vidData, ScanDataChangeType.Added)); } if (!Connect()) { foreach (var vidData in vidDatas) { vidData.Status = UploadStatus.Fail; try { vidData.Update(); } catch (Exception e) { Logger.WriteLineError($"update vStationVidData error, Id:{vidData.Id}, {e}"); } } return; } foreach (var vidData in vidDatas) { UploadFile(vidData); } } catch (Exception ex) { Logger.WriteLineError($"upload vStationVidDatas error,{ex}"); } finally { Disconnect(); } } private bool UploadFile(vStationVidData vidData) { try { if (_httpClient == null) { Logger.WriteLineWarn("Upload file to vStation error: the httpclient not started."); return false; } vidData.Status = UploadStatus.Waiting; var content = new ByteArrayContent(File.ReadAllBytes(vidData.VidFilePath)); content.Headers.Add("Token", _token); content.Headers.Add("Action", "UploadFile"); vidData.Status = UploadStatus.Uploading; var response = Task.Run(() => _httpClient.PostAsync(new Uri($"http://{_ipAddress}:{_port}/"), content, _cancellationTokenSource.Token).GetAwaiter().GetResult()).GetAwaiter().GetResult(); var result = CheckResult(response); if (!result) { vidData.Status = UploadStatus.Fail; try { vidData.Update(); } catch (Exception e) { Logger.WriteLineError($"update vStationVidData error, Id:{vidData.Id}, {e}"); } } else { vidData.Status = UploadStatus.Uploaded; } return result; } catch (Exception ex) { vidData.Status = UploadStatus.Fail; try { vidData.Update(); } catch (Exception e) { Logger.WriteLineError($"update vStationVidData error, Id:{vidData.Id}, {e}"); } Logger.WriteLineError($"Upload file to vStation error: {ex}"); } return false; } private bool CheckResult(HttpResponseMessage response) { if (response.StatusCode == HttpStatusCode.OK) { var data = Task.Run(() => response.Content.ReadAsStringAsync().GetAwaiter().GetResult()).GetAwaiter().GetResult(); if (data == Security.Hash(Security.Salt("200 - OK."))) { return true; } } return false; } private void DoDispose() { if (!_disposed) { _cancellationTokenSource?.Cancel(); foreach (var vidData in _uploadingvStationVidDatas.Values.ToArray()) { vidData.StatusChanged -= OnvStationVidDataStatusChanged; vidData.Dispose(); if (_uploadingvStationVidDatas.TryRemove(vidData.Id, out var removedData)) { OnvStationVidDataChanged(new vStationVidDataChangedEventArgs(removedData, ScanDataChangeType.Removed)); } } _disposed = true; } } public void Dispose() { DoDispose(); GC.SuppressFinalize(this); } } }