/// <summary>
 /// Raises event <b>Error</b>.
 /// </summary>
 /// <param name="e">Event data.</param>
 private void OnError(SIP_ResponseReceivedEventArgs e)
 {
     if (this.Error != null)
     {
         this.Error(this, e);
     }
 }
        /// <summary>
        /// This method is called when un-REGISTER has finished.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pUnregisterSender_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
        {
            SetState(SIP_UA_RegistrationState.Unregistered);
            OnUnregistered();

            if (m_AutoDispose)
            {
                Dispose();
            }

            m_pUnregisterSender = null;
        }
        /// <summary>
        /// This method is called when REGISTER has finished.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pRegisterSender_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
        {
            m_pFlow = e.ClientTransaction.Flow;

            if (e.Response.StatusCodeType == SIP_StatusCodeType.Provisional)
            {
                return;
            }
            else if (e.Response.StatusCodeType == SIP_StatusCodeType.Success)
            {
                m_pContacts.Clear();
                foreach (SIP_t_ContactParam c in e.Response.Contact.GetAllValues())
                {
                    m_pContacts.Add(c.Address.Uri);
                }

                SetState(SIP_UA_RegistrationState.Registered);

                OnRegistered();

                m_pFlow.SendKeepAlives = true;
            }
            else
            {
                SetState(SIP_UA_RegistrationState.Error);

                OnError(e);
            }

            // REMOVE ME:
            if (this.AutoFixContact && (m_pContact is SIP_Uri))
            {
                // If Via: received or rport paramter won't match to our sent-by, use received and rport to construct new contact value.

                SIP_Uri       cContact   = ((SIP_Uri)m_pContact);
                IPAddress     cContactIP = Net_Utils.IsIPAddress(cContact.Host) ? IPAddress.Parse(cContact.Host) : null;
                SIP_t_ViaParm via        = e.Response.Via.GetTopMostValue();
                if (via != null && cContactIP != null)
                {
                    IPEndPoint ep = new IPEndPoint(via.Received != null ? via.Received : cContactIP, via.RPort > 0 ? via.RPort : cContact.Port);
                    if (!cContactIP.Equals(ep.Address) || cContact.Port != via.RPort)
                    {
                        // Unregister old contact.
                        BeginUnregister(false);

                        // Fix contact.
                        cContact.Host = ep.Address.ToString();
                        cContact.Port = ep.Port;

                        m_pRegisterSender.Dispose();
                        m_pRegisterSender = null;

                        BeginRegister(m_AutoRefresh);

                        return;
                    }
                }
            }

            if (m_AutoRefresh)
            {
                // Set registration refresh timer.
                m_pTimer.Enabled = true;
            }

            m_pRegisterSender.Dispose();
            m_pRegisterSender = null;
        }
        /// <summary>
        /// Is called when client transactions receives response.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void ClientTransaction_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
        {
            lock (m_pLock){
                m_pFlow = e.ClientTransaction.Request.Flow;

                if (e.Response.StatusCode == 401 || e.Response.StatusCode == 407)
                {
                    // Check if authentication failed(We sent authorization data and it's challenged again,
                    // probably user name or password inccorect)
                    bool hasFailedAuthorization = false;
                    foreach (SIP_t_Challenge challange in e.Response.WWWAuthenticate.GetAllValues())
                    {
                        foreach (SIP_t_Credentials credentials in m_pTransaction.Request.Authorization.GetAllValues())
                        {
                            if (new Auth_HttpDigest(challange.AuthData, "").Realm == new Auth_HttpDigest(credentials.AuthData, "").Realm)
                            {
                                hasFailedAuthorization = true;
                                break;
                            }
                        }
                    }
                    foreach (SIP_t_Challenge challange in e.Response.ProxyAuthenticate.GetAllValues())
                    {
                        foreach (SIP_t_Credentials credentials in m_pTransaction.Request.ProxyAuthorization.GetAllValues())
                        {
                            if (new Auth_HttpDigest(challange.AuthData, "").Realm == new Auth_HttpDigest(credentials.AuthData, "").Realm)
                            {
                                hasFailedAuthorization = true;
                                break;
                            }
                        }
                    }

                    // Authorization failed, pass response to UA.
                    if (hasFailedAuthorization)
                    {
                        OnResponseReceived(e.Response);
                    }
                    // Try to authorize challanges.
                    else
                    {
                        SIP_Request request = m_pRequest.Copy();

                        /* RFC 3261 22.2.
                         *  When a UAC resubmits a request with its credentials after receiving a
                         *  401 (Unauthorized) or 407 (Proxy Authentication Required) response,
                         *  it MUST increment the CSeq header field value as it would normally
                         *  when sending an updated request.
                         */
                        request.CSeq = new SIP_t_CSeq(m_pStack.ConsumeCSeq(), request.CSeq.RequestMethod);

                        // All challanges authorized, resend request.
                        if (Authorize(request, e.Response, this.Credentials.ToArray()))
                        {
                            SIP_Flow flow = m_pTransaction.Flow;
                            CleanUpActiveTransaction();
                            SendToFlow(flow, request);
                        }
                        // We don't have credentials for one or more challenges.
                        else
                        {
                            OnResponseReceived(e.Response);
                        }
                    }
                }
                else
                {
                    OnResponseReceived(e.Response);
                    if (e.Response.StatusCodeType != SIP_StatusCodeType.Provisional)
                    {
                        OnCompleted();
                    }
                }
            }
        }