/*
* Copyright (c) Contributors, http://opensimulator.org/, http://www.nsl.tuis.ac.jp/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma warning disable S1128 // Unused "using" should be removed
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Timers;
using OpenSim.Framework.Servers.HttpServer;
using Nini.Config;
using log4net;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Servers;
using OpenSim.Data;
using NSL.Certificate.Tools;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using log4net.Appender;
using log4net.Core;
using log4net.Repository;
using OpenMetaverse;
using Timer = System.Timers.Timer;
#pragma warning restore S1128 // Unused "using" should be removed
///
/// OpenSim Grid MoneyServer
///
namespace OpenSim.Grid.MoneyServer
{
///
/// class MoneyServerBase : BaseOpenSimServer, IMoneyServiceCore
/// Manni internal class
///
internal class MoneyServerBase : BaseOpenSimServer, IMoneyServiceCore
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private string connectionString = string.Empty;
private uint m_moneyServerPort = 8008; // 8008 is default server port
private string m_certFilename = "";
private string m_certPassword = "";
private string m_cacertFilename = "";
private string m_clcrlFilename = "";
private bool m_checkClientCert = false;
private int DEAD_TIME = 120;
private int MAX_DB_CONNECTION = 10;
#pragma warning disable S1450 // Private fields only used as local variables in methods should become local variables
private MoneyXmlRpcModule m_moneyXmlRpcModule;
#pragma warning restore S1450 // Private fields only used as local variables in methods should become local variables
private MoneyDBService m_moneyDBService;
#pragma warning disable S2933 // Fields that are only assigned in the constructor should be "readonly"
private Dictionary m_sessionDic = new Dictionary();
private Dictionary m_secureSessionDic = new Dictionary();
private Dictionary m_webSessionDic = new Dictionary();
#pragma warning restore S2933 // Fields that are only assigned in the constructor should be "readonly"
IConfig m_server_config;
IConfig m_cert_config;
///
/// Money Server Base
///
public MoneyServerBase()
{
m_console = new RemoteConsole("MoneyServer ");
MainConsole.Instance = m_console;
}
///
/// Work
///
public void Work()
{
//The timer checks the transactions table every 60 seconds
Timer checkTimer = new Timer
{
Interval = 60 * 1000,
Enabled = true
};
checkTimer.Elapsed += new ElapsedEventHandler(CheckTransaction);
checkTimer.Start();
while (true) {
m_console.Prompt();
}
}
///
/// Check the transactions table, set expired transaction state to failed
///
private void CheckTransaction(object sender, ElapsedEventArgs e)
{
long ticksToEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
int unixEpochTime =(int) ((DateTime.UtcNow.Ticks - ticksToEpoch )/10000000);
int deadTime = unixEpochTime - DEAD_TIME;
m_moneyDBService.SetTransExpired(deadTime);
}
///
/// Startup Specific
///
protected override void StartupSpecific()
{
m_log.Info("[MONEY SERVER]: Setup HTTP Server process");
ReadIniConfig();
try {
if (m_certFilename != "")
{
m_httpServer = new BaseHttpServer(m_moneyServerPort, true, m_certFilename, m_certPassword);
if (m_checkClientCert) {
Type typeBaseHttpServer = typeof(BaseHttpServer);
PropertyInfo pinfo = typeBaseHttpServer.GetProperty("CertificateValidationCallback");
if (pinfo!=null) {
m_log.Info ("[MONEY SERVER]: Set RemoteCertificateValidationCallback");
}
else {
m_log.Error("[MONEY SERVER]: StartupSpecific: CheckClientCert is true. But this MoneyServer does not support CheckClientCert!!");
}
}
}
else {
m_httpServer = new BaseHttpServer(m_moneyServerPort);
}
SetupMoneyServices();
m_httpServer.Start();
base.StartupSpecific();
}
catch (Exception e)
{
m_log.ErrorFormat("[MONEY SERVER]: StartupSpecific: Fail to start HTTPS process");
m_log.ErrorFormat("[MONEY SERVER]: StartupSpecific: Please Check Certificate File or Password. Exit");
m_log.ErrorFormat("[MONEY SERVER]: StartupSpecific: {0}", e);
Environment.Exit(1);
}
}
///
/// Read Ini Config
///
protected void ReadIniConfig()
{
MoneyServerConfigSource moneyConfig = new MoneyServerConfigSource();
Config = moneyConfig.m_config;
try {
// [Startup]
IConfig st_config = moneyConfig.m_config.Configs["Startup"];
string PIDFile = st_config.GetString("PIDFile", "");
if (PIDFile != "") Create_PIDFile(PIDFile);
// [MySql]
IConfig db_config = moneyConfig.m_config.Configs["MySql"];
string sqlserver = db_config.GetString("hostname", "localhost");
string database = db_config.GetString("database", "OpenSim");
string username = db_config.GetString("username", "root");
string password = db_config.GetString("password", "password");
string pooling = db_config.GetString("pooling", "false");
string port = db_config.GetString("port", "3306");
MAX_DB_CONNECTION = db_config.GetInt ("MaxConnection", MAX_DB_CONNECTION);
connectionString = "Server=" + sqlserver + ";Port=" + port + ";Database=" + database + ";User ID=" +
username + ";Password=" + password + ";Pooling=" + pooling + ";";
// [MoneyServer]
m_server_config = moneyConfig.m_config.Configs["MoneyServer"];
DEAD_TIME = m_server_config.GetInt("ExpiredTime", DEAD_TIME);
m_moneyServerPort = (uint)m_server_config.GetInt("ServerPort", (int)m_moneyServerPort);
//
// [Certificate]
m_cert_config = moneyConfig.m_config.Configs["Certificate"];
if (m_cert_config==null) {
m_log.Info("[MONEY SERVER]: [Certificate] section is not found. Using [MoneyServer] section instead");
m_cert_config = m_server_config;
}
// HTTPS Server Cert (Server Mode)
m_certFilename = m_cert_config.GetString("ServerCertFilename", m_certFilename);
m_certPassword = m_cert_config.GetString("ServerCertPassword", m_certPassword);
if (m_certFilename != "")
{
m_log.Info("[MONEY SERVER]: ReadIniConfig: Execute HTTPS comunication. Cert file is " + m_certFilename);
}
m_checkClientCert = m_cert_config.GetBoolean("CheckClientCert", m_checkClientCert);
m_cacertFilename = m_cert_config.GetString("CACertFilename", m_cacertFilename);
m_clcrlFilename = m_cert_config.GetString("ClientCrlFilename", m_clcrlFilename);
//
if (m_checkClientCert && m_cacertFilename != "")
{
m_log.Info("[MONEY SERVER]: ReadIniConfig: Execute Authentication of Clients. CA file is " + m_cacertFilename);
}
else {
m_checkClientCert = false;
}
if (m_checkClientCert)
{
if (m_clcrlFilename != "")
{
m_log.Info("[MONEY SERVER]: ReadIniConfig: Execute Authentication of Clients. CRL file is " + m_clcrlFilename);
}
}
}
catch (Exception)
{
m_log.Error("[MONEY SERVER]: ReadIniConfig: Fail to setup configure. Please check MoneyServer.ini. Exit");
Environment.Exit(1);
}
}
///
/// Create PID File added by skidz
///
protected void Create_PIDFile(string path)
{
try
{
string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
FileStream fs = File.Create(path);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
Byte[] buf = enc.GetBytes(pidstring);
fs.Write(buf, 0, buf.Length);
fs.Close();
m_pidFile = path;
}
catch (Exception)
{
}
}
///
/// Setup Money Services
///
protected virtual void SetupMoneyServices()
{
m_log.Info("[MONEY SERVER]: Connecting to Money Storage Server");
m_moneyDBService = new MoneyDBService();
m_moneyDBService.Initialise(connectionString, MAX_DB_CONNECTION);
m_moneyXmlRpcModule = new MoneyXmlRpcModule();
m_moneyXmlRpcModule.Initialise(m_version, m_moneyDBService, this);
m_moneyXmlRpcModule.PostInitialise();
}
///
/// Is Check Client Cert
///
public bool IsCheckClientCert()
{
return m_checkClientCert;
}
///
/// Get Server Config
///
public IConfig GetServerConfig()
{
return m_server_config;
}
///
/// Get Cert Config
///
public IConfig GetCertConfig()
{
return m_cert_config;
}
///
/// Get Http Server
///
public BaseHttpServer GetHttpServer()
{
return m_httpServer;
}
///
/// Get Session Dic
///
public Dictionary GetSessionDic()
{
return m_sessionDic;
}
///
/// Get Secure Session Dic
///
public Dictionary GetSecureSessionDic()
{
return m_secureSessionDic;
}
///
/// Get Web Session Dic
///
public Dictionary GetWebSessionDic()
{
return m_webSessionDic;
}
}
///
/// class Money Server Config Source
///
class MoneyServerConfigSource
{
///
/// Ini Config Source
///
public IniConfigSource m_config;
///
/// Money Server Config Source
///
public MoneyServerConfigSource()
{
string configPath = Path.Combine(Directory.GetCurrentDirectory(), "MoneyServer.ini");
if (File.Exists(configPath))
{
m_config = new IniConfigSource(configPath);
}
else
{
}
}
///
/// Save config
///
public void Save(string path)
{
m_config.Save(path);
}
}
}