using Step.CmsConnectManager.Events;
using Step.CmsConnectManager.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static Step.CmsConnectManager.CMSConnectConstants;
namespace Step.CmsConnectManager
{
public class GatewayController
{
private SSHAdapter SSHAdapter;
//---------------------------------------------------------------------------------------------------
#region Public_methods
///
/// Simple constructor.
/// Create an instance with this configuration: hostname: localhost, username: root, password: root.
///
public GatewayController()
{
SSHAdapter = new SSHAdapter("localhost", "root", "root");
}
///
/// Advanced constructor.
/// Create an instance with the configuration passed by arguments
///
/// Name (or IP-Address) of the gateway
/// Username for Gateway Login
/// Password for Gateway Login
/// Thrown when one parameter is null
public GatewayController(string hostname, string username, string password)
{
SSHAdapter = new SSHAdapter(hostname, username, password);
}
///
/// Write Proxy-Configuration on Gateway.
/// See for generate the configuration.
///
/// Configuration of the proxy.
///
public void WriteGatewayProxyConfiguration(GatewayProxyConfiguration proxyConfiguration)
{
string Command = SSHAdapter.GenerateSshProxyCommand(proxyConfiguration);
SSHAdapter.SendSSHCommand(Command);
}
///
/// Write Newtork-Configuration on Gateway.
/// See for generate the configuration.
///
/// Configuration of the network.
///
public void WriteGatewayNetworkConfiguration(GatewayNetworkConfiguration networkConfiguration)
{
string NetworkCommand = SSHAdapter.GenerateSshNetworkCommand(networkConfiguration);
string DnsIpCommand = SSHAdapter.GenerateSshDnsCommand(networkConfiguration);
string DnsSuffixCommand = SSHAdapter.GenerateSshDnsSuffxCommand(networkConfiguration);
SSHAdapter.SendSSHCommand(new List() { NetworkCommand, DnsIpCommand, DnsSuffixCommand });
}
///
/// Read Newtork-Configuration saved on Gateway.
///
/// See
///
///
public GatewayNetworkConfiguration ReadGatewayNetworkConfiguration()
{
return ElaborateConfigFromSshNetworkCommand( SSHAdapter.SendSSHCommand(SSH_GET_NETWORK_COMMAND) );
}
///
/// Read Proxy-Configuration saved on Gateway.
///
/// See
///
///
public GatewayProxyConfiguration ReadGatewayProxyConfiguration()
{
return ElaborateConfigFromSshProxyCommand( SSHAdapter.SendSSHCommand(SSH_GET_PROXY_COMMAND));
}
///
/// Test connection to SCM/CMS Server, on Gateway.
///
/// Seconds timeout for the request
///
public GatewayConnectionStatus TestGatewayConnection(int timeout)
{
if (timeout < 0)
throw new ArgumentOutOfRangeException("Timeout must be > 0");
return ElaborateTestConnectionCommand(SSHAdapter.SendSSHCommand(SSH_TEST_CONNECTION_COMMAND + timeout));
}
///
/// Reboot asynchronously the Gateway.
///
/// Serconds to delay before reboot
/// Handler Callback when the operation is finished or an error occours.
/// See
///
public void RebootGatewayAsync(int delay, EventHandler handler)
{
if (delay < 0)
throw new ArgumentOutOfRangeException("Delay must be > 0");
//Create the Action
Action> action = (int del, EventHandler hand) =>
{
GatewayRebootEventHandlerArgs ev = new GatewayRebootEventHandlerArgs();
try
{
SSHAdapter.SendSSHReboot(del);
}
catch (Exception e)
{
ev.ErrorStatus = true;
ev.ErrorMessage = e.Message;
}
hand(this, ev);
};
// Create a task and not start it.
Task t = new Task (() => action(delay, handler));
t.Start();
}
///
/// Reboot and wait a new session of the Gateway.
///
/// Seconds to delay before reboot
///
public void RebootGateway(int delay)
{
if (delay < 0)
throw new ArgumentOutOfRangeException("Delay must be > 0");
// Send Command
SSHAdapter.SendSSHReboot(delay);
}
#endregion
//---------------------------------------------------------------------------------------------------
#region SSH_commands_preparations_sub_methods
#endregion
//---------------------------------------------------------------------------------------------------
#region elaborate_SSH_values_sub_methods
private GatewayNetworkConfiguration ElaborateConfigFromSshNetworkCommand(List lines)
{
GatewayNetworkConfiguration configuration = new GatewayNetworkConfiguration();
foreach (string line in lines)
{
if (line.StartsWith(IP_ADDR_LABEL))
DecodeNetworkIPAddress(line.Remove(0, IP_ADDR_LABEL.Length).Trim(), ref configuration);
else if (line.StartsWith(GATEWAY_LABEL))
DecodeNetworkDefGateway(line.Remove(0, GATEWAY_LABEL.Length).Trim(), ref configuration);
else if (line.StartsWith(DNSIP_LABEL))
DecodeNetworkDnsIp(line.Remove(0, DNSIP_LABEL.Length).Trim(), ref configuration);
else if (line.StartsWith(DNSPREFIX_LABEL))
DecodeNetworkDnsPrefix(line.Remove(0, DNSPREFIX_LABEL.Length).Trim(), ref configuration);
}
return configuration;
}
private GatewayProxyConfiguration ElaborateConfigFromSshProxyCommand(List lines)
{
GatewayProxyConfiguration configuration = new GatewayProxyConfiguration();
foreach (string line in lines)
{
if (line.StartsWith(PROXY_ADDR_LABEL))
DecodeProxyAddress(line.Remove(0, PROXY_ADDR_LABEL.Length).Trim(), ref configuration);
else if (line.StartsWith(NO_PROXY_LABEL))
DecodeNoProxyUrls(line.Remove(0, NO_PROXY_LABEL.Length).Trim(), ref configuration);
}
return configuration;
}
private GatewayConnectionStatus ElaborateTestConnectionCommand(List lines)
{
GatewayConnectionStatus status = new GatewayConnectionStatus();
foreach (string line in lines)
{
if (!string.IsNullOrWhiteSpace(line))
DecodeConnectionStatus(line.Trim(), ref status);
}
return status;
}
#endregion
//---------------------------------------------------------------------------------------------------
#region decode_SSH_values_sub_methods
private void DecodeNetworkIPAddress(string stringValue, ref GatewayNetworkConfiguration configuration)
{
//Check if has DHCP
if (stringValue == "DHCP")
configuration.hasDhcp = true;
else
{
configuration.hasDhcp = false;
//Check if has / for netmask
if (!stringValue.Contains('/'))
throw new GatewayException("Internal Gateway Error during read (bad format): " + IP_ADDR_LABEL + stringValue);
string [] tempAddr = stringValue.Split('/');
//Check if has lenght == 2
if (tempAddr.Length != 2)
throw new GatewayException("Internal Gateway Error during read (bad format): " + IP_ADDR_LABEL + stringValue);
//Set the IPAddress / Netmask
IPAddress tempIp;
if (!EvaluateIPV4(tempAddr[0], out tempIp))
throw new GatewayException("Internal Gateway Error during read (bad format): " + IP_ADDR_LABEL + stringValue);
IPNetwork tempIpNetw;
if (!IPNetwork.TryParse(stringValue, out tempIpNetw))
throw new GatewayException("Internal Gateway Error during read (bad format): " + IP_ADDR_LABEL + stringValue);
configuration.ipAddress = tempIp;
configuration.netMaskAddress = tempIpNetw.Netmask;
}
}
private void DecodeNetworkDefGateway(string stringValue, ref GatewayNetworkConfiguration configuration)
{
//check if is defined
if (stringValue == UNDEF_VALUE)
configuration.defaultGatewayAddress = null;
else
{
if (!EvaluateIPV4(stringValue, out IPAddress tempIp))
throw new GatewayException("Internal Gateway Error during read (bad format): " + GATEWAY_LABEL + stringValue);
configuration.defaultGatewayAddress = tempIp;
}
}
private void DecodeNetworkDnsIp(string stringValue, ref GatewayNetworkConfiguration configuration)
{
//check if is defined
if (stringValue == UNDEF_VALUE)
configuration.dnsAddresses = null;
else
{
string[] tempStr = stringValue.Split(' ');
if (tempStr.Length == 0)
configuration.dnsAddresses = null;
else
{
IPAddress tempIp;
List tempDns = new List();
foreach (string str in tempStr)
{
if (string.IsNullOrEmpty(str))
continue;
if (!EvaluateIPV4(str, out tempIp))
throw new GatewayException("Internal Gateway Error during read (bad format): " + DNSIP_LABEL + stringValue);
tempDns.Add(tempIp);
}
configuration.dnsAddresses = tempDns;
}
}
}
private void DecodeNetworkDnsPrefix(string stringValue, ref GatewayNetworkConfiguration configuration)
{
// Check if is defined
if (stringValue == UNDEF_VALUE)
configuration.dnsPrefixes = null;
else
{
string[] tempStr = stringValue.Split(' ');
if (tempStr.Length == 0)
configuration.dnsPrefixes = null;
else
configuration.dnsPrefixes = tempStr.Where(X=> !string.IsNullOrEmpty(X)).ToList();
}
}
private void DecodeProxyAddress(string stringValue, ref GatewayProxyConfiguration configuration)
{
// Check if is defined
if (stringValue == UNDEF_VALUE)
configuration.hasProxy = false;
else
{
configuration.hasProxy = true;
/* Must be one of these:
* - Address:Port
* - User:Password@Address:Port
*/
if (!stringValue.Contains("@"))
{
// Set username & password
configuration.username = null;
configuration.password = null;
// Check if has :
if (!stringValue.Contains(':'))
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
string[] tempAddr = stringValue.Split(':');
// Check if has lenght == 2
if (tempAddr.Length != 2)
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
// Set the address
configuration.address = tempAddr[0];
// Set the port
if (!uint.TryParse(tempAddr[1], out uint tempPort))
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
configuration.port = tempPort;
}
else
{
string[] splitted = stringValue.Split('@');
//Check if has lenght == 2
if (splitted.Length != 2)
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
//Check if has :
if (!splitted[0].Contains(':'))
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
if (!splitted[1].Contains(':'))
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
string[] tempLogin = splitted[0].Split(':');
string[] tempAddr = splitted[1].Split(':');
//Check if has lenght == 2
if (tempLogin.Length != 2)
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
if (tempAddr.Length != 2)
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
// Set the username
configuration.username = tempLogin[0];
// Set the password
configuration.password = tempLogin[1];
// Set the address
configuration.address = tempAddr[0];
// Set the port
if (!uint.TryParse(tempAddr[1], out uint tempPort))
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
configuration.port = tempPort;
}
}
}
private void DecodeNoProxyUrls(string stringValue, ref GatewayProxyConfiguration configuration)
{
// Check if is defined
if (stringValue == UNDEF_VALUE)
configuration.noproxyAddresses = null;
else
{
string[] tempStr = stringValue.Trim('"').Split(',');
for (int i=0;i