Add IPMonitor
This commit is contained in:
348
IPMonitor/Services/MainService.cs
Executable file
348
IPMonitor/Services/MainService.cs
Executable file
@@ -0,0 +1,348 @@
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <param name="configuration"></param>
|
||||
public void RunService(String[] args,IConfiguration configuration)
|
||||
{
|
||||
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
|
||||
{
|
||||
Profiler profiler=new Profiler();
|
||||
profiler.Start();
|
||||
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<bool>("FORCE");
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,$"FORCE={force}");
|
||||
}
|
||||
String ipAddress=GetPublicIPAddress();
|
||||
UpdateIPAddress(ipAddress,force);
|
||||
}
|
||||
catch(Exception exception)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retains a record of current ip address in ipaddress.txt file and updates that ip address to ZoneEdit for DNS
|
||||
/// </summary>
|
||||
/// <param name="ipAddress"></param>
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the public IP Address
|
||||
/// </summary>
|
||||
/// <param name="ipAddress"></param>
|
||||
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<MAX_RETRIES && null==address;index++)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,$"Requesting IPAddress from {request}");
|
||||
if(!NetworkStatus.IsNetworkAvailable(0))
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The Network seems to be disconnected. Will retry after {0} (ms) ",request,TIMEOUT_BETWEEN_ATTEMPTS));
|
||||
try{Thread.Sleep(TIMEOUT_BETWEEN_ATTEMPTS);}catch{;}
|
||||
continue;
|
||||
}
|
||||
address = GetHttpRequest(request);
|
||||
if(null==address)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request failed {0}. Will retry after {1} (ms) ",request,TIMEOUT_BETWEEN_ATTEMPTS));
|
||||
try{Thread.Sleep(TIMEOUT_BETWEEN_ATTEMPTS);}catch{;}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(null==address)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,$"Unable to obtain IP Address. Attempts:{MAX_RETRIES}");
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
int first = address.IndexOf("Address: ") + 9;
|
||||
int last = address.LastIndexOf("</body>");
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends an HttpRequest and receives the response string. Used by GetPublicIPAddress
|
||||
/// </summary>
|
||||
/// <param name="ipAddress"></param>
|
||||
public static String GetHttpRequest(String strRequest)
|
||||
{
|
||||
try
|
||||
{
|
||||
WebRequest request = WebRequest.Create(strRequest);
|
||||
using WebResponse response = request.GetResponse();
|
||||
using (StreamReader stream = new StreamReader(response.GetResponseStream()))
|
||||
{
|
||||
return stream.ReadToEnd();
|
||||
}
|
||||
}
|
||||
catch(Exception exception)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request {strRequest} Failed with {1}",exception.ToString()));
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates ZoneEdit with the given ipaddress.
|
||||
/// </summary>
|
||||
/// <param name="ipAddress"></param>
|
||||
/// <returns>ZoneEditResponses</returns>
|
||||
public static ZoneEditResponses UpdateZoneEditRecord(String ipAddress)
|
||||
{
|
||||
HttpClient client = default;
|
||||
HttpNetResponse httpNetResponse=default;
|
||||
|
||||
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)
|
||||
{
|
||||
return new ZoneEditResponses();
|
||||
}
|
||||
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",httpNetResponse.ResponseString));
|
||||
return new ZoneEditResponses(httpNetResponse.ResponseString);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(default!=client)
|
||||
{
|
||||
client.Dispose();
|
||||
}
|
||||
if(default!=httpNetResponse)
|
||||
{
|
||||
httpNetResponse.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the given ip address into the specified file
|
||||
/// </summary>
|
||||
/// <param name="strPathFileName"></param>
|
||||
/// <param name="ipAddress"></param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a string from the specified file
|
||||
/// </summary>
|
||||
/// <param name="strPathFileName"></param>
|
||||
/// <param name="ipAddress"></param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the fully qualified path file name for the provided file based on current directory and working folder
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends an email.
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
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(',');
|
||||
SMSClient.SendSMSEmail(message, smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user