using System.Diagnostics; using System.Net; using System.Text; using System.Web; using MarketData; using MarketData.Configuration; using MarketData.Integration; using MarketData.Utils; using Microsoft.Extensions.Configuration; namespace IPMonitor { public class MainService : IMainService { /// /// This is the main entry point. /// Arguments: /FORCE:true|false if true forces a refresh on ZoneEdit. /// Force an update to ZoneEdit at the top of every hour /// cron every hour /// DOTNET_ROOT=/opt/dotnet /// CRON_DIR_IPMONITOR=/opt/MarketData/IPMonitor /// 0 * * * * cd $CRON_DIR_IPMONITOR ; /opt/MarketData/IPMonitor/ipmonitor /FORCE:true > /dev/null 2>&1 /// cron 10 minute intervals except top of hour /// 10,20,30,40,50 * * * * cd $CRON_DIR_IPMONITOR ; /opt/MarketData/IPMonitor/ipmonitor > /dev/null 2>&1 /// /// /// public void RunService(String[] args,IConfiguration configuration) { Profiler profiler=new Profiler(); DateTime currentDate = DateTime.Now; GlobalConfig.Instance.Configuration = configuration; // This call sets up configuration stuff so it needs to be first. string arg = "ipmonitor"; CommandArgs commandArgs = new CommandArgs(args); if(!CreateLogging(arg)) { Console.WriteLine("CreateLogging returned false."); return; } try { MDTrace.WriteLine(LogLevel.DEBUG,$"[RunService] Started @ {Utility.DateTimeToStringYYYYHMMHDDHHMMSSTT(currentDate)} in {Directory.GetCurrentDirectory()}"); MDTrace.WriteLine(LogLevel.DEBUG,$"[RunService] Argument {arg}"); bool force=false; if(commandArgs.Has("FORCE")) { force=commandArgs.Coalesce("FORCE"); MDTrace.WriteLine(LogLevel.DEBUG,$"FORCE={force}"); } VerifyNetwork(); String ipAddress=GetPublicIPAddress(); UpdateIPAddress(ipAddress,force); } catch(Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); } finally { MDTrace.WriteLine(LogLevel.DEBUG,$"Done, total took {profiler.End()} (ms)"); } } private static bool CreateLogging(String task) { if(String.IsNullOrEmpty(task))return false; task=task.ToLower(); MDTrace.LogLevel = LogLevel.DEBUG; String logFolder = "/logs"; DateTime currentDate=DateTime.Now; String strLogFile = "marketdata_" + task + ".log"; String currentWorkingDirectory = Directory.GetCurrentDirectory(); Console.WriteLine($"Current directory is {currentWorkingDirectory}"); Utility.EnsureLogFolder(currentWorkingDirectory+logFolder); Utility.ExpireLogs(currentWorkingDirectory+logFolder,1); Trace.Listeners.Remove("Default"); Console.WriteLine($"Adding Trace Listener :{currentWorkingDirectory+logFolder+"/"+strLogFile}"); Trace.Listeners.Add(new TextWriterTraceListener(currentWorkingDirectory+logFolder+"/"+strLogFile)); MDTrace.WriteLine($"Trace Listener added."); Utility.ShowLogs(currentWorkingDirectory + logFolder); return true; } /// /// Verified that we are connected to the internet.00000000 /// Tghe method will retry for 5 minutes and then issue a reboot /// public static void VerifyNetwork() { int MAX_RETRIES=10; int TIMEOUT_BETWEEN_ATTEMPTS=30000; bool isNetworkAvailable=false; try { for(int index=0;index /// Retains a record of current ip address in ipaddress.txt file and updates that ip address to ZoneEdit for DNS /// /// public static void UpdateIPAddress(String ipAddress,bool force) { try { String strPathFileName="ipaddress.txt"; if(null==ipAddress)return; if(force) { File.Delete(GetPathFileName(strPathFileName)); } if(!File.Exists(GetPathFileName(strPathFileName))) { WriteFile(GetPathFileName(strPathFileName), ipAddress); ZoneEditResponses zoneEditResponses=UpdateZoneEditRecord(ipAddress); MDTrace.WriteLine(LogLevel.DEBUG,$"IPAddress {ipAddress}. ZoneEditUpdated={zoneEditResponses.IsSuccess()}"); SendSMSEmail(String.Format("IPAddress {0}. ZoneEditUpdated={1}",ipAddress,zoneEditResponses.IsSuccess())); if(!zoneEditResponses.IsSuccess()) { File.Delete(GetPathFileName(strPathFileName)); } } else { String currentIPAddress=ReadFile(GetPathFileName(strPathFileName)); if(null!=currentIPAddress && !currentIPAddress.Equals(ipAddress)) { WriteFile(GetPathFileName(strPathFileName),ipAddress); ZoneEditResponses zoneEditResponses=UpdateZoneEditRecord(ipAddress); SendSMSEmail(String.Format("IPAddress {0}. ZoneEditUpdated={1}",ipAddress,zoneEditResponses.IsSuccess())); } else if(null!=currentIPAddress && currentIPAddress.Equals(ipAddress)) { MDTrace.WriteLine(LogLevel.DEBUG,$"Public IP:{ipAddress} matches latest fetched IP:{currentIPAddress}"); } else if(null==currentIPAddress) { SendSMSEmail("IPMonitor "+ipAddress+ ". IPMonitor encountered an issue reading the IPAddress file."); } } } catch(Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); } } /// /// Retrieves the public IP Address. /// /// public static String GetPublicIPAddress() { int MAX_RETRIES=5; int TIMEOUT_BETWEEN_ATTEMPTS=30000; String request="http://checkip.dyndns.org/"; try { String address = null; for(int index=0;index"); address = address.Substring(first, last - first); MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request succeeded: {0} -> {1}",request,address)); return address; } catch(Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception parsing address: {0}",exception.ToString())); return null; } } catch(Exception exception) { String message = String.Format("Exception:{0}",exception.ToString()); MDTrace.WriteLine(LogLevel.DEBUG,message); SendSMSEmail("IPMonitor encountered an issue retrieving public IPAddress."); return null; } } /// /// Updates ZoneEdit with the given ipaddress. /// /// /// ZoneEditResponses public static ZoneEditResponses UpdateZoneEditRecord(String ipAddress) { HttpClient client = default; HttpNetResponse httpNetResponse=default; ZoneEditResponses zoneEditResponses = new ZoneEditResponses(); try { client = new HttpClient(); String user=GlobalConfig.Instance.Configuration["zoneedit_user"]; String password=GlobalConfig.Instance.Configuration["zoneedit_password"]; String host=GlobalConfig.Instance.Configuration["zoneedit_host"]; String strRequest=null; StringBuilder sb=new StringBuilder(); sb = new StringBuilder(); sb.Append("https://"); sb.Append("dynamic.zoneedit.com/auth/dynamic.html"); sb.Append("?host=").Append(HttpUtility.UrlEncode(host)); sb.Append("&dnsto=").Append(HttpUtility.UrlEncode(ipAddress)); strRequest=sb.ToString(); httpNetResponse = HttpNetRequest.GetRequestNoEncodingZoneEdit(strRequest,user,password); if(httpNetResponse.Success) { zoneEditResponses = new ZoneEditResponses(httpNetResponse.ResponseString); } foreach(ZoneEditResponse zoneEditResponse in zoneEditResponses) { MDTrace.WriteLine(LogLevel.DEBUG,$"Text:{zoneEditResponse.Text} Zone:{zoneEditResponse.Zone}"); } return zoneEditResponses; } finally { if(default!=client) { client.Dispose(); } if(default!=httpNetResponse) { httpNetResponse.Dispose(); } } } /// /// Writes the given ip address into the specified file /// /// /// public static void WriteFile(String strPathFileName,String ipAddress) { try { if(File.Exists(strPathFileName))File.Delete(strPathFileName); using FileStream fileStream=new FileStream(strPathFileName,FileMode.Create,FileAccess.Write,FileShare.Read); using StreamWriter streamWriter=new StreamWriter(fileStream); MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Creating address file:{0}",strPathFileName)); streamWriter.WriteLine(ipAddress); streamWriter.Flush(); } catch(Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); return; } } /// /// Reads a string from the specified file /// /// /// public static String ReadFile(String strPathFileName) { try { using FileStream fileStream=new FileStream(strPathFileName,FileMode.Open,FileAccess.ReadWrite,FileShare.Read); using StreamReader streamReader=new StreamReader(fileStream); String item=null; item=streamReader.ReadLine(); return item; } catch(Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); return null; } } /// /// Determines the fully qualified path file name for the provided file based on current directory and working folder /// /// /// public static String GetPathFileName(String fileName) { String currentWorkingDirectory = Directory.GetCurrentDirectory(); String workingFolder = GlobalConfig.Instance.Configuration["working_folder"]; if(workingFolder.StartsWith("/")) { String fullPath = currentWorkingDirectory+workingFolder; if(!Directory.Exists(fullPath))Directory.CreateDirectory(fullPath); return fullPath+"/"+fileName; } else { String fullPath = currentWorkingDirectory+"/"+workingFolder; if(!Directory.Exists(fullPath))Directory.CreateDirectory(fullPath); return fullPath+"/"+fileName; } } /// /// Sends an email. /// /// public static void SendSMSEmail(string message) { String smsSMTPAddress = GlobalConfig.Instance.Configuration["sms_smtpaddress"]; String smsUserName = GlobalConfig.Instance.Configuration["sms_smsusername"]; String smsPassword = GlobalConfig.Instance.Configuration["sms_smspassword"]; String[] smsRecipients = GlobalConfig.Instance.Configuration["sms_smsrecipients"].Split(','); bool sendNotifications = bool.Parse(GlobalConfig.Instance.Configuration["send_notifications"]); if(!sendNotifications) { MDTrace.WriteLine(LogLevel.DEBUG,$"Not sending Message '{message}' to {GlobalConfig.Instance.Configuration["sms_smsrecipients"]} because notifications are disabled."); return; } SMSClient.SendSMSEmail(message, smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword); } } }