using System; using System.Collections.Generic; using System.Linq; using System.Text; using Pluto.Api; using System.Net; using PlutoServer.MSL.Connectors; namespace PlutoServer.MSL { public static class RegistrationWrapper { // Allow the Registration wrapper to let the Service enter into a different 'disconnected' state internal static int HasConnectivityErrorCountInARow = 0; internal static int HasConnectivityErrorCountMaxBeforeStateChange = 10; internal static string RegistrationHOST = ""; internal static uint RegistrationPORT = 0; #region Connectivity /// /// Check to make sure we can communicate with the Registration Service. /// Check the Server's ip & port for connectivity as well as that this /// computer has connectivity. /// This way we won't throw any connectivity errors, which is good. /// /// true, if successfully can connect, false otherwise private static bool HasConnectivity() { try { bool bCanConnect = false; bool bUseConfiguration = true; // Try the overwritten Registration Host and Port first, if exists if (RegistrationHOST != "" && RegistrationPORT > 0) { bCanConnect = Yaulw.Net.IPHostHelper.HasConnectivity(RegistrationHOST, RegistrationPORT, 0); if (bCanConnect) bUseConfiguration = false; } // Else, fall-back on the configuration, if we couldn't connect if (!bCanConnect) { bCanConnect = Yaulw.Net.IPHostHelper.HasConnectivity(Configuration.REGISTRATION_HOST_URL, (uint)Configuration.REGISTRATION_CHANNEL_PORT, 0); if (bCanConnect) bUseConfiguration = true; } if (bCanConnect) { MSLSpecific.Logger.Info("Network Communication successful with the McKesson's Mobile Gateway bUseConfiguration={0}", bUseConfiguration.ToString()); if (bUseConfiguration) { IPAddress ip = Yaulw.Net.IPHostHelper.GetIpForHost(Configuration.REGISTRATION_HOST_URL); RegistrationAPI.API.SetNetworkSettings(ip.ToString(), (uint)Configuration.REGISTRATION_CHANNEL_PORT); } else { IPAddress ip = Yaulw.Net.IPHostHelper.GetIpForHost(RegistrationHOST); RegistrationAPI.API.SetNetworkSettings(ip.ToString(), RegistrationPORT); } HasConnectivityErrorCountInARow = 0; } else { // Try to retrieve the latest Host and Port Setting online try { string HostNPortSetOnline = Yaulw.Net.WCHelper.ScreenScrapeFromURL(Configuration.REGISTRATION_HOST_N_PORT_URL); if (!String.IsNullOrEmpty(HostNPortSetOnline)) { RegistrationHOST = HostNPortSetOnline.Split(';')[0]; RegistrationPORT = uint.Parse(HostNPortSetOnline.Split(';')[1]); } } catch (Exception e) { MSLSpecific.Logger.Error("Retrieving Host and Port Setting from REGISTRATION_HOST_N_PORT_URL failed", e); } // Try to connection one more time if (RegistrationHOST != "" && RegistrationPORT > 0) bCanConnect = Yaulw.Net.IPHostHelper.HasConnectivity(RegistrationHOST, RegistrationPORT, 0); // if we can connect, we are Golden if (bCanConnect) { MSLSpecific.Logger.Info("Network Communication successful with the McKesson's Mobile Gateway bUseConfiguration=False"); IPAddress ip = Yaulw.Net.IPHostHelper.GetIpForHost(RegistrationHOST); RegistrationAPI.API.SetNetworkSettings(ip.ToString(), RegistrationPORT); HasConnectivityErrorCountInARow = 0; } else { // Connectivity Errors too plentiful - Change the state of the service to reflect that if (HasConnectivityErrorCountInARow >= HasConnectivityErrorCountMaxBeforeStateChange) { MSLSpecific.Logger.Info("Entering no_Connectivity to McKesson's Mobile Gateway state"); PlutoService.state = HostGUIDstate.no_connectivity; } else { MSLSpecific.Logger.Error("Network Communication unsuccessful with McKesson's Mobile Gateway"); HasConnectivityErrorCountInARow++; } } } return bCanConnect; } catch (Exception e) { MSLSpecific.Logger.Error("HasConnectivity() error thrown", e); } return false; } #endregion #region Registration Specifics that don't require network /// /// Get a Practice Name with (MCK) in it (for internal usuage) /// /// /// public static string GetMCKPractice(string PracticeName) { return RegistrationAPI.API.GetMcKInternalizedPracticeName(PracticeName); } #endregion #region Update Server /// /// Update Server Internal / External /// /// /// /// public static void UpdateServerIntExt(IPAddress internalIP, IPAddress externalIP, uint Port) { string LocalIP = ""; if (Yaulw.Net.IPHostHelper.IsValidIPv4Address(internalIP, false)) LocalIP = internalIP.ToString(); string ExternalIP = ""; if (Yaulw.Net.IPHostHelper.IsValidIPv4Address(externalIP, false)) ExternalIP = externalIP.ToString(); if ((!String.IsNullOrEmpty(LocalIP) || !String.IsNullOrEmpty(ExternalIP)) || Port > 0) UpdateServerIntExt(LocalIP, ExternalIP, Port); else MSLSpecific.Logger.Info("UpdateServerIntExt was called with invalid parameters. Registration not updated."); } /// /// Update Server Internal / External (actually does the work) /// /// /// /// private static void UpdateServerIntExt(string internalIP, string externalIP, uint Port) { try { if(HasConnectivity()) { bool bSuccess = RegistrationAPI.API.UpdateServer(MSLSpecific.GetHostGUID(), internalIP, externalIP, Port); if (bSuccess) MSLSpecific.Logger.Info("Updating IP Internal/External information occured successfully for Host:{0} LocalIP:{1}, ExternalIP:{2}, Port:{3}", MSLSpecific.GetHostGUID(), internalIP, externalIP, Port); else MSLSpecific.Logger.Error("Updating IP Internal/External information failed for Host:{0} LocalIP:{1}, ExternalIP:{2}, Port:{3}", MSLSpecific.GetHostGUID(), internalIP, externalIP, Port); } } catch (Exception e) { MSLSpecific.Logger.Error("UdateServerIntExt Error Thrown", e); } } /// /// Update Server Internal /// /// /// public static void UpdateServerInternal(IPAddress internalIP) { string LocalIP = ""; if (Yaulw.Net.IPHostHelper.IsValidIPv4Address(internalIP, false)) LocalIP = internalIP.ToString(); if (!String.IsNullOrEmpty(LocalIP)) UpdateServerInternal(LocalIP); else MSLSpecific.Logger.Info("UpdateServerInternal was called with invalid parameters. Registration not updated."); } /// /// Update Server Internal (actually does the work) /// /// /// /// private static void UpdateServerInternal(string internalIP) { try { if (HasConnectivity()) { bool bSuccess = RegistrationAPI.API.UpdateServer(MSLSpecific.GetHostGUID(), internalIP, String.Empty, PlutoService.INTERNAL_CHANNEL_PORT); if (bSuccess) MSLSpecific.Logger.Info("Updating IP Internal information occured successfully for Host:{0} LocalIP:{1}, Port:{2}", MSLSpecific.GetHostGUID(), internalIP, PlutoService.INTERNAL_CHANNEL_PORT); else MSLSpecific.Logger.Error("Updating IP Internal information failed for Host:{0} LocalIP:{1}, Port:{2}", MSLSpecific.GetHostGUID(), internalIP, PlutoService.INTERNAL_CHANNEL_PORT); } } catch (Exception e) { MSLSpecific.Logger.Error("UpdateServerInternal Error Thrown", e); } } #endregion #region Register Update/New Practice /// /// Register New Practice /// /// Name of Practice /// Is Medisoft /// out ApiKey /// out Pin /// true, if successful, false otherwise public static bool RegisterNewPractice(string PracticeName, bool bIsMedisoft, out string strApiKey, out string strPin) { strApiKey = ""; strPin = ""; try { if (HasConnectivity()) { // Set up local IP string LocalIP = ""; if (Yaulw.Net.IPHostHelper.IsValidIPv4Address(PlutoService.InternalIP, false)) LocalIP = PlutoService.InternalIP.ToString(); // Set up external IP and Port string ExternalIP = ""; uint Port = 0; if (PlutoService.IsExtIPandExtPortSet) { if (Yaulw.Net.IPHostHelper.IsValidIPv4Address(PlutoService.ExternalIP, false)) ExternalIP = PlutoService.ExternalIP.ToString(); Port = PlutoService.ExternalPort; } else { Port = PlutoService.INTERNAL_CHANNEL_PORT; } // Set up Practice Name if (PlutoService.IsOnMcKessonNetwork) PracticeName = GetMCKPractice(PracticeName); // Set up Product Name string ProductName = ProductType.GetProductName(bIsMedisoft); // Make the Registration Call MSLSpecific.Logger.Info("Registering PracticeName:{0}, LocalIP:{1}, ExternalIP:{2}, Port:{3}, ProductName:{4} for Host:{5}", PracticeName, LocalIP, ExternalIP, Port, ProductName, MSLSpecific.GetHostGUID()); bool bSuccess = RegistrationAPI.API.RegisterNewServerPractice(MSLSpecific.GetHostGUID(), PracticeName, LocalIP, ExternalIP, Port, ProductName, out strApiKey, out strPin); if (bSuccess) MSLSpecific.Logger.Info("Registering Practice successfully"); else MSLSpecific.Logger.Error("Registering Practice failed"); return bSuccess; } } catch (Exception e) { MSLSpecific.Logger.Error("RegisterNewPractice Error Thrown", e); } return false; } /// /// Update Practice Name /// /// /// /// /// public static bool UpdatePracticeName(string UserApiKey, string Pin, string NewPracticeName) { try { if (HasConnectivity()) { // Set up Practice Name if (PlutoService.IsOnMcKessonNetwork) NewPracticeName = GetMCKPractice(NewPracticeName); bool bSuccess = RegistrationAPI.API.UpdatePracticeName(UserApiKey, Pin, NewPracticeName); if (bSuccess) MSLSpecific.Logger.Info("Updating Practice Name successfully"); else MSLSpecific.Logger.Error("Updating Practice Name failed"); return bSuccess; } } catch (Exception e) { MSLSpecific.Logger.Error("UpdatePracticeName Error Thrown", e); } return false; } #endregion #region Other Register Methods /// /// Retrieve Pin for UserApiKey /// /// /// public static string RetrievePinForUserApiKey(string UserApiKey) { try { if (HasConnectivity()) { if (!String.IsNullOrEmpty(UserApiKey)) { string Pin = RegistrationAPI.API.RetrieveUserApiKeyPin(UserApiKey); return Pin; } } } catch (Exception e) { MSLSpecific.Logger.Error("RetrievePinForUserApiKey Error Thrown", e); } return String.Empty; } /// /// Is this Server reachable online /// /// public static bool IsServerReachable() { try { if (PlutoService.IsOnMcKessonNetwork) { MSLSpecific.Logger.Info("This host/server is in WIFI only mode, due to being on the McKesson Network"); PlutoService.AppLogWarning("This is a host/server is in WIFI only mode, due to being on the McKesson Network"); return false; } if (!PlutoService.IsExtIPandExtPortSet) { MSLSpecific.Logger.Info("This host/server is in WIFI only mode, external connectivity not configured"); PlutoService.AppLogWarning("This is a host/server is in WIFI only mode, external connectivity not configured"); return false; } if (HasConnectivity()) { bool bSuccess = RegistrationAPI.API.IsServerReachable(PlutoService.ExternalIP.ToString(), PlutoService.ExternalPort); if (bSuccess) MSLSpecific.Logger.Info("The server/host was reachable (success) on External IP:{0} and Port:{1}", PlutoService.ExternalIP.ToString(), PlutoService.ExternalPort); else MSLSpecific.Logger.Error("The server/host was unreachable (failure) on External IP:{0} and Port:{1}", PlutoService.ExternalIP.ToString(), PlutoService.ExternalPort); return bSuccess; } } catch (Exception e) { MSLSpecific.Logger.Error("IsServerReachable Error Thrown", e); } return false; } /// /// Is a specific Server reachable online /// /// /// /// /// public static bool IsServerReachable(IPAddress externalIP, uint Port) { try { // Set up external IP string ExtIP = ""; if (Yaulw.Net.IPHostHelper.IsValidIPv4Address(externalIP, false)) ExtIP = externalIP.ToString(); if (String.IsNullOrEmpty(ExtIP)) { MSLSpecific.Logger.Info("Invalid External IP passed in"); return false; } // Check Port if (Port <= 0) { MSLSpecific.Logger.Info("Invalid Port passed in"); return false; } // Check Connectivity if (HasConnectivity()) { bool bSuccess = RegistrationAPI.API.IsServerReachable(ExtIP, Port); if (bSuccess) MSLSpecific.Logger.Info("The server/host was reachable (success) on External IP:{0} and Port:{1}", ExtIP, Port); else MSLSpecific.Logger.Error("The server/host was unreachable (failure) on External IP:{0} and Port:{1}", ExtIP, Port); return bSuccess; } } catch (Exception e) { MSLSpecific.Logger.Error(String.Format("IsServerReachable Error Thrown with ExtIP={0} and Port={1}", externalIP.ToString(), Port.ToString()), e); } return false; } /// /// Retrieve the HostGUID from a Server/Port if that Server Port is running Pluto /// /// /// /// HostGUID or "" if none found public static string RetrieveHostGUIDForServer(IPAddress externalIP, uint Port) { try { // Set up external IP string ExtIP = ""; if (Yaulw.Net.IPHostHelper.IsValidIPv4Address(externalIP, false)) ExtIP = externalIP.ToString(); if (String.IsNullOrEmpty(ExtIP)) { MSLSpecific.Logger.Info("Invalid External IP passed in"); return String.Empty; } // Check Port if (Port <= 0) { MSLSpecific.Logger.Info("Invalid Port passed in"); return String.Empty; } if(HasConnectivity()) { string retVal = RegistrationAPI.API.RetrievePlutoHostGUID(externalIP.ToString(), Port); return retVal; } } catch (Exception e) { MSLSpecific.Logger.Error("RetrieveHostGUIDForServer Error Thrown", e); } return String.Empty; } /// /// Connectivity / HOST Guid State * Important for Integrity Checking * /// public enum HostGUIDstate { exists, not_exists, no_connectivity } /// /// Quick Check to see if our host guid even exists on the server, if it doesn't /// then no need to call UpdateServer() in any form /// /// public static HostGUIDstate DoesServerHostGuidExist() { try { if (HasConnectivity()) { bool bExists = RegistrationAPI.API.DoesServerHostGUIDExist(MSLSpecific.GetHostGUID()); if (bExists) { MSLSpecific.Logger.Info("HostGuid found on Mobile Gateway Server. Some Practice(s) are registered online"); return HostGUIDstate.exists; } else { MSLSpecific.Logger.Info("HostGuid not found on Mobile Gateway Server. No Practice is registered online"); return HostGUIDstate.not_exists; } } } catch (Exception e) { MSLSpecific.Logger.Error("DoesServerHostGuidExist Error Thrown", e); } return HostGUIDstate.no_connectivity; } /// /// Let the Registration Service know what we have been updated /// /// public static void ServerHasBeenUpdated(string version) { try { if (HasConnectivity()) { RegistrationAPI.API.ServerHasBeenUpdated(MSLSpecific.GetHostGUID(), version); } } catch (Exception e) { MSLSpecific.Logger.Error("ServerHasBeenUpdated Error Thrown", e); } } #endregion } }