diff --git a/DataCenter_Windows/WindowsDataCenter/CardReaderService/CardReaderService.cs b/DataCenter_Windows/WindowsDataCenter/CardReaderService/CardReaderService.cs index 6f6d5d8..e5bf9ab 100644 --- a/DataCenter_Windows/WindowsDataCenter/CardReaderService/CardReaderService.cs +++ b/DataCenter_Windows/WindowsDataCenter/CardReaderService/CardReaderService.cs @@ -18,6 +18,9 @@ namespace CardReaderService private string _readerName = ""; private SCardMonitor _cardMonitor; + private bool _initialised = false; + private AutoResetEvent _mainWorkerTerminationSignal; + private ILogger _logger; public CardReaderService() @@ -32,43 +35,9 @@ namespace CardReaderService protected override void OnStart(string[] args) { - var configPath = string.Concat(System.Reflection.Assembly.GetEntryAssembly().Location, ".config"); - _logger = NinjectHelper.GetInstance().Get(); - _logger.Trace("Starting Service.. Getting available readers"); - var ctxFactory = ContextFactory.Instance; - using(var context = ctxFactory.Establish(SCardScope.System)) - { - var readerNames = context.GetReaders(); - if (NoReaderAvailable(readerNames)) - { - _logger.Trace("No Card Reader is available, Exiting.."); - throw new ApplicationException("A card reader must be provided in order to operate."); - } - foreach (var reader in readerNames) - { - _logger.Trace("Found reader: {0}", reader); - } - - var readerNameConfig = ConfigurationHandler.ConfigurationHandler.GetConfiguration("ReaderName"); - if (string.IsNullOrEmpty(readerNameConfig) || (!readerNames.Contains(readerNameConfig))) - { - _logger.Warn("No reader found with the name: {0}, defaulting to first available reader {1}", - readerNameConfig, readerNames.First()); - - readerNameConfig = readerNames.First(); - - } - _logger.Trace("Choosing reader: {0}", readerNameConfig); - _readerName = readerNameConfig; - - _cardMonitor = new SCardMonitor(ctxFactory, SCardScope.System); - _cardMonitor.CardInserted += _cardMonitor_CardInserted; - _cardMonitor.Start(_readerName); - - StartWorkerThread(); - } + StartWorkerThread(); } public void StopService() @@ -79,6 +48,7 @@ namespace CardReaderService protected override void OnStop() { _stopMainWorkerThread = true; + _mainWorkerTerminationSignal.Set(); if (_mainWorkThread!= null && _mainWorkThread.IsAlive) { _mainWorkThread.Join(3000); @@ -102,6 +72,7 @@ namespace CardReaderService Name = "CardServiceMainThread", IsBackground = false }; + _mainWorkerTerminationSignal = new AutoResetEvent(false); _mainWorkThread.Start(); } @@ -135,7 +106,7 @@ namespace CardReaderService _logger.Trace("Card Inserted, ATR: " + atrString + ", and UID is: " + uid); var postObj = new CardDataPost {CardUId = uid}; - DataCenterHelper.PostAsync(postObj, "/api/swipedata"); + DataCenterHelper.PostAsync(_logger, postObj, "/api/swipedata"); _logger.Trace("Posted to Server"); } else @@ -151,7 +122,51 @@ namespace CardReaderService while (!_stopMainWorkerThread) { //dont actually need to do anything.. but cannot exit right away? - Thread.Sleep(3000); + if (!WeHaveValidCardReader()) + { + if (_initialised) + { + //card reader no longer available, tidy up. + _cardMonitor.Cancel(); + _cardMonitor.CardInserted -= _cardMonitor_CardInserted; + _cardMonitor.Dispose(); + _cardMonitor = null; + _initialised = false; + } + var ctxFactory = ContextFactory.Instance; + using (var context = ctxFactory.Establish(SCardScope.System)) + { + var readerNames = context.GetReaders(); + if (NoReaderAvailable(readerNames)) + { + _logger.Trace("No Card Reader is available.."); + } + else + { + foreach (var reader in readerNames) + { + _logger.Trace("Found reader: {0}", reader); + } + + var readerNameConfig = ConfigurationHandler.ConfigurationHandler.GetConfiguration("ReaderName"); + if (string.IsNullOrEmpty(readerNameConfig) || (!readerNames.Contains(readerNameConfig))) + { + _logger.Warn("No reader found with the name: {0}, defaulting to first available reader {1}", + readerNameConfig, readerNames.First()); + + readerNameConfig = readerNames.First(); + } + _logger.Trace("Choosing reader: {0}", readerNameConfig); + _readerName = readerNameConfig; + + _cardMonitor = new SCardMonitor(ctxFactory, SCardScope.System); + _cardMonitor.CardInserted += _cardMonitor_CardInserted; + _cardMonitor.Start(_readerName); + _initialised = true; + } + } + } + _mainWorkerTerminationSignal.WaitOne(3000); } } @@ -169,5 +184,23 @@ namespace CardReaderService { return readerNames == null || readerNames.Count < 1; } + + private bool WeHaveValidCardReader() + { + if (_cardMonitor == null) + { + return false; + } + _logger.Trace(_cardMonitor.GetCurrentState(0).ToString()); + if (_cardMonitor.GetCurrentState(0) == SCRState.Unknown + || _cardMonitor.GetCurrentState(0) == SCRState.Unavailable + || _cardMonitor.GetCurrentState(0) == (SCRState.Ignore | SCRState.Unavailable) + //|| _cardMonitor.GetCurrentState(0) == SCRState.Unaware //if we say this is an invalid state, we cause a memory leak where we create a duplicate card monitor, subscribe and overwrite. + ) + { + return false; + } + return true; + } } } diff --git a/DataCenter_Windows/WindowsDataCenter/CardReaderService/DataCenterHelper.cs b/DataCenter_Windows/WindowsDataCenter/CardReaderService/DataCenterHelper.cs index 6bb0452..24e61cb 100644 --- a/DataCenter_Windows/WindowsDataCenter/CardReaderService/DataCenterHelper.cs +++ b/DataCenter_Windows/WindowsDataCenter/CardReaderService/DataCenterHelper.cs @@ -5,13 +5,14 @@ using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; +using Interfaces; using Newtonsoft.Json; namespace CardReaderService { static class DataCenterHelper { - public static void Post(CardDataPost postObject, string url) + public static void Post(ILogger logger, CardDataPost postObject, string url) { var endpointConfig = ConfigurationHandler.ConfigurationHandler.GetConfiguration("DataCenterServiceEndpoint") ?? "http://localhost:8800"; @@ -22,10 +23,10 @@ namespace CardReaderService var content = new StringContent(jsonObject, Encoding.UTF8, "application/json"); try { - Console.WriteLine("Writing"); + logger.Trace("Writing"); var fullUrl = endpointConfig + url; var response = client.PostAsync(fullUrl, content).Result; - Console.WriteLine("Written"); + logger.Trace("Written"); } catch (Exception) { @@ -35,9 +36,9 @@ namespace CardReaderService } } - public static Task PostAsync(CardDataPost postObject, string url) + public static Task PostAsync(ILogger logger, CardDataPost postObject, string url) { - return Task.Run(() => Post(postObject, url)); + return Task.Run(() => Post(logger, postObject, url)); } } diff --git a/DataCenter_Windows/WindowsDataCenter/NLogLogger/NLogConfig.xml b/DataCenter_Windows/WindowsDataCenter/NLogLogger/NLogConfig.xml index 819283f..9600876 100644 --- a/DataCenter_Windows/WindowsDataCenter/NLogLogger/NLogConfig.xml +++ b/DataCenter_Windows/WindowsDataCenter/NLogLogger/NLogConfig.xml @@ -4,8 +4,12 @@ autoReload="true"> + + \ No newline at end of file diff --git a/DataCenter_Windows/WindowsDataCenter/NLogLogger/NLogger.cs b/DataCenter_Windows/WindowsDataCenter/NLogLogger/NLogger.cs index 291b4a9..abbc712 100644 --- a/DataCenter_Windows/WindowsDataCenter/NLogLogger/NLogger.cs +++ b/DataCenter_Windows/WindowsDataCenter/NLogLogger/NLogger.cs @@ -9,14 +9,14 @@ namespace NLogLogger { public class NLogger:ILogger { - private NLog.Logger _logger; + private readonly Logger _logger; public NLogger() { var nlogConfigPathOption = ConfigurationHandler.ConfigurationHandler.GetConfiguration("NLogConfigFilePath"); if (nlogConfigPathOption == null) { - throw new ArgumentNullException("nlogConfigPath"); + throw new ArgumentNullException("nlogConfigPath", "NLogConfigFilePath missing from application config file."); } var nlogConfigPath = new Uri(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().CodeBase), nlogConfigPathOption)).LocalPath; LogManager.Configuration = new XmlLoggingConfiguration(nlogConfigPath);