using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Xml.Serialization;
using System.IO;

using System.Net;
using System.Net.Sockets;

//using DWItaly.Sinp.Utility;
using Wayne.Lib;
using Wayne.FDCPOSLibrary;
using Wayne.FDCPOSLibrary.Configuration;


namespace Wayne.ForecourtControl.Fusion
{
    public class TCPListenerThread
    {
        public bool bRunning = false;

        public bool bTerminate = false;
        TcpListener tcpListener = null;
        IFSFManager ifsfManager = null;
        string name = "";

        public TCPListenerThread(TcpListener _listener, IFSFManager _ifsfManager, string _name)
        {
            tcpListener = _listener;
            ifsfManager = _ifsfManager;
            name = _name;
        }

        public void TCPListenerThreadProc()
        {
            Trace.WriteLine(string.Format("TCPListenerThreadProc Id={0}, WId={1}: init", this.ifsfManager.clientSocket.Id, this.ifsfManager.clientSocket.workstationID));
            TcpClient tcpclient = null;
            bRunning = true;
            try
            {
                if (tcpListener != null)
                {
                    Trace.WriteLine("tcpListener starting");
                    tcpListener.Start();
                    Trace.WriteLine("tcpListener started");
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine("TCPListenerThreadProc: Exception tcpListener.Start! " + ex.Message + " - " + ex.StackTrace);
                bRunning = false;
                return;
            }

            bTerminate = false;
            string sbuffer = "";
            OverallResult result = OverallResult.Success;
            NetworkStream networkStream = null;
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            while (!bTerminate)
            {
                try
                {
                    result = OverallResult.Success;

                    if (tcpclient == null && tcpListener != null) //-- || !tcpclient.Connected)
                    {
                        Trace.WriteLine("TCPListenerThreadProc: TcpClient Accepting");
                        tcpclient = tcpListener.AcceptTcpClient();
                        Trace.WriteLine("TcpClient Accepted");
                    }
                    else
                    {
                        //Trace.WriteLine(string.Format("{0} getting stream ...", this.name));
                        if (tcpListener != null)
                            networkStream = tcpclient.GetStream();
                        else if (ifsfManager.clientSocket.socketReqChannelA != null)  // Disconnet() makes _socketRequChannelA to null!!!
                            networkStream = ifsfManager.clientSocket.socketReqChannelA.GetStream();
                        else
                        {
                            Trace.WriteLine("Both tcpListener and socketReqChannelA are null!!! break out - Id=" + this.ifsfManager.clientSocket.Id);
                            break;
                        }

                        Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("TCPListenerThreadProc Id={0}, WId={1}: {2} got stream ...", this.ifsfManager.clientSocket.Id, this.ifsfManager.clientSocket.workstationID, this.name));
                        StringBuilder sb = new StringBuilder();


                        // read header
                        byte[] header;
                        int headerLength, encrStart;
                        if (FDCGlobal.ProtocolVersion <= FDCVersion.V0007)
                        {
                            headerLength = Define.HeaderLength + Define.MD5EncriptionLength;
                            encrStart = Define.HeaderLength;
                        }
                        else if (this.ifsfManager.clientSocket.headerEncryption != 0)
                        {
                            headerLength = Define.HeaderLength + Define.EncriptionTypeLength + Define.MD5EncriptionLength;
                            encrStart = Define.HeaderLength + Define.EncriptionTypeLength;
                        }
                        else
                        {
                            headerLength = Define.HeaderLength + Define.EncriptionTypeLength;
                            encrStart = Define.HeaderLength + Define.EncriptionTypeLength;
                        }
                        header = new byte[headerLength];
                        Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("TCPListenerThreadProc: header length={0}", header.GetLength(0)));
                        int nread = 0, nreadtot = 0;
                        do
                        {
                            Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TCPListenerThreadProc: reading ..."));
                            nread = networkStream.Read(header, nreadtot, (headerLength) - nreadtot);
                            Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TCPListenerThreadProc Id={0}, WId={1}: read '{2}' bytes", this.ifsfManager.clientSocket.Id, this.ifsfManager.clientSocket.workstationID, nread));
                            nreadtot += nread;
                            if (nread == 0)
                                Thread.Sleep(500);
                        }
                        while (nreadtot < headerLength);
                        int msglength = getMsgLength(header);
                        // There're some cases that msglenght was huge > 120mb
                        if (msglength > 40000)
                            throw new System.OutOfMemoryException("Wayne's exception: Out of memory");

                        // read message
                        byte[] buffer;
                        buffer = new byte[msglength];
                        Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("TCPListenerThreadProc: buffer msg length={0}", buffer.GetLength(0)));
                        nreadtot = 0;
                        do
                        {
                            Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TCPListenerThreadProc: reading ..."));
                            nread = networkStream.Read(buffer, nreadtot, msglength - nreadtot);
                            Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TCPListenerThreadProc Id={0}, WId={1}: read '{2}' bytes", this.ifsfManager.clientSocket.Id, this.ifsfManager.clientSocket.workstationID, nread));
                            nreadtot += nread;
                            if (nread == 0)
                                Thread.Sleep(500);
                        }
                        while (!bTerminate && (nreadtot < msglength));

                        sb.Remove(0, sb.Length);
                        sb.Append(Encoding.UTF8.GetString(buffer, 0, nreadtot));
                        Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("TCPListenerThreadProc Id={0}, WId={1}: read '{2}' bytes: {3}", this.ifsfManager.clientSocket.Id, this.ifsfManager.clientSocket.workstationID, msglength, Encoding.ASCII.GetString(buffer, 0, msglength)));

                        sbuffer += sb.ToString();

                        bool bEnd = false;
                        string sEndmsg = "", smsg = "";
                        int indexEndMsgSR = -1, indexEndFDCMsg = -1, indexEnd = -1;
                        indexEnd = sbuffer.IndexOf("/>");
                        //Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("indexend={0}, buffer={1}", indexEnd, sbuffer));

                        do
                        {
                            indexEndMsgSR = sbuffer.IndexOf("</ServiceResponse>");
                            indexEndFDCMsg = sbuffer.IndexOf("</FDCMessage>");
                            if (indexEndMsgSR >= 0 && indexEndFDCMsg >= 0)
                            {
                                indexEnd = System.Math.Min(indexEndMsgSR, indexEndFDCMsg);
                                if (indexEndMsgSR < indexEndFDCMsg)
                                {
                                    sEndmsg = "</ServiceResponse>";
                                    indexEndFDCMsg = -1;
                                }
                                else
                                {
                                    sEndmsg = "</FDCMessage>";
                                    indexEndMsgSR = -1;
                                }
                            }
                            else if (indexEndMsgSR >= 0 && indexEndFDCMsg < 0)
                            {
                                indexEnd = indexEndMsgSR;
                                sEndmsg = "</ServiceResponse>";
                            }
                            else if (indexEndFDCMsg > 0)
                            {
                                indexEnd = indexEndFDCMsg;
                                sEndmsg = "</FDCMessage>";
                            }
                            else
                            {
                                indexEnd = sbuffer.IndexOf("/>");
                                sEndmsg = "/>";
                            }
                            if (indexEnd >= 0)
                            {
                                smsg = sbuffer.Substring(0, indexEnd + sEndmsg.Length);
                                sbuffer = sbuffer.Substring(indexEnd + sEndmsg.Length);
                                //Trace.WriteLine(string.Format("smsg={0}, sbuffer={1}", smsg, sbuffer));
                                //string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "FUSION-Connection", "CheckEncryption");
                                if (this.ifsfManager.clientSocket.headerEncryption != 0)
                                {
                                    MD5Crypter crypter = new MD5Crypter();
                                    if (!crypter.verifyMD5Hash(smsg + MD5Crypter.passphrase, System.Text.Encoding.ASCII.GetString(header, Define.HeaderLength, Define.MD5EncriptionLength)))
                                        result = OverallResult.ValidationError;
                                }
                                if (smsg.Length > 0)
                                {
                                    if (indexEndMsgSR >= 0)
                                        ifsfManager.ReadResponse(smsg, msglength, ref result);
                                    else if (indexEndFDCMsg > 0)
                                        ifsfManager.ReadMessage(smsg, msglength, ref result);
                                }
                            }
                            else bEnd = true;
                        } while (!bEnd);
                    }
                }
                catch (SocketException sex)
                {
                    Trace.WriteLine("Exception TCPListenerThreadProc: " + sex.Message);
                    tcpclient = null;
                    if (sex.ErrorCode == 10049)
                        ifsfManager.Disconnect();
                    Thread.Sleep(1000);
                }
                catch (Exception ex)
                {
                    tcpclient = null;
                    ifsfManager.isForcedToDisconnect = true;
                    Trace.WriteLine(string.Format("Exception TCPListenerThreadProc! {0}, Id={1}", ex.Message + " - " + ex.StackTrace, this.ifsfManager.clientSocket.Id));
                    ifsfManager.Disconnect();
                    bTerminate = true; // WJU - get out of the loop since Disconnect was called already. This is a quicker way out.
                }
            }
            if (tcpListener != null)
                tcpListener.Stop();
            bRunning = false;
            Trace.WriteLine(string.Format("TCPListenerThreadProc Id={0}, WId={1}: end", this.ifsfManager.clientSocket.Id, this.ifsfManager.clientSocket.workstationID));
        }

        private bool checkHash(string smsg, int encrStart, byte[] header)
        {
            MD5Crypter crypter = new MD5Crypter();
            byte[] datahash = crypter.ComputeHash(System.Text.Encoding.UTF8.GetBytes(smsg + MD5Crypter.passphrase));
            byte[] inputhash;
            inputhash = new byte[Define.MD5EncriptionLength];
            for (int i = encrStart; i < Define.MD5EncriptionLength + encrStart; i++)
                inputhash[i - encrStart] = header[i];
            bool error = false;
            for (int i = 0; i < Define.MD5EncriptionLength; i++)
                if (inputhash[i] != datahash[i])
                {
                    Trace.WriteLine(string.Format("ValidationError: inputhash={0}, datahash={1}", System.Text.Encoding.UTF8.GetString(inputhash, 0, inputhash.GetLength(0)), System.Text.Encoding.UTF8.GetString(datahash, 0, datahash.GetLength(0))));
                    Trace.WriteLine(string.Format("ValidationError: inputhash[{0}]={1} != datahash[{2}]={3}", i, inputhash[i], i, datahash[i]));
                    error = true;
                    break;
                }
            return error;
        }

        private int getMsgLength(byte[] header)
        {
            int length = 0;
            for (int pos = 1; pos <= Define.HeaderLength; pos++)
            {
                length |= ((int)(header[pos - 1] << (Define.HeaderLength - pos) * 8));
            }
            return length;
        }
    }


    public class IFSFSockets : IIdentifiableEntity, IDisposable//, IConnectable
    {
        private TcpClient _socketReqChannelA = null;
        public TcpClient socketReqChannelA
        {
            get { return _socketReqChannelA; }
        }

        private TcpListener _socketRespChannelB = null;
        public TcpListener socketRespChannelB
        {
            get { return _socketRespChannelB; }
        }

        private TcpListener _socketUnsolicitedChannelC = null;
        public TcpListener socketUnsolicitedChannelC
        {
            get { return _socketUnsolicitedChannelC; }
        }

        private TcpClient _socketReqChannelConfig = null;
        public TcpClient socketReqChannelConfig
        {
            get { return _socketReqChannelConfig; }
        }

        public TCPListenerThread respChannelBThreadObj;
        public Thread respChannelBThread;
        public TCPListenerThread unsolicitedChannelCThreadObj;
        public Thread unsolicitedChannelCThread;
        public TCPListenerThread respChannelConfigThreadObj;
        public Thread respChannelConfigThread;

        IFSFManager ifsfManager = null;

        IFSFMessages _ifsfMessages = null;
        public IFSFMessages ifsfMessages
        {
            get { return _ifsfMessages; }
        }

        private string _applicationSender = "";
        public string applicationSender
        {
            get { return _applicationSender; }
        }
        private string _workstationID = "";
        public string workstationID
        {
            get { return _workstationID; }
        }
        private string _sIPAddress = "";
        public string sIPAddress
        {
            get { return _sIPAddress; }
        }
        private string _sIPAddress2 = "";
        public string sIPAddress2
        {
            get { return _sIPAddress2; }
        }

        private int _iIPPortA = 0;
        public int iIPPortA
        {
            get { return _iIPPortA; }
        }
        private int _iIPPortB = 0;
        public int iIPPortB
        {
            get { return _iIPPortB; }
        }
        private int _iIPPortC = 0;
        public int iIPPortC
        {
            get { return _iIPPortC; }
        }

        private long _heartbeatInterval = 20000;
        public long heartbeatInterval
        {
            get { return _heartbeatInterval; }
        }

        private long _heartbeatTimeout = 20000;
        public long heartbeatTimeout
        {
            get { return _heartbeatTimeout; }
        }

        private long _headerEncryption = 1;
        public long headerEncryption
        {
            get { return _headerEncryption; }
            set { _headerEncryption = value; }
        }

        public bool logOnSendCalled = false;
        private byte[][] _validationInfo = null;
        public byte[][] validationInfo
        {
            get { return _validationInfo; }
            set { _validationInfo = value; }
        }

        private string _posInfo = "";
        public string posInfo
        {
            get { return _posInfo; }
            set { _posInfo = value; }
        }

        private bool disposed;
        private int id;
        private IIdentifiableEntity parentEntity;

        private object _socketLockObject = new object();
        internal object SocketLockObject
        {
            get { return _socketLockObject; }
        }

        private DeviceConnectionState _mainConnectionState = DeviceConnectionState.Disconnected;
        public DeviceConnectionState mainConnectionState
        {
            get { return _mainConnectionState; }
            set
            {
                lock (SocketLockObject)
                {
                    if (_mainConnectionState != value)
                    {
                        _mainConnectionState = value;
                        if (OnConnectionStateChange != null)
                        {
                            OnConnectionStateChange.Invoke(this, new ConnectionChangedEventArgs(mainConnectionState));
                        }
                    }
                }
            }
        }

        public event EventHandler<ConnectionChangedEventArgs> OnConnectionStateChange;
        public event EventHandler OnResponseTimeout;
        public readonly ConfigurationParams configParam;

        public IFSFSockets(int id, IFSFManager _ifsfManager/*, IIdentifiableEntity parentEntity*/)
        {
            this.id = id;
            this.parentEntity = (IIdentifiableEntity)ifsfManager;
            ifsfManager = _ifsfManager;

            configParam = _ifsfManager.ConfigParam;
            this._applicationSender = configParam.applicationSender;
            this._workstationID = configParam.workstationID;
            this._sIPAddress = configParam.sIPAddress;
            this._sIPAddress2 = configParam.sIPAddress2;
            this._iIPPortA = configParam.iIPPortA;
            this._iIPPortB = configParam.iIPPortB;
            this._iIPPortC = configParam.iIPPortC;
            this._heartbeatTimeout = configParam.heartbeatTimeout;
            this._heartbeatInterval = configParam.heartbeatInterval;
            this._headerEncryption = configParam.headerEncryption;

            _ifsfMessages = new IFSFMessages(this);
            _ifsfMessages.OnIFSFSMessageEnqueued += new EventHandler(ifsfmessages_OnMessageEnqueued);
            _ifsfMessages.OnResponseTimeout += new EventHandler(ifsfmessages_OnResponseTimeout);
        }

        private bool getConnectionParams(string connectionString)
        {
            Dictionary<string, string> connectionStringParamDict;
            connectionStringParamDict = Strings.ParseConnectionString(connectionString);
            string key = "";

            key = "IdShift";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                try
                {
                    ((FUSIONForecourtControl)(FUSIONFactory.fusionForecourtControlList[this.Id])).manager.IdShift = Convert.ToInt32(connectionStringParamDict[key]);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading IdShift: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }

            key = "IdPumpShift";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                try
                {
                    ((FUSIONForecourtControl)(FUSIONFactory.fusionForecourtControlList[this.Id])).manager.IdPumpShift = Convert.ToInt32(connectionStringParamDict[key]);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading IdPumpShift: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }

            key = "IdNozzleShift";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                try
                {
                    ((FUSIONForecourtControl)(FUSIONFactory.fusionForecourtControlList[this.Id])).manager.IdNozzleShift = Convert.ToInt32(connectionStringParamDict[key]);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading IdNozzleShift: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }

            key = "IdTankShift";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                try
                {
                    ((FUSIONForecourtControl)(FUSIONFactory.fusionForecourtControlList[this.Id])).manager.IdTankShift = Convert.ToInt32(connectionStringParamDict[key]);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading IdTankShift: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }

            key = "Host";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
                this._sIPAddress = connectionStringParamDict[key];
            key = "Host2";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
                this._sIPAddress2 = connectionStringParamDict[key];
            key = "Port";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                try
                {
                    this._iIPPortA = Convert.ToInt32(connectionStringParamDict[key]);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading IPPortA: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }
            key = "PortB";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                try
                {
                    this._iIPPortB = Convert.ToInt32(connectionStringParamDict[key]);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading IPPortB: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }
            key = "PortC";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                try
                {
                    this._iIPPortC = Convert.ToInt32(connectionStringParamDict[key]);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading IPPortC: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }
            //key = "workstationID";
            //if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            //    this._applicationSender = connectionStringParamDict[key];
            //else
            //{
            //    key = "ClientName";
            //    if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            //        this._applicationSender = connectionStringParamDict[key];
            //}
            //key = "applicationSender";
            //if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            //    this._workstationID = connectionStringParamDict[key];
            //else
            //{
            //    key = "ClientId";
            //    if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            //        this._workstationID = connectionStringParamDict[key];
            //}

            key = "ClientId";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                this._workstationID = connectionStringParamDict[key];
                this._applicationSender = connectionStringParamDict[key];
            }
            else
            {
                key = "applicationSender";
                if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
                {
                    this._workstationID = connectionStringParamDict[key];
                    this._applicationSender = connectionStringParamDict[key];
                }
            }

            key = "heartbeatInterval";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                try
                {
                    this._heartbeatInterval = Convert.ToInt16(connectionStringParamDict[key]);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading heartbeatInterval: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }
            key = "heartbeatTimeout";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                try
                {
                    this._heartbeatTimeout = Convert.ToInt16(connectionStringParamDict[key]);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading _heartbeatTimeout: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }
            key = "headerEncryption";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                try
                {
                    this._headerEncryption = Convert.ToInt16(connectionStringParamDict[key]);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading _headerEncryption: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }
            key = "posInfo";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
                this._posInfo = connectionStringParamDict[key];
            key = "validationInfo";
            if (connectionStringParamDict.ContainsKey(key) && connectionStringParamDict[key] != null && connectionStringParamDict[key] != "")
            {
                string[] validationInfoArray;
                try
                {
                    //validationInfoArray = connectionStringParamDict[key].Split('@');
                    //this._validationInfo = new byte[validationInfoArray.Length][];
                    //int i = 0;
                    //foreach(string s in validationInfoArray)
                    //{


                    string s = connectionStringParamDict[key];
                    string elem;
                    while (s.Length > 0)
                    {
                        if (s.IndexOf("@@@") >= 0)
                        {
                            elem = s.Substring(0, s.IndexOf("@@@"));
                            s = s.Substring(s.IndexOf("@@@") + 3);
                        }
                        else
                        {
                            elem = s;
                            s = "";
                        }
                        //DESCrypter descrypter = new DESCrypter();
                        //byte[] dataencrypted = descrypter.Encrypt(elem);

                        byte[] b = System.Text.Encoding.Unicode.GetBytes(elem);

                        this.ifsfManager.LogOnAddValidationInfo(b);

                        //IFSFManager.ArrayResize<byte[]>(ref _validationInfo, (_validationInfo != null) ? _validationInfo.Length + 1 : 1);
                        //this._validationInfo[_validationInfo.Length-1] = new byte[dataencrypted.Length];
                        //this._validationInfo[_validationInfo.Length-1] = dataencrypted;
                    }
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Exception reading _validationInfo: {0}", ex.Message + " - " + ex.StackTrace));
                }
            }
            return true;
        }


        public void SendConfig(string commandFileName)
        {
            if (this.mainConnectionState == DeviceConnectionState.Connected)
            {
                int iIPPortConfig = Convert.ToInt32(IniFile.IniReadValue(ConfigurationParams.getSINPPath("ini\\") + @"ForecourtServer.ini", "FUSION-Connection", "IPPortConfig"));
                try
                {
                    IPAddress serverIPAddress = null;
                    IPEndPoint endPoint = null;
                    bool bIPAddress = false;

                    if (iIPPortConfig != this._iIPPortA)
                    {
                        int socketTimeout = 3000;
                        bool noDelay = true;
                        try
                        {
                            string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "FUSION-Connection", "SocketTimeout");
                            if (sValue.Length > 0)
                                socketTimeout = Convert.ToInt32(sValue);
                            Trace.WriteLine(string.Format("socketTimeout={0}", socketTimeout));
                            sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "FUSION-Connection", "NoDelay");
                            if (sValue.Length > 0 && sValue == "0")
                                noDelay = false;
                            Trace.WriteLine(string.Format("socketTimeout={0}", socketTimeout));
                        }
                        catch (Exception ex)
                        {
                            Trace.WriteLine("EXCEPTION! " + ex.Message);
                        }

                        _socketReqChannelConfig = new TcpClient();
                        _socketReqChannelConfig.SendTimeout = socketTimeout;
                        _socketReqChannelConfig.NoDelay = noDelay;
                        int retrycount = 0;

                        bool bConnected = false;
                        string ipAddress = this._sIPAddress;
                        string error = "";
                        while (!bConnected)
                        {
                            if (retrycount == 5)
                            {
                                if (this._sIPAddress2 != "") ipAddress = this._sIPAddress2;
                                Trace.WriteLine(error);
                            }
                            else if (retrycount == 10)
                            {
                                retrycount = 0;
                                ipAddress = this._sIPAddress;
                                Trace.WriteLine(error);
                                Thread.Sleep(5000);
                            }
                            retrycount++;

                            try
                            {
                                socketReqChannelConfig.Connect(ipAddress, iIPPortConfig);
                                bConnected = true;
                            }
                            catch (SocketException sex)
                            {
                                Trace.WriteLine(sex.Message + " - " + sex.StackTrace);
                                if (sex.ErrorCode == 10049)
                                    bIPAddress = false;
                                Thread.Sleep(1000);
                            }
                        }
                        respChannelConfigThreadObj = new TCPListenerThread(null, ifsfManager, "ChannelConfig");
                        respChannelConfigThread = new Thread(new ThreadStart(respChannelConfigThreadObj.TCPListenerThreadProc));
                        respChannelConfigThread.Start();
                    }
                    else
                        _socketReqChannelConfig = this._socketReqChannelA;

                    Thread.Sleep(2000);

                    // start reading file with config messages
                    string line, xmlconfigfile = ConfigurationParams.getSINPPath("ini\\") + commandFileName;
                    StringBuilder sb = new StringBuilder(); ;
                    StreamReader sr = new StreamReader(xmlconfigfile);
                    while (sr.Peek() != -1)
                    {
                        line = sr.ReadLine();
                        sb.Append(line);
                    }
                    sr.Close();
                    string allconfig = sb.ToString();
                    //string allconfig = sr.ReadToEnd();
                    string[] messages;
                    string msg2;
                    messages = allconfig.Split('#');
                    foreach (string msg in messages)
                    {
                        msg2 = msg;
                        //msg2 = msg.Replace("\r", "");
                        //msg2 = msg2.Replace("\n", "");
                        //msg2 = msg2.Replace("\t", "");
                        this.SendConfigMessage(msg2);
                    }
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("end: EXCEPTION! Stack chiamate: {0} Messaggio: {1}", ex.StackTrace, ex.Message));
                }
                if (iIPPortConfig != this._iIPPortA)
                {
                    if (_socketReqChannelConfig != null)
                        this._socketReqChannelConfig.Close();
                    this._socketReqChannelConfig = null;
                }
            }
            else
                Trace.WriteLine("SendConfig ERROR: NOT Connected!");
        }

        /// <summary>
        /// will setup the tcp connect and send LogOn request to Fdc server.
        /// </summary>
        /// <param name="connectionString"></param>
        /// <returns></returns>
        public bool Connect(string connectionString)
        {
            Trace.WriteLine(string.Format("start Connect: status='{0}'", this.mainConnectionState));

            lock (ifsfManager.SyncObject)
            {
                if ((this.mainConnectionState == DeviceConnectionState.Disconnected) || (this.mainConnectionState == DeviceConnectionState.Disconnecting))
                {
                    //this.mainConnectionState = DeviceConnectionState.Connecting;

                    try
                    {
                        Trace.WriteLine(string.Format("id={0}, -connectionString:'{1}'", this.id, connectionString));
                        getConnectionParams(connectionString);

                        FDCGlobal.ProtocolVersion = FDCVersion.V0007;// "00.07";// FDCGlobal.VersionFromString(IniFile.IniReadValue(ConfigurationParams.inifile, "FUSION-Connection", "FDCPOSInterfaceVersion"));
                        Trace.WriteLine(string.Format("id={0}, version:'{1}'", this.id, FDCGlobal.ProtocolVersion));
                        this.ifsfManager.heartbeat.heartbeatInterval = this.heartbeatInterval;
                        this.ifsfManager.heartbeat.heartbeatTimeout = this.heartbeatTimeout;
                        int socketTimeout = 3000;
                        bool noDelay = true;
                        try
                        {
                            string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "FUSION-Connection", "SocketTimeout");
                            if (sValue.Length > 0)
                                socketTimeout = Convert.ToInt32(sValue);
                            Trace.WriteLine(string.Format("socketTimeout={0}", socketTimeout));
                            sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "FUSION-Connection", "NoDelay");
                            if (sValue.Length > 0 && sValue == "0")
                                noDelay = false;
                            Trace.WriteLine(string.Format("socketTimeout={0}", socketTimeout));
                        }
                        catch (Exception ex)
                        {
                            Trace.WriteLine("EXCEPTION! " + ex.Message);
                        }

                        IPAddress serverIPAddress = null;
                        IPEndPoint endPoint = null;

                        _socketReqChannelA = new TcpClient();
                        _socketReqChannelA.SendTimeout = socketTimeout;
                        _socketReqChannelA.NoDelay = noDelay;
                        int retrycount = 0;

                        bool bConnected = false;
                        string ipAddress = this._sIPAddress;
                        string error = "";
                        while (!bConnected)
                        {
                            if (retrycount == 5)
                            {
                                if (this._sIPAddress2 != "") ipAddress = this._sIPAddress2;
                                Trace.WriteLine(error);
                            }
                            else if (retrycount == 10)
                            {
                                retrycount = 0;
                                ipAddress = this._sIPAddress;
                                Trace.WriteLine(error);
                                Thread.Sleep(5000);
                            }
                            retrycount++;

                            try
                            {
                                Trace.WriteLine(string.Format("connecting to ip={0}, port={1}", ipAddress, this.iIPPortA));
                                this.socketReqChannelA.Connect(ipAddress, this.iIPPortA);
                                bConnected = true;
                            }
                            catch (SocketException sex)
                            {
                                error = sex.Message + " - " + sex.StackTrace;
                                Console.WriteLine("IFSFSocket to " + ipAddress + ", " + this.iIPPortA + " exceptioned: " + sex);
                                Thread.Sleep(3000);
                            }
                        }

                        if (iIPPortB != iIPPortA /*&& _socketRespChannelB == null*/)
                            _socketRespChannelB = new TcpListener(iIPPortB);
                        else
                            _socketRespChannelB = null;
                        if (iIPPortC != iIPPortA /*&& _socketUnsolicitedChannelC == null*/)
                            _socketUnsolicitedChannelC = new TcpListener(iIPPortC);
                        else
                            _socketUnsolicitedChannelC = null;


                        Trace.WriteLine(string.Format("Channel A Connected: Id={0}, WId={1}, AId={2}", this.id, this.workstationID, this.applicationSender));

                        ifsfManager.authentificationErrorRetry = true;
                        if (this.validationInfo != null)
                            ifsfManager.LogOn(validationInfo, posInfo, "");
                        else
                            ifsfManager.LogOnSend(posInfo);
                        ifsfManager.heartbeat.ResetDisconnectionTimeout();

                        if (iIPPortB != iIPPortA /*&& respChannelBThreadObj == null*/)
                        {
                            respChannelBThreadObj = new TCPListenerThread(socketRespChannelB, ifsfManager, "ChannelB");
                            respChannelBThread = new Thread(new ThreadStart(respChannelBThreadObj.TCPListenerThreadProc));
                            respChannelBThread.Start();
                        }
                        else /*if (respChannelBThreadObj == null)*/
                        {
                            respChannelBThreadObj = new TCPListenerThread(null, ifsfManager, "ChannelA");
                            respChannelBThread = new Thread(new ThreadStart(respChannelBThreadObj.TCPListenerThreadProc));
                            respChannelBThread.Start();
                        }
                        if (iIPPortC != iIPPortA /*&& unsolicitedChannelCThreadObj == null*/)
                        {
                            unsolicitedChannelCThreadObj = new TCPListenerThread(socketUnsolicitedChannelC, ifsfManager, "ChannelC");
                            unsolicitedChannelCThread = new Thread(new ThreadStart(unsolicitedChannelCThreadObj.TCPListenerThreadProc));
                            unsolicitedChannelCThread.Start();
                        }
                    }
                    catch (Exception ex)
                    {
                        Trace.WriteLine(string.Format("end: EXCEPTION! Stack chiamate: {0} Messaggio: {1}", ex.StackTrace, ex.Message));
                        return false;
                    }

                }

            }

            //if ((this.mainConnectionState != DeviceConnectionState.Disconnected) && (this.mainConnectionState != DeviceConnectionState.Disconnecting))
            //{
            //    throw new SocketException(SocketExceptionType.ClientNotDisconnected);
            //}
            //TransportFrameClientSocket.ValidateConnectionString(connectionString);
            //if (this.debugLogger.IsActive(LogCategory.UserRequest, DebugLogLevel.Normal))
            //{
            //    this.debugLogger.Add(string.Format("Connect({0})", connectionString), LogCategory.UserRequest, DebugLogLevel.Normal);
            //}
            //this.userWantConnection = true;
            //this.stateMachine.IncomingEvent(new ConnectionStringStateEngineEvent(connectionString, EventType.ConnectRequested));

            Trace.WriteLine("end: ok");
            return true;
        }

        public void Disconnect()
        {
            //if ((this.mainConnectionState == DeviceConnectionState.Connected) || (this.mainConnectionState == DeviceConnectionState.Connecting))
            {
                Trace.WriteLine("terminating respThreadObjs");
                if (respChannelBThreadObj != null)
                    respChannelBThreadObj.bTerminate = true;
                Trace.WriteLine("terminating respChannelCThreadObj");
                if (unsolicitedChannelCThreadObj != null)
                    unsolicitedChannelCThreadObj.bTerminate = true;

                if (respChannelConfigThreadObj != null)
                    respChannelConfigThreadObj.bTerminate = true;

                if (_socketReqChannelA != null)
                    this._socketReqChannelA.Close();
                this._socketReqChannelA = null;
                if (_socketReqChannelConfig != null)
                    this._socketReqChannelConfig.Close();
                this._socketReqChannelConfig = null;

                if (this._socketRespChannelB != null)
                    this._socketRespChannelB.Stop();
                _socketRespChannelB = null;
                if (this._socketUnsolicitedChannelC != null)
                    this._socketUnsolicitedChannelC.Stop();
                _socketUnsolicitedChannelC = null;

                //if (this.debugLogger.IsActive(LogCategory.UserRequest, DebugLogLevel.Normal))
                //{
                //    this.debugLogger.Add(string.Format("Disconnect()", new object[0]), LogCategory.UserRequest, DebugLogLevel.Normal);
                //}
                //this.userWantConnection = false;
                //this.stateMachine.IncomingEvent(new StateEngineEvent(EventType.DisconnectRequested));
            }
        }

        public virtual void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                this.disposed = true;
                if (disposing)
                {
                    //this.transportFrameClientSocket.Dispose();
                    //this.stateMachine.Dispose();
                    //this.debugLogger.Dispose();
                }
            }
        }

        // Properties
        //[CLSCompliant(false)]
        //public ushort ClientId
        //{
        //    get
        //    {
        //        return this.transportFrameClientSocket.ClientId;
        //    }
        //}

        //public string ClientName
        //{
        //    get
        //    {
        //        return this.transportFrameClientSocket.Name;
        //    }
        //}

        public DeviceConnectionState ConnectionState
        {
            get
            {
                return this.mainConnectionState;
            }
        }

        public string EntitySubType
        {
            get
            {
                return "RPC";
            }
        }

        public string EntityType
        {
            get
            {
                return "ClientSocket";
            }
        }

        /// <summary>
        /// This is used by the logger and should never be set by implementing classes
        /// </summary>
        public string FullEntityName { get; set; }

        public int Id
        {
            get
            {
                return this.id;
            }
        }

        public IIdentifiableEntity ParentEntity
        {
            get
            {
                return this.parentEntity;
            }
        }


        public void Serialize<T>(T sr)
        {
            if (sr != null && socketReqChannelA != null)
            {
                XmlSerializer serializer = null;
                var netstream = socketReqChannelA.GetStream();
                using (var memstream = new MemoryStream())
                {
                    serializer = new XmlSerializer(typeof(T));
                    serializer.Serialize(memstream, (T)sr);

                    // writes header and encription string
                    using (var memstream2 = new MemoryStream())
                    {
                        byte[] bytes = new byte[Define.HeaderLength];
                        using (var writer = new BinaryWriter(memstream2))
                        {
                            bytes[3] = (byte)(memstream.Length & 0x000000FF);
                            bytes[2] = (byte)((memstream.Length & 0x0000FF00) / Math.Pow(2, 8));
                            bytes[1] = (byte)((memstream.Length & 0x00FF0000) / Math.Pow(2, 16));
                            bytes[0] = (byte)((memstream.Length & 0xFF000000) / Math.Pow(2, 24));
                            writer.Write(bytes);
                            bytes = new byte[Define.EncriptionTypeLength];
                            //string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "FUSION-Connection", "CheckEncryption");
                            if (this.ifsfManager.clientSocket.headerEncryption != 0)
                            {
                                MD5Crypter crypter = new MD5Crypter();
                                byte[] hashingbytes = new byte[memstream.Length + crypter.getPassphrase().GetLength(0)];
                                Array.Copy(memstream.GetBuffer(), hashingbytes, (int)memstream.Length);
                                Array.Copy(crypter.getPassphrase(), 0, hashingbytes, (int)memstream.Length,
                                           (int)crypter.getPassphrase().Length);
                                bytes = crypter.ComputeHash(hashingbytes);
                            }
                            else
                            {
                                for (int i = 0; i < Define.EncriptionTypeLength; i++)
                                    bytes[i] = 0;
                            }
                            writer.Write(bytes);
                            memstream2.WriteTo(netstream);
                        }
                    }
                    memstream.WriteTo(netstream);
                }
                TraceXML(serializer, (T)sr);
            }
        }

        public void SendConfigMessage(string configmessage)
        {
            NetworkStream netstream = socketReqChannelConfig.GetStream();

            // writes header and encription string
            using (MemoryStream memstream = new MemoryStream())
            {
                byte[] bytes = new byte[Define.HeaderLength];
                using (BinaryWriter writer = new BinaryWriter(memstream))
                {

                    bytes[3] = (byte)(configmessage.Length & 0x000000FF);
                    bytes[2] = (byte)((configmessage.Length & 0x0000FF00) / Math.Pow(2, 8));
                    bytes[1] = (byte)((configmessage.Length & 0x00FF0000) / Math.Pow(2, 16));
                    bytes[0] = (byte)((configmessage.Length & 0xFF000000) / Math.Pow(2, 24));
                    writer.Write(bytes);
                    if (FDCGlobal.ProtocolVersion >= FDCVersion.V0100)
                    {
                        bytes = new byte[Define.EncriptionTypeLength];
                        if (this.ifsfManager.clientSocket.headerEncryption != 0)
                            bytes[1] = (byte)(1);
                        else
                            bytes[1] = (byte)(0);
                        bytes[0] = (byte)(0);
                        writer.Write(bytes);
                    }
                    // writes encryption
                    if (FDCGlobal.ProtocolVersion <= FDCVersion.V0007 ||
                        (FDCGlobal.ProtocolVersion >= FDCVersion.V0100 && this.ifsfManager.clientSocket.headerEncryption != 0))
                    {
                        bytes = new byte[Define.MD5EncriptionLength];
                        //string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "FUSION-Connection", "CheckEncryption");
                        if (this.ifsfManager.clientSocket.headerEncryption != 0)
                        {
                            var crypter = new MD5Crypter();
                            byte[] hashingbytes = new byte[memstream.Length + crypter.getPassphrase().GetLength(0)];
                            Array.Copy(memstream.GetBuffer(), hashingbytes, (int)memstream.Length);
                            Array.Copy(crypter.getPassphrase(), 0, hashingbytes, (int)memstream.Length, (int)crypter.getPassphrase().Length);
                            bytes = crypter.ComputeHash(hashingbytes);
                        }
                        else
                        {
                            for (int i = 0; i < Define.MD5EncriptionLength; i++)
                                bytes[i] = 0;
                        }
                        writer.Write(bytes);
                    }


                    byte[] bytedata;
                    System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                    bytedata = encoding.GetBytes(configmessage);
                    writer.Write(bytedata);

                    memstream.WriteTo(netstream);
                    TraceXML(memstream, configmessage);
                }
            }
        }

        private void ifsfmessages_OnResponseTimeout(object sender, EventArgs e)
        {
            if (OnResponseTimeout != null)
                OnResponseTimeout.Invoke(this, e);
        }

        private void ifsfmessages_OnMessageEnqueued(object sender, EventArgs e)
        {
            Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("ifsfmessages_OnMessageEnqueued init"));
            string requestType = "";
            int requestId = 0;
            try
            {
                while (ifsfMessages.serviceRequestChannelA.Count > 0)
                {
                    BasePOSRequest sr = ifsfMessages.serviceRequestChannelA.Dequeue();
                    Trace.WriteLine(string.Format("sr.GetType:{0}", sr.GetType().FullName));
                    if (sr.GetType() == typeof(POSMessagePOSReady))
                    {
                        requestType = ((FDCMessage)sr).MessageType;
                        requestId = Convert.ToInt32(((FDCMessage)sr).MessageID);
                    }
                    else
                    {
                        requestType = ((ServiceRequest)sr).RequestType;
                        requestId = Convert.ToInt32(((ServiceRequest)sr).RequestID);
                    }

                    switch (requestType)
                    {
                        case "POSHeartBeat":
                            Serialize((ServiceRequestHeartbeat)sr);
                            break;
                        case "LogOn":
                            if (FDCGlobal.ProtocolVersion <= FDCVersion.V0007)
                                Serialize((ServiceRequestLogOnV07)sr);
                            else
                                Serialize((ServiceRequestLogOn)sr);
                            break;
                        case "LogOff":
                            Serialize((ServiceRequestLogOff)sr);
                            break;
                        case "VersionInfo":
                            Serialize((ServiceRequestVersionInfo)sr);
                            break;
                        case "StartForecourt":
                            Serialize((ServiceRequestStartForecourt)sr);
                            break;
                        case "StopForecourt":
                            Serialize((ServiceRequestStopForecourt)sr);
                            break;
                        case "GetCurrentFuellingStatus":
                            Serialize((ServiceRequestGetCurrentFuellingStatus)sr);
                            break;
                        case "GetFuelPointTotals":
                            Serialize((ServiceRequestGetFuelPointTotals)sr);
                            break;
                        case "GetDeviceState":
                            Serialize((ServiceRequestGetDeviceState)sr);
                            break;
                        case "TerminateFuelling":
                            Serialize((ServiceRequestTerminateFuelling)sr);
                            break;
                        case "AuthoriseFuelPoint":
                            Serialize((ServiceRequestAuthoriseFuelPoint)sr);
                            break;
                        case "ChangeFuelMode":
                            Serialize((ServiceRequestChangeFuelMode)sr);
                            break;
                        case "ChangeFuelPrice":
                            Serialize((ServiceRequestChangeFuelPrice)sr);
                            break;
                        case "LockFuelSaleTrx":
                            Serialize((ServiceRequestLockFuelSaleTrx)sr);
                            break;
                        case "UnlockFuelSaleTrx":
                            Serialize((ServiceRequestUnlockFuelSaleTrx)sr);
                            break;
                        case "ClearFuelSaleTrx":
                            Serialize((ServiceRequestClearFuelSaleTrx)sr);
                            break;
                        case "GetAvailableFuelSaleTrxs":
                            Serialize((ServiceRequestGetAvailableFuelSaleTrxs)sr);
                            break;
                        case "GetFuelSaleTrxDetails":
                            Serialize((ServiceRequestGetFuelSaleTrxDetails)sr);
                            break;
                        case "GetProductTable":
                            Serialize((ServiceRequestGetProductTable)sr);
                            break;
                        case "GetModeTable":
                            Serialize((ServiceRequestGetModeTable)sr);
                            break;
                        case "GetFuelMode":
                            Serialize((ServiceRequestGetFuelMode)sr);
                            break;
                        case "GetConfiguration":
                            Serialize((ServiceRequestGetConfiguration)sr);
                            break;
                        case "GetDSPConfiguration":
                            Serialize((ServiceRequestGetDSPConfiguration)sr);
                            break;
                        case "GetTLGConfiguration":
                            Serialize((ServiceRequestGetTLGConfiguration)sr);
                            break;
                        case "GetPPConfiguration":
                            Serialize((ServiceRequestGetPPConfiguration)sr);
                            break;
                        case "SetConfiguration":
                            Serialize((ServiceRequestSetConfiguration)sr);
                            break;
                        case "LockNozzle":
                            Serialize((ServiceRequestLockNozzle)sr);
                            break;
                        case "UnlockNozzle":
                            Serialize((ServiceRequestUnlockNozzle)sr);
                            break;
                        case "OpenDevice":
                            Serialize((ServiceRequestOpenDevice)sr);
                            break;
                        case "CloseDevice":
                            Serialize((ServiceRequestCloseDevice)sr);
                            break;
                        case "GetCountrySettings":
                            Serialize((ServiceRequestGetCountrySettings)sr);
                            break;
                        case "GetDSPLimits":
                            Serialize((ServiceRequestGetDSPLimits)sr);
                            break;
                        case "ChangeDSPLimits":
                            Serialize((ServiceRequestChangeDSPLimits)sr);
                            break;
                        case "SuspendFuelling":
                            Serialize((ServiceRequestSuspendFuelling)sr);
                            break;
                        case "ResumeFuelling":
                            Serialize((ServiceRequestResumeFuelling)sr);
                            break;
                        case "LockTank":
                            Serialize((ServiceRequestLockTank)sr);
                            break;
                        case "UnlockTank":
                            Serialize((ServiceRequestUnlockTank)sr);
                            break;
                        case "GetTankData":
                            Serialize((ServiceRequestGetTankData)sr);
                            break;
                        case "ReserveFuelPoint":
                            Serialize((ServiceRequestReserveFuelPoint)sr);
                            break;
                        case "FreeFuelPoint":
                            Serialize((ServiceRequestFreeFuelPoint)sr);
                            break;
                        case "StartFuelPointTest":
                            Serialize((ServiceRequestStartFuelPointTest)sr);
                            break;
                        case "EndFuelPointTest":
                            Serialize((ServiceRequestEndFuelPointTest)sr);
                            break;
                        case "OpenFuelPoint":
                            Serialize((ServiceRequestOpenFuelPoint)sr);
                            break;
                        case "CloseFuelPoint":
                            Serialize((ServiceRequestCloseFuelPoint)sr);
                            break;
                        case "SetDeviceAlarm":
                            Serialize((ServiceRequestSetDeviceAlarm)sr);
                            break;
                        case "OPTAdd":
                            Serialize((ServiceRequestOPTAdd)sr);
                            break;
                        case "OPTRemove":
                            Serialize((ServiceRequestOPTRemove)sr);
                            break;
                        case "OPTWrite":
                            if (FDCGlobal.ProtocolVersion <= FDCVersion.V0007)
                                Serialize((ServiceRequestOPTWriteV07)sr);
                            else
                                Serialize((ServiceRequestOPTWrite)sr);
                            break;
                        case "ConfigStart":
                            Serialize((ServiceRequestConfigStart)sr);
                            break;
                        case "ConfigEnd":
                            Serialize((ServiceRequestConfigEnd)sr);
                            break;
                        case "DefGrade":
                        case "DefGrades":
                            Serialize((ServiceRequestDefGrades)sr);
                            break;
                        case "AssignGradePars":
                            Serialize((ServiceRequestAssignGradePars)sr);
                            break;
                        case "DefTanks":
                            Serialize((ServiceRequestDefTanks)sr);
                            break;
                        case "DefFuelMode":
                            Serialize((ServiceRequestDefFuelMode)sr);
                            break;
                        case "DefFuellingMode":
                            Serialize((ServiceRequestDefFuellingMode)sr);
                            break;
                        case "DefFuelPoint":
                            Serialize((ServiceRequestDefFuelPoint)sr);
                            break;
                        case "AssignGrades":
                            Serialize((ServiceRequestAssignGrades)sr);
                            break;
                        case "AssignMeters":
                            Serialize((ServiceRequestAssignMeters)sr);
                            break;
                        case "AssignTanks":
                            Serialize((ServiceRequestAssignTanks)sr);
                            break;
                        case "DefPricePole":
                            Serialize((ServiceRequestDefPricePole)sr);
                            break;
                        case "LoadPriceset":
                            Serialize((ServiceRequestLoadPriceset)sr);
                            break;
                        case "GetTPState":
                            Serialize((ServiceRequestGetTPState)sr);
                            break;
                        default:
                            throw new ArgumentOutOfRangeException("probably a merge issue...");
                    }
                }
            }
            catch (SocketException sex)
            {
                Trace.WriteLine("ifsfmessages_OnMessageEnqueued RequestType:" + requestType + " RequestId:" + requestId + " Exception! " + sex.Message + " - " + sex.StackTrace);
                if (mainConnectionState != DeviceConnectionState.Disconnected)
                {
                    this.ifsfManager.Disconnect();
                    mainConnectionState = DeviceConnectionState.Disconnected;
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine("ifsfmessages_OnMessageEnqueued RequestType:" + requestType + " RequestId:" + requestId + " Exception! " + ex.Message + " - " + ex.StackTrace);
                if (mainConnectionState != DeviceConnectionState.Disconnected)
                {
                    this.ifsfManager.Disconnect();
                    mainConnectionState = DeviceConnectionState.Disconnected;
                }
            }

            Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("ifsfmessages_OnMessageEnqueued end RequestType:{0}", requestType));
        }

        private void TraceXML<T>(XmlSerializer serializer, T sr)
        {
            try
            {
                if (configParam.TraceXML)
                {
                    DateTime now = DateTime.Now;
                    using (var testwriter = new StreamWriter(string.Format("{0}{1:00}-{2:00}-xmlClientMsg.xml", ConfigurationParams.tracePath, now.Day, now.Month), true))
                    {
                        serializer.Serialize(testwriter, (T)sr);
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine("Exception! " + ex.Message + " - " + ex.StackTrace);
            }
        }

        private void TraceXML(MemoryStream ms, string msg)
        {
            try
            {
                if (configParam.TraceXML)
                {
                    DateTime now = DateTime.Now;
                    using (var testwriter = new StreamWriter(string.Format("{0}{1:00}-{2:00}-xmlClientMsg.xml", ConfigurationParams.tracePath, now.Day, now.Month), true))
                    {
                        testwriter.Write(msg);
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine("Exception! " + ex.Message + " - " + ex.StackTrace);
            }
        }

    }
}