/// <summary>
        /// Starts processing server transaction.
        /// </summary>
        private void Begin()
        {
            // Log
            m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) created.");

            // INVITE server transaction
            if(m_pRequest.Method == "INVITE"){
                /*  When a server transaction is constructed for a request, it enters the
                    "Proceeding" state. The server transaction MUST generate a 100 (Trying) response.
                */

                m_TransactionState = SIP_ServerTransactionState.Proceeding;

                SendTrying();
            }
            // Non-INVITE server transaction
            else{
                /* When a server transaction is constructed for a request, it enters the "Trying" state.
                */

                m_TransactionState = SIP_ServerTransactionState.Trying;
            }

            // This is just timout timer and ensures that transaction ends or will terminated.
            m_pTransactionTimeoutTimer = new Timer(120 * m_T1);
            m_pTransactionTimeoutTimer.Elapsed += new ElapsedEventHandler(m_pTransactionTimeoutTimer_Elapsed);
            m_pTransactionTimeoutTimer.Enabled = true;
            // Log
            m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) Transaction timeout Timer started, will triger after " + m_pTransactionTimeoutTimer.Interval + ".");
        }
        /// <summary>
        /// Processes transaction request.
        /// </summary>
        /// <param name="request">SIP request.</param>
        internal void ProcessRequest(SIP_Request request)
        {
            // TODO: We MAY accept only ACK,CANCEL and request retransmission.

            // Log
            m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) got request '" + request.Method +  "'.");

            lock(this){

                #region ACK

                if(request.Method == SIP_Methods.ACK){
                    /* RFC 3261 17.2.1.
                        If an ACK is received while the server transaction is in the
                        "Completed" state, the server transaction MUST transition to the
                        "Confirmed" state.  As Timer G is ignored in this state, any
                        retransmissions of the response will cease.

                        Also kill timer H(ACK wait timeout timer) because we got ACK.
                    */
                    if(m_TransactionState == SIP_ServerTransactionState.Completed){
                        m_TransactionState = SIP_ServerTransactionState.Confirmed;

                        // If there is timer G (response retransmit timer), stop it,because we got ACK.
                        if(m_pTimerG != null){
                            m_pTimerG.Dispose();
                            m_pTimerG = null;

                            // Log
                            m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) Timer G (response retransmit timer) stopped.");
                        }
                        // If there is timer H (ACK wait timeout timer), stop it because we got ACK.
                        if(m_pTimerH != null){
                            m_pTimerH.Dispose();
                            m_pTimerH = null;

                            // Log
                            m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) Timer H (ACK wait timeout timer) stopped.");
                        }

                        /* RFC 3261 17.2.1.
                            The purpose of the "Confirmed" state is to absorb any additional ACK
                            messages that arrive, triggered from retransmissions of the final response.
                            When confirmed state is entered, timer I is set to fire in T4
                            seconds for unreliable transports, and zero seconds for reliable transports.
                        */
                        if(request.Via.GetTopMostValue().ProtocolTransport.ToUpper() == "UDP"){
                            m_pTimerI = new Timer(m_T4);
                            m_pTimerI.AutoReset = false;
                            m_pTimerI.Elapsed += new ElapsedEventHandler(m_pTimerI_Elapsed);

                            // Log
                            m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) Timer I (additional ACK absorb) started, will triger after " + m_pTimerI.Interval + ".");
                        }
                        else{
                            Dispose();
                        }
                    }
                }

                #endregion

                #region CANCEL

                else if(request.Method == SIP_Methods.CANCEL){
                    // Do new server transaction for cancel.
                    // We bind RFC here, rfc says UAS needs to respond canel, we hide cancel stuff from user.
                    // If somebody knows why we can't do so, let me know.
                    m_pSipStack.TransactionLayer.CreateServerTransaction(request).SendResponse(request.CreateResponse(SIP_ResponseCodes.x200_Ok));

                    Cancel();
                }

                #endregion

                #region INVITE

                // INVITE server transaction
                else if(request.Method == SIP_Methods.INVITE){
                    /*
                        If a retransmission of the request is received while in the "Proceeding" state, the most
                        recently sent provisional response MUST be passed to the transport layer for retransmission.

                        In the "Completed" state, the server transaction MUST pass the final response to the transport
                        layer for retransmission whenever a retransmission of the request is received.
                    */

                    if(m_TransactionState == SIP_ServerTransactionState.Proceeding){
                        SIP_Response lastProvisionalResponse = GetLastProvisionalResponse();
                        if(lastProvisionalResponse != null){
                            m_pSipStack.TransportLayer.SendResponse(request.Socket,lastProvisionalResponse);
                        }
                    }
                    else if(m_TransactionState == SIP_ServerTransactionState.Completed){
                        m_pSipStack.TransportLayer.SendResponse(request.Socket,GetFinalResponse());
                    }
                }

                #endregion

                #region Non-INVITE

                // Non-INVITE server transaction
                else{
                    /*
                        In the "Trying" state, any further request retransmissions are discarded.

                        If a retransmission of the request is received while in the "Proceeding" state, the most
                        recently sent provisional response MUST be passed to the transport layer for retransmission.

                        In the "Completed" state, the server transaction MUST pass the final response to the transport
                        layer for retransmission whenever a retransmission of the request is received.
                    */

                    if(m_TransactionState == SIP_ServerTransactionState.Trying){
                        // Do nothing
                    }
                    else if(m_TransactionState == SIP_ServerTransactionState.Proceeding){
                        m_pSipStack.TransportLayer.SendResponse(request.Socket,GetLastProvisionalResponse());
                    }
                    else if(m_TransactionState == SIP_ServerTransactionState.Completed){
                        m_pSipStack.TransportLayer.SendResponse(request.Socket,GetFinalResponse());
                    }
                }

                #endregion

            }
        }
        /// <summary>
        /// Processes specified SIP response through this transaction.
        /// </summary>
        /// <param name="response">SIP response to process.</param>
        internal void ProcessResponse(SIP_Response response)
        {
            #region INVITE

            // INVITE server transaction
            if(m_pRequest.Method == "INVITE"){

                #region Proceeding

                // Proceeding state
                if(m_TransactionState == SIP_ServerTransactionState.Proceeding){
                    // 1xx response
                    if(response.StausCodeType == SIP_StatusCodeType.Provisional){
                        // We don't forward 100 Trying, skip it
                        if(response.StatusCode == 100){
                            return;
                        }

                        m_pResponses.Add(response);

                        EnsureDialog(response);
                        PassResponseToDialog(response);

                        // Send unreliably (Pass to tranport layer)
                        m_pSipStack.TransportLayer.SendResponse(m_pRequest.Socket,m_pRequest.RemoteEndPoint,response);
                    }
                    // 2xx response
                    else if(response.StausCodeType == SIP_StatusCodeType.Success){
                        EnsureDialog(response);
                        PassResponseToDialog(response);

                        // Send unreliably (Pass to tranport layer)
                        m_pSipStack.TransportLayer.SendResponse(m_pRequest.Socket,m_pRequest.RemoteEndPoint,response);

                        m_TransactionState = SIP_ServerTransactionState.Terminated;
                        Dispose();
                    }
                    // 300-699 response
                    else{
                        m_TransactionState = SIP_ServerTransactionState.Completed;
                        m_pResponses.Add(response);

                        // Send unreliably (Pass to tranport layer)
                        m_pSipStack.TransportLayer.SendResponse(m_pRequest.Socket,m_pRequest.RemoteEndPoint,response);

                        /* RFC 3261 17.2.1.
                            When the "Completed" state is entered, timer H MUST be set to fire in
                            64*T1 seconds for all transports.  Timer H determines when the server
                            transaction abandons retransmitting the response.
                        */
                        m_pTimerH = new Timer(64 * m_T1);
                        m_pTimerH.AutoReset = false;
                        m_pTimerH.Elapsed += new ElapsedEventHandler(m_pTimerH_Elapsed);
                        // Log
                        m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) Timer H(response retransmit timeout timer) started, will triger after " + m_pTimerH.Interval + ".");

                        /* RFC 3261 17.2.1.
                            For unreliable transports, timer G is set to fire in T1 seconds,
                            and is not set to fire for reliable transports.
                            (INVITE final response retransmit timer)
                        */
                        if(response.Via.GetTopMostValue().ProtocolTransport.ToUpper() == "UDP"){
                            m_pTimerG = new Timer(m_T1);
                            m_pTimerG.Elapsed += new ElapsedEventHandler(m_pTimerG_Elapsed);
                            m_pTimerG.Enabled = true;

                            // Log
                            m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) Timer G(INVITE final response retransmit timer) started, will triger after " + m_pTimerG.Interval + ".");
                        }
                    }
                }

                #endregion

                #region Completed

                // Completed state
                else if(m_TransactionState == SIP_ServerTransactionState.Completed){
                    // We do nothing here, we just wait ACK to arrive.
                }

                #endregion

                #region Confirmed

                else if(m_TransactionState == SIP_ServerTransactionState.Confirmed){
                    // We do nothing, just wait ACK retransmissions while linger time.
                }

                #endregion

                #region Terminated

                else if(m_TransactionState == SIP_ServerTransactionState.Terminated){
                   // We should never rreach here, but if so, skip it.
                }

                #endregion
            }

            #endregion

            #region Non-INVITE

            // Non-INVITE server transaction
            else{

                #region Trying

                // Trying state
                if(m_TransactionState == SIP_ServerTransactionState.Trying){
                    // 1xx response
                    if(response.StausCodeType == SIP_StatusCodeType.Provisional){
                        m_TransactionState = SIP_ServerTransactionState.Proceeding;
                        m_pResponses.Add(response);

                        // Send unreliably (Pass to tranport layer)
                        m_pSipStack.TransportLayer.SendResponse(m_pRequest.Socket,m_pRequest.RemoteEndPoint,response);
                    }
                    // 200-699 response
                    else{
                        m_TransactionState = SIP_ServerTransactionState.Completed;
                        m_pResponses.Add(response);

                        // Send unreliably (Pass to tranport layer)
                        m_pSipStack.TransportLayer.SendResponse(m_pRequest.Socket,m_pRequest.RemoteEndPoint,response);

                        /* RFC 3261 17.2.2.
                            When the server transaction enters the "Completed" state, it MUST set
                            Timer J to fire in 64*T1 seconds for unreliable transports.
                            (wait time for retransmissions of non-INVITE requests)
                        */
                        if(response.Via.GetTopMostValue().ProtocolTransport.ToUpper() == "UDP"){
                            m_pTimerJ = new Timer(64 * m_T1);
                            m_pTimerJ.AutoReset = false;
                            m_pTimerJ.Elapsed += new ElapsedEventHandler(m_pTimerJ_Elapsed);
                            m_pTimerJ.Enabled = true;

                            // Log
                            m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) Timer J(wait time for retransmissions of non-INVITE requests) started, will triger after " + m_pTimerJ.Interval + ".");
                        }
                        else{
                            Dispose();
                        }
                    }
                }

                #endregion

                #region Proceeding

                // Proceeding state
                else if(m_TransactionState == SIP_ServerTransactionState.Proceeding){
                    // 1xx response
                    if(response.StausCodeType == SIP_StatusCodeType.Provisional){
                        m_pResponses.Add(response);

                        // Send unreliably (Pass to tranport layer)
                        m_pSipStack.TransportLayer.SendResponse(m_pRequest.Socket,m_pRequest.RemoteEndPoint,response);
                    }
                    // 200-699 response
                    else{
                        m_TransactionState = SIP_ServerTransactionState.Completed;
                        m_pResponses.Add(response);

                        // Send unreliably (Pass to tranport layer)
                        m_pSipStack.TransportLayer.SendResponse(m_pRequest.Socket,m_pRequest.RemoteEndPoint,response);

                        /* RFC 3261 17.2.2.
                            When the server transaction enters the "Completed" state, it MUST set
                            Timer J to fire in 64*T1 seconds for unreliable transports.
                            (wait time for retransmissions of non-INVITE requests)
                        */
                        if(response.Via.GetTopMostValue().ProtocolTransport.ToUpper() == "UDP"){
                            m_pTimerJ = new Timer(64 * m_T1);
                            m_pTimerJ.AutoReset = false;
                            m_pTimerJ.Elapsed += new ElapsedEventHandler(m_pTimerJ_Elapsed);
                            m_pTimerJ.Enabled = true;

                            // Log
                            m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) Timer J(wait time for retransmissions of non-INVITE requests) started, will triger after " + m_pTimerJ.Interval + ".");
                        }
                    }
                }

                #endregion

                #region Completed

                // Completed state
                else if(m_TransactionState == SIP_ServerTransactionState.Completed){
                    // Just resend last response.
                    m_pSipStack.TransportLayer.SendResponse(m_pRequest.Socket,m_pRequest.RemoteEndPoint,GetFinalResponse());
                }

                #endregion

                #region Terminated

                // Terminated state
                else if(m_TransactionState == SIP_ServerTransactionState.Terminated){
                    // We should never rreach here, but if so, skip it.
                }

                #endregion
            }

            #endregion
        }
        /// <summary>
        /// Disposes transaction and cleans up all resources.
        /// </summary>
        public override void Dispose()
        {
            if(m_Disposed){
                return;
            }

            try{
                m_TransactionState = SIP_ServerTransactionState.Terminated;

                base.Dispose();

                if(m_pTransactionTimeoutTimer != null){
                    m_pTransactionTimeoutTimer.Dispose();
                    m_pTransactionTimeoutTimer = null;
                }

                if(m_pTimerG != null){
                    m_pTimerG.Dispose();
                    m_pTimerG = null;
                }

                if(m_pTimerH != null){
                    m_pTimerH.Dispose();
                    m_pTimerH = null;
                }

                if(m_pTimerI != null){
                    m_pTimerI.Dispose();
                    m_pTimerI = null;
                }

                if(m_pTimerJ != null){
                    m_pTimerJ.Dispose();
                    m_pTimerJ = null;
                }

                // Log
                m_pSipStack.Logger.AddDebug("Transaction(id='" + m_ID + "' method=" + m_pRequest.Method + " server=true) disposed.");
            }
            finally{
                // Remove from transactions collection.
                m_pSipStack.TransactionLayer.RemoveServerTransaction(this);

                OnTerminated();
            }

            m_Disposed = true;
        }