Newer
Older
Import / projects / Gameloft / bne_lib / tools / AutobotServer / ServerCaller.cs
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Collections;
using System.ComponentModel;

namespace AutobotServer
{
    /// <summary>
    /// Delegate used by the events StdOutReceived and
    /// StdErrReceived...
    /// </summary>
    public delegate void TcpDataReceivedHandler(object sender, TcpDataReceivedEventArgs e);
    public delegate void HasDataHandler(object sender, TcpDataReceivedEventArgs e);

    /// <summary>
    /// Event Args for above delegate
    /// </summary>
    public class TcpDataReceivedEventArgs : EventArgs
    {
        /// <summary>
        /// The text that was received
        /// </summary>
        public string Text;
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="text">The text that was received for this event to be triggered.</param>
        public TcpDataReceivedEventArgs(string text)
        {
            Text = text;
        }
    }

    /// <summary>
    /// This class Will Launch a tcp server Instance on an Accepted socket 
    /// Output from reading the TCP socket is returnd to GUI app for display 
    /// in textboxes, etc.
    /// </summary>
    public class ServerCaller : AsyncOperation
    {
        private System.Net.Sockets.Socket m_TcpSocket;
        private System.Net.Sockets.NetworkStream NetworkStreamForClient;
        private int m_iReadAmount;
        private int m_iAmountRead;
        private int m_iStartRead;
        private byte[] m_ReadBytes;

        /// Fired for the appriproate TCP events
        public event TcpDataReceivedHandler TcpOutReceived;
        public event TcpDataReceivedHandler TcpErrorReceived;
        public event HasDataHandler HasDataEventCB;

        /// Amount of time to sleep on threads while waiting for the process to finish.
        public int SleepTime = 500;

        /// The Parent Owner of this Process
        public Object m_pParent;

        MethodInvoker m_TCPReader;
        IAsyncResult m_TCPReaderTag;

        public ServerCaller(ISynchronizeInvoke isi, System.Net.Sockets.Socket a_TcpSocket)
            : base(isi)
        {
            m_TcpSocket = a_TcpSocket;
            m_iReadAmount = 0;
            m_iAmountRead = 0;
            m_iStartRead = 0;
            m_ReadBytes = null;
        }

        public bool ReadAmount(int a_iReadamount)
        {
            if (null != NetworkStreamForClient && null != m_TcpSocket && m_TcpSocket.Connected && !CancelRequested && Interlocked.Equals(m_iStartRead, 0))
            {
                m_iReadAmount = a_iReadamount;
                m_iAmountRead = 0;
                m_ReadBytes = new byte[a_iReadamount];
                Interlocked.Exchange(ref m_iStartRead, 1);
                return true;
            }
            return false;
        }

        public void SendData(String a_sData)
        {
            if (null != NetworkStreamForClient)
            {
                try
                {
                    Byte[] sendBytes = Encoding.ASCII.GetBytes(a_sData);
                    NetworkStreamForClient.WriteAsync(sendBytes, 0, sendBytes.Length);
                    NetworkStreamForClient.FlushAsync();

                    //NetworkStreamForClient.Write(sendBytes, 0, sendBytes.Length);
                    //NetworkStreamForClient.Flush();
                }
                catch (Exception e)
                {
                    if (!CancelRequested)
                    {
                        FireAsync(TcpErrorReceived, this, new TcpDataReceivedEventArgs(e.ToString()));
                    }
                }
            }
        }


        private bool HasData()
        {
            if (null != NetworkStreamForClient && null != m_TcpSocket && m_TcpSocket.Connected)
            {
                return NetworkStreamForClient.DataAvailable;
            }
            return false;
        }

        protected override void DoWork()
        {
            NetworkStreamForClient = new System.Net.Sockets.NetworkStream(m_TcpSocket);
            m_TCPReader = new MethodInvoker(ReadTcpOut);
            m_TCPReaderTag = m_TCPReader.BeginInvoke(null, null);

            // Wait for the process to end, or cancel it
            while (!CancelRequested)
            {
                Thread.Sleep(SleepTime); // sleep
                if (!m_TcpSocket.Connected)
                {
                    Cancel();
                }
                else if (HasData())
                {
                    FireAsync(HasDataEventCB, this, new TcpDataReceivedEventArgs(""));
                }
            }

            try
            {
                if (m_TcpSocket.Connected)
                {
                    m_TcpSocket.Close();
                }
            }
            finally
            {
                BlockFlushConsole();
                AcknowledgeCancel();
            }
        }

        protected virtual void ReadTcpOut()
        {
            while (!CancelRequested)
            {
                bool bSleep = true;
                try
                {
                    if (null != NetworkStreamForClient && Interlocked.Equals(m_iStartRead, 1) && m_TcpSocket.Connected && NetworkStreamForClient.DataAvailable)
                    {
                        int iAmountReceived = NetworkStreamForClient.Read(m_ReadBytes, m_iAmountRead, m_iReadAmount - m_iAmountRead);
                        if (iAmountReceived > 0)
                        {
                            bSleep = false;
                            m_iAmountRead += iAmountReceived;
                            if (m_iAmountRead == m_iReadAmount && !CancelRequested)
                            {
                                string dataFromClient = System.Text.Encoding.ASCII.GetString(m_ReadBytes, 0, iAmountReceived);
                                Interlocked.Exchange(ref m_iStartRead, 0);
                                FireAsync(TcpOutReceived, this, new TcpDataReceivedEventArgs(dataFromClient));
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    if (!CancelRequested)
                    {
                        FireAsync(TcpErrorReceived, this, new TcpDataReceivedEventArgs(e.ToString()));
                    }
                }

                if (bSleep && !CancelRequested)
                {
                    System.Threading.Thread.Sleep(500);
                }
            }
        }

        protected override void BlockFlushConsole()
        {
            if (null != m_TCPReader)
            {
                m_TCPReader.EndInvoke(m_TCPReaderTag);
            }
        }

    }
}