Ejemplo n.º 1
0
            /// <summary>
            /// This method is called when INVITE 2xx retransmit timer triggered.
            /// </summary>
            /// <param name="sender">Sender.</param>
            /// <param name="e">Event data.</param>
            private void m_pTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                /* RFC 3261 13.3.1.4.
                 *  Once the response has been constructed, it is passed to the INVITE
                 *  server transaction.  Note, however, that the INVITE server
                 *  transaction will be destroyed as soon as it receives this final
                 *  response and passes it to the transport.  Therefore, it is necessary
                 *  to periodically pass the response directly to the transport until the
                 *  ACK arrives.  The 2xx response is passed to the transport with an
                 *  interval that starts at T1 seconds and doubles for each
                 *  retransmission until it reaches T2 seconds (T1 and T2 are defined in
                 *  Section 17).  Response retransmissions cease when an ACK request for
                 *  the response is received.  This is independent of whatever transport
                 *  protocols are used to send the response.
                 *
                 *      Since 2xx is retransmitted end-to-end, there may be hops between
                 *      UAS and UAC that are UDP.  To ensure reliable delivery across
                 *      these hops, the response is retransmitted periodically even if the
                 *      transport at the UAS is reliable.
                 *
                 *  If the server retransmits the 2xx response for 64*T1 seconds without
                 *  receiving an ACK, the dialog is confirmed, but the session SHOULD be
                 *  terminated.  This is accomplished with a BYE, as described in Section
                 *  15.
                 */

                lock (m_pLock){
                    if (m_StartTime.AddMilliseconds(64 * SIP_TimerConstants.T1) < DateTime.Now)
                    {
                        // Log
                        if (m_pDialog.Stack.Logger != null)
                        {
                            m_pDialog.Stack.Logger.AddText("Dialog [id='" + m_pDialog.ID + "'] ACK was not received for (re-)INVITE, terminating INVITE session.");
                        }

                        m_pDialog.Terminate("Dialog Error: ACK was not received for (re-)INVITE.", true);
                        Dispose();
                    }
                    else
                    {
                        // Retransmit response.
                        try{
                            m_pDialog.Flow.Send(m_pResponse);

                            // Log
                            if (m_pDialog.Stack.Logger != null)
                            {
                                m_pDialog.Stack.Logger.AddText("Dialog [id='" + m_pDialog.ID + "';statusCode=" + m_pResponse.StatusCode + "] UAS 2xx response retransmited");
                            }
                        }
                        catch (Exception x) {
                            // Log
                            if (m_pDialog.Stack.Logger != null)
                            {
                                m_pDialog.Stack.Logger.AddText("Dialog [id='" + m_pDialog.ID + "'] UAS 2xx response retransmission failed: " + x.Message);
                            }
                        }

                        m_pTimer.Interval = Math.Min(m_pTimer.Interval * 2, SIP_TimerConstants.T2);
                        m_pTimer.Enabled  = true;
                    }
                }
            }