DnsWebService: Implemented _webServiceHttpEP to keep track of correct http web server ep. Added dns app store support api. Using SocketsHttpHandler in CheckForUpdateAsync(). Code refactoring done.

This commit is contained in:
Shreyas Zare
2021-04-10 14:14:28 +05:30
parent f5da78c579
commit aadfb7cdec

View File

@@ -71,6 +71,7 @@ namespace DnsServerCore
readonly string _appFolder;
readonly string _configFolder;
readonly Uri _updateCheckUri;
readonly Uri _appStoreUri;
readonly LogManager _log;
@@ -91,6 +92,7 @@ namespace DnsServerCore
X509Certificate2 _webServiceTlsCertificate;
readonly IndependentTaskScheduler _webServiceTaskScheduler = new IndependentTaskScheduler(ThreadPriority.AboveNormal);
string _webServiceHostname;
IPEndPoint _webServiceHttpEP;
string _dnsTlsCertificatePath;
string _dnsTlsCertificatePassword;
@@ -121,7 +123,7 @@ namespace DnsServerCore
#region constructor
public DnsWebService(string configFolder = null, Uri updateCheckUri = null)
public DnsWebService(string configFolder = null, Uri updateCheckUri = null, Uri appStoreUri = null)
{
Assembly assembly = Assembly.GetExecutingAssembly();
AssemblyName assemblyName = assembly.GetName();
@@ -138,6 +140,7 @@ namespace DnsServerCore
Directory.CreateDirectory(_configFolder);
_updateCheckUri = updateCheckUri;
_appStoreUri = appStoreUri;
_log = new LogManager(_configFolder);
@@ -282,17 +285,8 @@ namespace DnsServerCore
await sslStream.AuthenticateAsServerAsync(_webServiceTlsCertificate);
IPEndPoint httpEP;
if (_webServiceLocalAddresses[0].Equals(IPAddress.Any))
httpEP = new IPEndPoint(IPAddress.Loopback, _webServiceHttpPort);
else if (_webServiceLocalAddresses[0].Equals(IPAddress.IPv6Any))
httpEP = new IPEndPoint(IPAddress.IPv6Loopback, _webServiceHttpPort);
else
httpEP = new IPEndPoint(_webServiceLocalAddresses[0], _webServiceHttpPort);
tunnel = new Socket(httpEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
tunnel.Connect(httpEP);
tunnel = new Socket(_webServiceHttpEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
tunnel.Connect(_webServiceHttpEP);
NetworkStream tunnelStream = new NetworkStream(tunnel, true);
@@ -516,7 +510,19 @@ namespace DnsServerCore
break;
case "/api/apps/list":
ListApps(jsonWriter);
ListInstalledApps(jsonWriter);
break;
case "/api/apps/listStoreApps":
await ListStoreApps(jsonWriter);
break;
case "/api/apps/downloadAndInstall":
await DownloadAndInstallAppAsync(request);
break;
case "/api/apps/downloadAndUpdate":
await DownloadAndUpdateAppAsync(request);
break;
case "/api/apps/install":
@@ -1036,7 +1042,7 @@ namespace DnsServerCore
{
try
{
HttpClientHandler handler = new HttpClientHandler();
SocketsHttpHandler handler = new SocketsHttpHandler();
handler.Proxy = _dnsServer.Proxy;
using (HttpClient http = new HttpClient(handler))
@@ -1127,7 +1133,12 @@ namespace DnsServerCore
jsonWriter.WriteStartArray();
foreach (IPAddress localAddress in _webServiceLocalAddresses)
jsonWriter.WriteValue(localAddress.ToString());
{
if (localAddress.AddressFamily == AddressFamily.InterNetworkV6)
jsonWriter.WriteValue("[" + localAddress.ToString() + "]");
else
jsonWriter.WriteValue(localAddress.ToString());
}
jsonWriter.WriteEndArray();
@@ -4707,7 +4718,7 @@ namespace DnsServerCore
#region dns apps api
private void ListApps(JsonTextWriter jsonWriter)
private void ListInstalledApps(JsonTextWriter jsonWriter)
{
List<string> apps = new List<string>(_dnsServer.DnsApplicationManager.Applications.Keys);
@@ -4756,6 +4767,166 @@ namespace DnsServerCore
jsonWriter.WriteEndArray();
}
private async Task ListStoreApps(JsonTextWriter jsonWriter)
{
SocketsHttpHandler handler = new SocketsHttpHandler();
handler.Proxy = _dnsServer.Proxy;
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (HttpClient http = new HttpClient(handler))
{
string strStoreAppsJsonArray = await http.GetStringAsync(_appStoreUri);
dynamic jsonStoreAppsArray = JsonConvert.DeserializeObject(strStoreAppsJsonArray);
List<string> installedApps = new List<string>(_dnsServer.DnsApplicationManager.Applications.Keys);
jsonWriter.WritePropertyName("storeApps");
jsonWriter.WriteStartArray();
foreach (dynamic jsonStoreApp in jsonStoreAppsArray)
{
string name = jsonStoreApp.name.Value;
string version = jsonStoreApp.version.Value;
string description = jsonStoreApp.description.Value;
string url = jsonStoreApp.url.Value;
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("name");
jsonWriter.WriteValue(name);
jsonWriter.WritePropertyName("version");
jsonWriter.WriteValue(version);
jsonWriter.WritePropertyName("description");
jsonWriter.WriteValue(description);
jsonWriter.WritePropertyName("url");
jsonWriter.WriteValue(url);
bool installed = _dnsServer.DnsApplicationManager.Applications.TryGetValue(name, out DnsApplication installedApp);
jsonWriter.WritePropertyName("installed");
jsonWriter.WriteValue(installed);
if (installed)
{
jsonWriter.WritePropertyName("installedVersion");
jsonWriter.WriteValue(GetCleanVersion(installedApp.Version));
jsonWriter.WritePropertyName("updateAvailable");
jsonWriter.WriteValue(new Version(version) > installedApp.Version);
}
jsonWriter.WriteEndObject();
}
jsonWriter.WriteEndArray();
}
}
private async Task DownloadAndInstallAppAsync(HttpListenerRequest request)
{
string name = request.QueryString["name"];
if (string.IsNullOrEmpty(name))
throw new DnsWebServiceException("Parameter 'name' missing.");
string url = request.QueryString["url"];
if (string.IsNullOrEmpty(url))
throw new DnsWebServiceException("Parameter 'url' missing.");
if (!url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
throw new DnsWebServiceException("Parameter 'url' value must start with 'https://'.");
string tmpFile = Path.GetTempFileName();
try
{
using (FileStream fS = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite))
{
//download to temp file
SocketsHttpHandler handler = new SocketsHttpHandler();
handler.Proxy = _dnsServer.Proxy;
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (HttpClient http = new HttpClient(handler))
{
using (Stream httpStream = await http.GetStreamAsync(url))
{
await httpStream.CopyToAsync(fS);
}
}
//install app
fS.Position = 0;
await _dnsServer.DnsApplicationManager.InstallApplicationAsync(name, fS);
_log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DNS application '" + name + "' was installed successfully from: " + url);
}
}
finally
{
try
{
File.Delete(tmpFile);
}
catch (Exception ex)
{
_log.Write(ex);
}
}
}
private async Task DownloadAndUpdateAppAsync(HttpListenerRequest request)
{
string name = request.QueryString["name"];
if (string.IsNullOrEmpty(name))
throw new DnsWebServiceException("Parameter 'name' missing.");
string url = request.QueryString["url"];
if (string.IsNullOrEmpty(url))
throw new DnsWebServiceException("Parameter 'url' missing.");
if (!url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
throw new DnsWebServiceException("Parameter 'url' value must start with 'https://'.");
string tmpFile = Path.GetTempFileName();
try
{
using (FileStream fS = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite))
{
//download to temp file
SocketsHttpHandler handler = new SocketsHttpHandler();
handler.Proxy = _dnsServer.Proxy;
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (HttpClient http = new HttpClient(handler))
{
using (Stream httpStream = await http.GetStreamAsync(url))
{
await httpStream.CopyToAsync(fS);
}
}
//update app
fS.Position = 0;
await _dnsServer.DnsApplicationManager.UpdateApplicationAsync(name, fS);
_log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DNS application '" + name + "' was updated successfully from: " + url);
}
}
finally
{
try
{
File.Delete(tmpFile);
}
catch (Exception ex)
{
_log.Write(ex);
}
}
}
private async Task InstallAppAsync(HttpListenerRequest request)
{
string name = request.QueryString["name"];
@@ -4788,18 +4959,19 @@ namespace DnsServerCore
#endregion
//write to temp file
string tmpFile = Path.GetTempFileName();
try
{
using (FileStream fS = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite))
{
//write to temp file
await request.InputStream.CopyToAsync(fS);
//install app
fS.Position = 0;
await _dnsServer.DnsApplicationManager.InstallApplicationAsync(name, fS);
_log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DNS application was installed successfully: " + name);
_log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DNS application '" + name + "' was installed successfully.");
}
}
finally
@@ -4847,18 +5019,19 @@ namespace DnsServerCore
#endregion
//write to temp file
string tmpFile = Path.GetTempFileName();
try
{
using (FileStream fS = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite))
{
//write to temp file
await request.InputStream.CopyToAsync(fS);
//update app
fS.Position = 0;
await _dnsServer.DnsApplicationManager.UpdateApplicationAsync(name, fS);
_log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DNS application was updated successfully: " + name);
_log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DNS application '" + name + "' was updated successfully.");
}
}
finally
@@ -4881,7 +5054,7 @@ namespace DnsServerCore
throw new DnsWebServiceException("Parameter 'name' missing.");
_dnsServer.DnsApplicationManager.UninstallApplication(name);
_log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DNS application was uninstalled successfully: " + name);
_log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DNS application '" + name + "' was uninstalled successfully.");
}
private async Task GetAppConfigAsync(HttpListenerRequest request, JsonTextWriter jsonWriter)
@@ -5172,26 +5345,32 @@ namespace DnsServerCore
private void ListDhcpLeases(JsonTextWriter jsonWriter)
{
ICollection<Scope> scopes = _dhcpServer.Scopes;
IReadOnlyDictionary<string, Scope> scopes = _dhcpServer.Scopes;
//sort by name
Scope[] scopesArray = new Scope[scopes.Count];
scopes.CopyTo(scopesArray, 0);
Array.Sort(scopesArray);
List<Scope> sortedScopes = new List<Scope>(scopes.Count);
foreach (KeyValuePair<string, Scope> entry in scopes)
sortedScopes.Add(entry.Value);
sortedScopes.Sort();
jsonWriter.WritePropertyName("leases");
jsonWriter.WriteStartArray();
foreach (Scope scope in scopesArray)
foreach (Scope scope in sortedScopes)
{
ICollection<Lease> leases = scope.Leases;
IReadOnlyDictionary<ClientIdentifierOption, Lease> leases = scope.Leases;
//sort by address
Lease[] leasesArray = new Lease[leases.Count];
leases.CopyTo(leasesArray, 0);
Array.Sort(leasesArray);
List<Lease> sortedLeases = new List<Lease>(leases.Count);
foreach (Lease lease in leasesArray)
foreach (KeyValuePair<ClientIdentifierOption, Lease> entry in leases)
sortedLeases.Add(entry.Value);
sortedLeases.Sort();
foreach (Lease lease in sortedLeases)
{
jsonWriter.WriteStartObject();
@@ -5225,17 +5404,20 @@ namespace DnsServerCore
private void ListDhcpScopes(JsonTextWriter jsonWriter)
{
ICollection<Scope> scopes = _dhcpServer.Scopes;
IReadOnlyDictionary<string, Scope> scopes = _dhcpServer.Scopes;
//sort by name
Scope[] scopesArray = new Scope[scopes.Count];
scopes.CopyTo(scopesArray, 0);
Array.Sort(scopesArray);
List<Scope> sortedScopes = new List<Scope>(scopes.Count);
foreach (KeyValuePair<string, Scope> entry in scopes)
sortedScopes.Add(entry.Value);
sortedScopes.Sort();
jsonWriter.WritePropertyName("scopes");
jsonWriter.WriteStartArray();
foreach (Scope scope in scopesArray)
foreach (Scope scope in sortedScopes)
{
jsonWriter.WriteStartObject();
@@ -5512,8 +5694,10 @@ namespace DnsServerCore
IPAddress endingAddress = IPAddress.Parse(strEndingAddress);
//validate scope address
foreach (Scope existingScope in _dhcpServer.Scopes)
foreach (KeyValuePair<string, Scope> entry in _dhcpServer.Scopes)
{
Scope existingScope = entry.Value;
if (existingScope.Equals(scope))
continue;
@@ -6485,14 +6669,24 @@ namespace DnsServerCore
string webServiceHostname = null;
_webService = new HttpListener();
IPAddress httpAddress = null;
foreach (IPAddress webServiceLocalAddress in _webServiceLocalAddresses)
{
string host;
if (webServiceLocalAddress.Equals(IPAddress.Any) || webServiceLocalAddress.Equals(IPAddress.IPv6Any))
if (webServiceLocalAddress.Equals(IPAddress.Any))
{
host = "+";
httpAddress = IPAddress.Loopback;
}
else if (webServiceLocalAddress.Equals(IPAddress.IPv6Any))
{
host = "+";
if ((httpAddress == null) || !IPAddress.IsLoopback(httpAddress))
httpAddress = IPAddress.IPv6Loopback;
}
else
{
@@ -6501,6 +6695,9 @@ namespace DnsServerCore
else
host = webServiceLocalAddress.ToString();
if (httpAddress == null)
httpAddress = webServiceLocalAddress;
if (webServiceHostname == null)
webServiceHostname = host;
}
@@ -6510,6 +6707,11 @@ namespace DnsServerCore
_webService.Start();
if (httpAddress == null)
httpAddress = IPAddress.Loopback;
_webServiceHttpEP = new IPEndPoint(httpAddress, _webServiceHttpPort);
_webServiceHostname = webServiceHostname ?? Environment.MachineName.ToLower();
}
catch (Exception ex)
@@ -6530,6 +6732,8 @@ namespace DnsServerCore
_webService.Start();
}
_webServiceHttpEP = new IPEndPoint(IPAddress.Loopback, _webServiceHttpPort);
_webServiceHostname = "localhost";
}