private void ProcessreceivedMsg(Message msg)
 {
     if (msg.CommandCode == DiameterMessageCode.DEVICE_WATCHDOG)
     {
         Message DWA    = new Answer(stackContext).CreateDWA(msg);
         byte[]  toSend = DWA.GetBytes();
         //networkStream.Write(toSend, 0, toSend.Length);
         tcpClient.Client.Send(toSend);
     }
     else
     {
         //Return message response
         if (msg.CommandCode == DiameterMessageCode.CAPABILITY_EXCHANGE)
         {
             if (ResponseWaiter.ContainsRequest("CEX"))
             {
                 msg.SessionID = "CEX";
                 if (!ResponseWaiter.AddResponse(msg))
                 {
                     Common.StackLog.Write2ErrorLog("ProcessreceivedMsg", "Unable to Add Response for CEA Session:" + msg.SessionID);
                 }
             }
             else
             {
                 Common.StackLog.Write2ErrorLog("ProcessreceivedMsg", "Unexpected CEA Received \r\n" + msg.ToString());
             }
         }
         else if (msg.CommandCode == DiameterMessageCode.CREDIT_CONTROL)
         {
             if (ResponseWaiter.ContainsRequest(msg.SessionID))
             {
                 if (!ResponseWaiter.AddResponse(msg))
                 {
                     Common.StackLog.Write2ErrorLog("ProcessreceivedMsg", "Unable to Add Response for CCA Session:" + msg.SessionID);
                 }
             }
             else
             {
                 Common.StackLog.Write2ErrorLog("ProcessreceivedMsg", "Unexpected CCA Received for Session " + msg.SessionID + "\r\n" + msg.ToString());
             }
         }
         else
         {
             Common.StackLog.Write2ErrorLog("ProcessreceivedMsg", "Unexpected Messages Received:" + msg.ToString() + msg.ToString());
         }
     }
 }
        /// <summary>
        /// Send Message to the Diameter Peer
        /// </summary>
        /// <param name="MessageBytes"></param>
        /// <param name="TransportType"></param>
        /// <param name="remotePeer"></param>
        public Message SendMessage(Message diameterRequest, Peer destPeer)
        {
            try
            {
                byte[] mgsBytesToSend = diameterRequest.GetBytes();

                //Connect if not connected
                if (stackContext.peers[0].PeerConnection == null || !stackContext.peers[0].PeerConnection.Connected)
                {
                    if (diameterRequest.CommandCode != DiameterMessageCode.CAPABILITY_EXCHANGE)
                    {
                        Common.StackLog.Write2ErrorLog("Transport::SendMessage", "Connection Broken, calling Connect()");
                    }

                    //Connect Diameter Socket
                    Connect();
                }


                Thread pWaiterThread;

                //Just Copy to localThreadWaiter Variable.
                pWaiterThread = Thread.CurrentThread;

                //CCRWaiter vRespWaiter = null;
                //if Message is a CCR message, we need to wait for a response, so add Session to CCRSession
                if (diameterRequest.CommandCode == DiameterMessageCode.CREDIT_CONTROL)
                {
                    ResponseWaiter.AddRequest(diameterRequest.SessionID, pWaiterThread);
                }
                //CER Never Contains a Session ID
                else if (diameterRequest.CommandCode == DiameterMessageCode.CAPABILITY_EXCHANGE)
                {
                    ResponseWaiter.AddRequest("CEX", pWaiterThread);
                    diameterRequest.SessionID = "CEX";
                }
                else
                {
                    StackLog.Write2TraceLog("Transport.SendMessage() ", "UnHandled Message Type:" + diameterRequest.CommandCode);
                    return(null);
                }
                //Record Time
                TimeSpan STime = new TimeSpan(DateTime.Now.Ticks);
                ///////////////////////////////Send Message to the Remote Peer ////////////////////////////////

                //StackLog.Write2TraceLog("\r\nSendMessage", diameterRequest.ToString());
                msgLogger.Write2MessageLog(diameterRequest.ToString());

                Common.StackLog.Write2TraceLog("Transport::SendMessage() ", " Sending Message " + DiameterMessageCode.GetMessageName(diameterRequest.CommandCode, true) + " (" + diameterRequest.SessionID + ") ..");

                destPeer.PeerConnection.GetStream().Write(mgsBytesToSend, 0, mgsBytesToSend.Length);

                //Wait for Response;
                Common.StackLog.Write2TraceLog("Transport::SendMessage() ", " Message Sent, Waiting For Diameter Message Response of Session: " + diameterRequest.SessionID);
                bool isInterrupted = false;
                try
                {
                    //Sleep for 3 Seconds Maximum until interrupted.
                    for (int i = 0; i <= stackContext.CCATimeout * 10; i++)
                    {
                        Thread.Sleep(100);
                    }
                }
                catch (ThreadInterruptedException ex)
                {
                    isInterrupted = true;
                    //StackLog.Write2ErrorLog("SendMessage", "Thread Intrupted for for Response for the Session: " + diameterRequest.SessionID);
                }

                if (isInterrupted)
                {
                    Common.StackLog.Write2TraceLog("Transport.SendMessage() ", " Waiter Thread Response Interrupted for Session: " + diameterRequest.SessionID);
                }
                else
                {
                    Common.StackLog.Write2TraceLog("Transport.SendMessage() ", " Waiter Thread Response Timedout for Session: " + diameterRequest.SessionID);
                }

                //After Thread intrruption get the response here.
                //CEX Dont have any session ID so validate here.
                Message diameterResponse;
                if (ResponseWaiter.ContainsResponse(diameterRequest.SessionID))
                {
                    diameterResponse = ResponseWaiter.GetResponse(diameterRequest.SessionID);
                }
                else
                {
                    Common.StackLog.Write2ErrorLog("Transport::SendMessage", "Response message not available for " + DiameterMessageCode.GetMessageName(diameterRequest.CommandCode, true) + " " + diameterRequest.SessionID);
                    return(null);
                }
                //Check the Recieved Response
                if (diameterResponse != null)
                {
                    Common.StackLog.Write2TraceLog("Transport.SendMessage() ", "Response Message " + DiameterMessageCode.GetMessageName(diameterResponse.CommandCode, false) + " of Request Session: " + diameterRequest.SessionID + " with Response of:" + diameterResponse.SessionID.ToString() + " Received..\r\n");

                    /*if (diameterResponse.avps.Count == 0)
                     * {
                     *  StackLog.Write2ErrorLog("SendMessage", "Response Msg has no AVP's for Session:" + diameterResponse.SessionID);
                     *  StackLog.Write2ErrorLog("SendMessage", diameterResponse.ToString());
                     * }*/
                    ////Log Recieved Message
                    //StackLog.Write2MessageLog(diameterResponse.ToString());
                    msgLogger.Write2MessageLog(diameterResponse.ToString());
                    TimeSpan ETime = new TimeSpan(DateTime.Now.Ticks);
                    diameterResponse.ExecTime = ETime.Subtract(STime).Milliseconds;
                    //diameterResponse.PrintMessage();
                }
                else
                {
                    Common.StackLog.Write2ErrorLog("Transport::SendMessage", "Unable to Receive Response message for " + DiameterMessageCode.GetMessageName(diameterRequest.CommandCode, true) + " " + diameterRequest.SessionID);
                    //Common.StackLog.Write2ErrorLog("Transport::SendMessage", diameterRequest.ToString());
                }

                return(diameterResponse);
            }
            catch (Exception exp)
            {
                StackLog.Write2ErrorLog("DiameterTransport:SendMessage()", "Error:" + exp.Message + " Stack:" + exp.StackTrace.ToString());
                //throw exp;
                return(null);
            }
        }
        private void ReceiveCallbackSeq(IAsyncResult result)
        {
            int bytesRead;

            StateObject state = (StateObject)result.AsyncState;

            Socket client = state.workSocket;

            //NetworkStream networkStream = tcpClient.GetStream();
            //responseBuffer = result.AsyncState as byte[];

            try
            {
                // Retrieve the state object and the client socket

                try
                {
                    // read = networkStream.EndRead(result);
                    bytesRead = client.EndReceive(result);
                }
                catch
                {
                    //An error has occured when reading
                    return;
                }

                if (bytesRead == 0)
                {
                    //The connection has been closed.
                    return;
                }

                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallbackSeq), state);
                /// Begin processing Diameter messages
                ///
                byte[] responselocBuffer = new byte[bytesRead];

                Array.Copy(state.buffer, 0, responselocBuffer, 0, bytesRead);

                Message msg = new Message(stackContext, responselocBuffer);

                //msg = msg.ProcessMessage(stackContext, responselocBuffer);

                //Perform Additional Messag Processing

                if (msg.CommandCode == DiameterMessageCode.DEVICE_WATCHDOG)
                {
                    Message DWA    = new Answer(stackContext).CreateDWA(msg);
                    byte[]  toSend = DWA.GetBytes();
                    //networkStream.Write(toSend, 0, toSend.Length);
                    client.Send(toSend);
                }
                else
                {
                    //Return message response
                    if (msg.CommandCode == DiameterMessageCode.CAPABILITY_EXCHANGE)
                    {
                        if (ResponseWaiter.ContainsRequest("CEX"))
                        {
                            msg.SessionID = "CEX";
                            if (!ResponseWaiter.AddResponse(msg))
                            {
                                Common.StackLog.Write2ErrorLog("ReceiveCallBack", "Unable to Add Response for CEA Session:" + msg.SessionID);
                            }
                        }
                        else
                        {
                            Common.StackLog.Write2ErrorLog("ReceiveCallBack", "Unexpected CEA Received \r\n" + msg.ToString());
                        }
                    }
                    else if (msg.CommandCode == DiameterMessageCode.CREDIT_CONTROL)
                    {
                        if (ResponseWaiter.ContainsRequest(msg.SessionID))
                        {
                            if (!ResponseWaiter.AddResponse(msg))
                            {
                                Common.StackLog.Write2ErrorLog("ReceiveCallBack", "Unable to Add Response for CCA Session:" + msg.SessionID);
                            }
                        }
                        else
                        {
                            Common.StackLog.Write2ErrorLog("ReceiveCallBack", "Unexpected CCA Received for Session " + msg.SessionID + "\r\n" + msg.ToString());
                        }
                    }
                    else
                    {
                        Common.StackLog.Write2ErrorLog("ReceiveCallBack", "Unexpected Messages Received:" + msg.ToString());
                    }
                }

                //Then start reading from the network again after Parsing recieved Message.
                //networkStream.BeginRead(responseBuffer, 0, responseBuffer.Length, ReceiveCallback, buffer);
            }
            catch (Exception e)
            {
                //Then start reading from the network again.
                //networkStream.BeginRead(buffer, 0, buffer.Length, ReceiveCallback, buffer);
                //state.workSocket.Connect(state.workSocket.RemoteEndPoint);
                Common.StackLog.Write2ErrorLog("ReceiveCallBack", "Error:" + e.Message + " Stack:" + e.StackTrace);

                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallbackSeq), state);
            }
        }