Fix: Disable HTTP KeepAlive

To improve support for proxy servers which do not support this
optimisation.
See:
http://discoict.com.au/forum/support/2013/2/connection-issues,-lwt,-updates-etc.aspx
This commit is contained in:
Gary Sharp
2013-02-08 12:32:54 +11:00
parent 8089544dab
commit eb03365513
7 changed files with 684 additions and 655 deletions
+198 -185
View File
@@ -1,185 +1,198 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Xml.Serialization;
using Disco.Data.Repository;
using Disco.Models.BI.Interop.Community;
using Disco.Services.Tasks;
using Newtonsoft.Json;
namespace Disco.BI.Interop.Community
{
public static class UpdateCheck
{
private static string UpdateUrl(DiscoDataContext db)
{
// Special case for DiscoCommunity Hosting Network
try
{
var ip = (from addr in Dns.GetHostEntry(Dns.GetHostName()).AddressList
where addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
&& addr.ToString().StartsWith("10.131.200.")
select addr).FirstOrDefault();
if (ip != null)
{
return "http://hades3:9393/base/DiscoUpdate/V1";
}
}
catch (Exception)
{} // Ignore Errors
return "http://discoict.com.au/base/DiscoUpdate/V1";
}
public static string CurrentDiscoVersion()
{
var AssemblyVersion = typeof(UpdateCheck).Assembly.GetName().Version;
return string.Format("{0}.{1}.{2:0000}.{3:0000}", AssemblyVersion.Major, AssemblyVersion.Minor, AssemblyVersion.Build, AssemblyVersion.Revision);
}
public static UpdateResponse Check(DiscoDataContext db, bool UseProxy, ScheduledTaskStatus status = null)
{
if (status != null)
status.UpdateStatus(10, "Building Update Request");
var request = BuildRequest(db);
//var requestJson = JsonConvert.SerializeObject(request);
if (status != null)
status.UpdateStatus(40, "Sending Request");
var DiscoBIVersion = CurrentDiscoVersion();
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(UpdateUrl(db));
webRequest.ContentType = "application/json";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.UserAgent = string.Format("Disco/{0} (Update)", DiscoBIVersion);
using (var wrStream = webRequest.GetRequestStream())
{
XmlSerializer xml = new XmlSerializer(typeof(UpdateRequestV1));
xml.Serialize(wrStream, request);
}
if (status != null)
status.UpdateStatus(50, "Waiting for Response");
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
if (status != null)
status.UpdateStatus(90, "Reading Response");
UpdateResponse result;
using (var wResStream = webResponse.GetResponseStream())
{
XmlSerializer xml = new XmlSerializer(typeof(UpdateResponse));
result = (UpdateResponse)xml.Deserialize(wResStream);
}
//var result = JsonConvert.DeserializeObject<UpdateResponse>(responseContent);
db.DiscoConfiguration.UpdateLastCheck = result;
db.SaveChanges();
status.SetFinishedMessage(string.Format("The update server reported Version {0} is the latest.", result.Version));
return result;
}
else
{
if (status != null)
status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return null;
}
}
}
private static UpdateRequestV1 BuildRequest(DiscoDataContext db)
{
var m = new UpdateRequestV1();
m.DeploymentId = db.DiscoConfiguration.DeploymentId;
m.CurrentDiscoVersion = CurrentDiscoVersion();
m.OrganisationName = db.DiscoConfiguration.OrganisationName;
m.BroadbandDoeWanId = GetBroadbandDoeWanId();
m.BetaDeployment = db.DiscoConfiguration.UpdateBetaDeployment;
m.Stat_JobCounts = db.Jobs.GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
m.Stat_OpenJobCounts = db.Jobs.Where(j => j.ClosedDate == null).GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
var activeThreshold = DateTime.Now.AddDays(-60);
m.Stat_ActiveDeviceModelCounts = db.DeviceModels.Select(dm => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = dm.Manufacturer + ";" + dm.Model, Count = dm.Devices.Count(d => d.DecommissionedDate == null && (d.LastNetworkLogonDate == null || d.LastNetworkLogonDate > activeThreshold)) }).ToList();
m.Stat_UserCounts = db.Users.GroupBy(u => u.Type).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
return m;
}
#region DoE Query
public static string GetBroadbandDoeWanId()
{
// DnsQuery for broadband.doe.wan
IPHostEntry doeWanDnsEntry;
try
{
doeWanDnsEntry = Dns.GetHostEntry("broadband.doe.wan");
}
catch (Exception)
{ return null; } // Fail on error
// Try using IPSearch feature
XDocument doeWanIPSearchResult = TryDownloadDoeIPSearch(false);
if (doeWanIPSearchResult == null)
doeWanIPSearchResult = TryDownloadDoeIPSearch(true);
if (doeWanIPSearchResult == null)
return null;
try
{
return doeWanIPSearchResult.Element("resultset").Element("site").Element("number").Value.ToLower();
}
catch (Exception)
{ return null; } // Fail on error
}
private static XDocument TryDownloadDoeIPSearch(bool useProxy)
{
try
{
var DiscoBIVersion = CurrentDiscoVersion();
HttpWebRequest wReq = (HttpWebRequest)HttpWebRequest.Create("http://broadband.doe.wan/ipsearch/showresult.php");
if (!useProxy)
wReq.Proxy = new WebProxy(); // Empty Proxy Config
wReq.Method = WebRequestMethods.Http.Post;
wReq.ContentType = "application/x-www-form-urlencoded";
wReq.UserAgent = string.Format("Disco/{0}", DiscoBIVersion);
using (var wrStream = wReq.GetRequestStream())
{
using (var wrStreamWriter = new StreamWriter(wrStream))
{
wrStreamWriter.Write("mode=whoami");
}
}
using (HttpWebResponse wRes = (HttpWebResponse)wReq.GetResponse())
{
if (wRes.StatusCode == HttpStatusCode.OK)
{
using (var wResStream = wRes.GetResponseStream())
{
return XDocument.Load(wResStream);
}
}
else
return null;
}
}
catch (Exception)
{ return null; } // Fail on error
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Xml.Serialization;
using Disco.Data.Repository;
using Disco.Models.BI.Interop.Community;
using Disco.Services.Tasks;
using Newtonsoft.Json;
namespace Disco.BI.Interop.Community
{
public static class UpdateCheck
{
private static string UpdateUrl(DiscoDataContext db)
{
// Special case for DiscoCommunity Hosting Network
try
{
var ip = (from addr in Dns.GetHostEntry(Dns.GetHostName()).AddressList
where addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
&& addr.ToString().StartsWith("10.131.200.")
select addr).FirstOrDefault();
if (ip != null)
{
return "http://hades3:9393/base/DiscoUpdate/V1";
}
}
catch (Exception)
{ } // Ignore Errors
return "http://discoict.com.au/base/DiscoUpdate/V1";
}
public static string CurrentDiscoVersion()
{
var AssemblyVersion = typeof(UpdateCheck).Assembly.GetName().Version;
return string.Format("{0}.{1}.{2:0000}.{3:0000}", AssemblyVersion.Major, AssemblyVersion.Minor, AssemblyVersion.Build, AssemblyVersion.Revision);
}
public static UpdateResponse Check(DiscoDataContext db, bool UseProxy, ScheduledTaskStatus status = null)
{
if (status != null)
status.UpdateStatus(10, "Building Update Request");
var request = BuildRequest(db);
//var requestJson = JsonConvert.SerializeObject(request);
if (status != null)
status.UpdateStatus(40, "Sending Request");
var DiscoBIVersion = CurrentDiscoVersion();
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(UpdateUrl(db));
// Added: 2013-02-08 G#
// Fix for Proxy Servers which dont support KeepAlive
webRequest.KeepAlive = false;
// End Added: 2013-02-08 G#
if (!UseProxy)
webRequest.Proxy = new WebProxy();
webRequest.ContentType = "application/json";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.UserAgent = string.Format("Disco/{0} (Update)", DiscoBIVersion);
using (var wrStream = webRequest.GetRequestStream())
{
XmlSerializer xml = new XmlSerializer(typeof(UpdateRequestV1));
xml.Serialize(wrStream, request);
}
if (status != null)
status.UpdateStatus(50, "Waiting for Response");
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
if (status != null)
status.UpdateStatus(90, "Reading Response");
UpdateResponse result;
using (var wResStream = webResponse.GetResponseStream())
{
XmlSerializer xml = new XmlSerializer(typeof(UpdateResponse));
result = (UpdateResponse)xml.Deserialize(wResStream);
}
//var result = JsonConvert.DeserializeObject<UpdateResponse>(responseContent);
db.DiscoConfiguration.UpdateLastCheck = result;
db.SaveChanges();
status.SetFinishedMessage(string.Format("The update server reported Version {0} is the latest.", result.Version));
return result;
}
else
{
if (status != null)
status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return null;
}
}
}
private static UpdateRequestV1 BuildRequest(DiscoDataContext db)
{
var m = new UpdateRequestV1();
m.DeploymentId = db.DiscoConfiguration.DeploymentId;
m.CurrentDiscoVersion = CurrentDiscoVersion();
m.OrganisationName = db.DiscoConfiguration.OrganisationName;
m.BroadbandDoeWanId = GetBroadbandDoeWanId();
m.BetaDeployment = db.DiscoConfiguration.UpdateBetaDeployment;
m.Stat_JobCounts = db.Jobs.GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
m.Stat_OpenJobCounts = db.Jobs.Where(j => j.ClosedDate == null).GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
var activeThreshold = DateTime.Now.AddDays(-60);
m.Stat_ActiveDeviceModelCounts = db.DeviceModels.Select(dm => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = dm.Manufacturer + ";" + dm.Model, Count = dm.Devices.Count(d => d.DecommissionedDate == null && (d.LastNetworkLogonDate == null || d.LastNetworkLogonDate > activeThreshold)) }).ToList();
m.Stat_UserCounts = db.Users.GroupBy(u => u.Type).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
return m;
}
#region DoE Query
public static string GetBroadbandDoeWanId()
{
// DnsQuery for broadband.doe.wan
IPHostEntry doeWanDnsEntry;
try
{
doeWanDnsEntry = Dns.GetHostEntry("broadband.doe.wan");
}
catch (Exception)
{ return null; } // Fail on error
// Try using IPSearch feature
XDocument doeWanIPSearchResult = TryDownloadDoeIPSearch(false);
if (doeWanIPSearchResult == null)
doeWanIPSearchResult = TryDownloadDoeIPSearch(true);
if (doeWanIPSearchResult == null)
return null;
try
{
return doeWanIPSearchResult.Element("resultset").Element("site").Element("number").Value.ToLower();
}
catch (Exception)
{ return null; } // Fail on error
}
private static XDocument TryDownloadDoeIPSearch(bool useProxy)
{
try
{
var DiscoBIVersion = CurrentDiscoVersion();
HttpWebRequest wReq = (HttpWebRequest)HttpWebRequest.Create("http://broadband.doe.wan/ipsearch/showresult.php");
// Added: 2013-02-08 G#
// Fix for Proxy Servers which dont support KeepAlive
webRequest.KeepAlive = false;
// End Added: 2013-02-08 G#
if (!useProxy)
wReq.Proxy = new WebProxy(); // Empty Proxy Config
wReq.Method = WebRequestMethods.Http.Post;
wReq.ContentType = "application/x-www-form-urlencoded";
wReq.UserAgent = string.Format("Disco/{0}", DiscoBIVersion);
using (var wrStream = wReq.GetRequestStream())
{
using (var wrStreamWriter = new StreamWriter(wrStream))
{
wrStreamWriter.Write("mode=whoami");
}
}
using (HttpWebResponse wRes = (HttpWebResponse)wReq.GetResponse())
{
if (wRes.StatusCode == HttpStatusCode.OK)
{
using (var wResStream = wRes.GetResponseStream())
{
return XDocument.Load(wResStream);
}
}
else
return null;
}
}
catch (Exception)
{ return null; } // Fail on error
}
#endregion
}
}
@@ -1,86 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.Data.Repository;
using Disco.Services.Logging;
using Disco.Services.Tasks;
using Quartz;
namespace Disco.BI.Interop.Community
{
public class UpdateCheckTask : ScheduledTask
{
public override string TaskName { get { return "Disco Community - Check for Update"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public static ScheduledTaskStatus ScheduleNow()
{
var runningTasks = ScheduledTasks.GetTaskStatuses(typeof(UpdateCheckTask)).Where(ts => ts.IsRunning).ToList();
if (runningTasks.Count > 0)
return runningTasks.First();
else
{
var t = new UpdateCheckTask();
return t.ScheduleTask();
}
}
public static ScheduledTaskStatus RunningStatus
{
get
{
return ScheduledTasks.GetTaskStatuses(typeof(UpdateCheckTask)).Where(ts => ts.IsRunning).FirstOrDefault();
}
}
public static DateTime? NextScheduled
{
get
{
var runningTasks = ScheduledTasks.GetTaskStatuses(typeof(UpdateCheckTask)).ToList();
DateTime timestamp = DateTime.MaxValue;
foreach (var t in runningTasks)
{
if (t.NextScheduledTimestamp != null && t.NextScheduledTimestamp.Value < timestamp)
timestamp = t.NextScheduledTimestamp.Value;
}
if (timestamp == DateTime.MaxValue)
return null;
else
return timestamp;
}
}
public override void InitalizeScheduledTask(Data.Repository.DiscoDataContext dbContext)
{
// ActiveDirectoryUpdateLastNetworkLogonDateJob @ 11:30pm
var rnd = new Random();
var rndHour = rnd.Next(12, 23);
var rndMinute = rnd.Next(0, 59);
TriggerBuilder triggerBuilder = TriggerBuilder.Create().
WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(rndHour, rndMinute));
this.ScheduleTask(triggerBuilder);
}
protected override void ExecuteTask()
{
using (DiscoDataContext db = new DiscoDataContext())
{
try
{
UpdateCheck.Check(db, true, this.Status);
}
catch (Exception)
{
// Could be proxy error - try again without proxy:
UpdateCheck.Check(db, false, this.Status);
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.Data.Repository;
using Disco.Services.Logging;
using Disco.Services.Tasks;
using Quartz;
namespace Disco.BI.Interop.Community
{
public class UpdateCheckTask : ScheduledTask
{
public override string TaskName { get { return "Disco Community - Check for Update"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public static ScheduledTaskStatus ScheduleNow()
{
var runningTasks = ScheduledTasks.GetTaskStatuses(typeof(UpdateCheckTask)).Where(ts => ts.IsRunning).ToList();
if (runningTasks.Count > 0)
return runningTasks.First();
else
{
var t = new UpdateCheckTask();
return t.ScheduleTask();
}
}
public static ScheduledTaskStatus RunningStatus
{
get
{
return ScheduledTasks.GetTaskStatuses(typeof(UpdateCheckTask)).Where(ts => ts.IsRunning).FirstOrDefault();
}
}
public static DateTime? NextScheduled
{
get
{
var runningTasks = ScheduledTasks.GetTaskStatuses(typeof(UpdateCheckTask)).ToList();
DateTime timestamp = DateTime.MaxValue;
foreach (var t in runningTasks)
{
if (t.NextScheduledTimestamp != null && t.NextScheduledTimestamp.Value < timestamp)
timestamp = t.NextScheduledTimestamp.Value;
}
if (timestamp == DateTime.MaxValue)
return null;
else
return timestamp;
}
}
public override void InitalizeScheduledTask(Data.Repository.DiscoDataContext dbContext)
{
// ActiveDirectoryUpdateLastNetworkLogonDateJob @ 11:30pm
var rnd = new Random();
var rndHour = rnd.Next(12, 23);
var rndMinute = rnd.Next(0, 59);
TriggerBuilder triggerBuilder = TriggerBuilder.Create().
WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(rndHour, rndMinute));
this.ScheduleTask(triggerBuilder);
}
protected override void ExecuteTask()
{
using (DiscoDataContext db = new DiscoDataContext())
{
try
{
UpdateCheck.Check(db, true, this.Status);
}
catch (Exception ex)
{
ScheduledTasksLog.LogScheduledTaskException(this.Status.TaskName, this.Status.SessionId, this.Status.TaskType, ex);
// Could be proxy error - try again without proxy:
UpdateCheck.Check(db, false, this.Status);
}
}
}
}
}