Esempio n. 1
0
        /// <summary>
        /// Starts terminating call. To get when call actually terminates, monitor <b>StateChanged</b> event.
        /// </summary>
        /// <exception cref="ObjectDisposedException">Is raised when this object is disposed and and this method is accessed.</exception>
        public void Terminate()
        {
            lock (m_pLock)
            {
                if (m_State == SIP_UA_CallState.Disposed)
                {
                    throw new ObjectDisposedException(GetType().Name);
                }

                if (m_State == SIP_UA_CallState.Terminating || m_State == SIP_UA_CallState.Terminated)
                {
                    return;
                }
                else if (m_State == SIP_UA_CallState.WaitingForStart)
                {
                    SetState(SIP_UA_CallState.Terminated);
                }
                else if (m_State == SIP_UA_CallState.WaitingToAccept)
                {
                    m_pInitialInviteTransaction.SendResponse(
                        m_pUA.Stack.CreateResponse(SIP_ResponseCodes.x487_Request_Terminated,
                                                   m_pInitialInviteTransaction.Request));

                    SetState(SIP_UA_CallState.Terminated);
                }
                else if (m_State == SIP_UA_CallState.Active)
                {
                    m_pDialog.Terminate();

                    SetState(SIP_UA_CallState.Terminated);
                }
                else if (m_pInitialInviteSender != null)
                {
                    /* RFC 3261 15.
                     *  If we are caller and call is not active yet, we must do following actions:
                     *) Send CANCEL, set call Terminating flag.
                     *) If we get non 2xx final response, we are done. (Normally cancel causes '408 Request terminated')
                     *) If we get 2xx response (2xx sent by remote party before our CANCEL reached), we must send BYE to active dialog.
                     */

                    SetState(SIP_UA_CallState.Terminating);

                    m_pInitialInviteSender.Cancel();
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// This method is called when SIP stack received new message.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pStack_RequestReceived(object sender, SIP_RequestReceivedEventArgs e)
        {
            // TODO: Performance: rise events on thread pool or see if this method called on pool aready, then we may not keep lock for events ?

            if (e.Request.RequestLine.Method == SIP_Methods.CANCEL)
            {
                /* RFC 3261 9.2.
                 *  If the UAS did not find a matching transaction for the CANCEL
                 *  according to the procedure above, it SHOULD respond to the CANCEL
                 *  with a 481 (Call Leg/Transaction Does Not Exist).
                 *
                 *  Regardless of the method of the original request, as long as the
                 *  CANCEL matched an existing transaction, the UAS answers the CANCEL
                 *  request itself with a 200 (OK) response.
                 */

                SIP_ServerTransaction trToCancel = m_pStack.TransactionLayer.MatchCancelToTransaction(e.Request);
                if (trToCancel != null)
                {
                    trToCancel.Cancel();
                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, e.Request));
                }
                else
                {
                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist, e.Request));
                }
            }
            else if (e.Request.RequestLine.Method == SIP_Methods.BYE)
            {
                /* RFC 3261 15.1.2.
                 *  If the BYE does not match an existing dialog, the UAS core SHOULD generate a 481
                 *  (Call/Transaction Does Not Exist) response and pass that to the server transaction.
                 */
                // TODO:

                SIP_Dialog dialog = m_pStack.TransactionLayer.MatchDialog(e.Request);
                if (dialog != null)
                {
                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, e.Request));
                    dialog.Terminate();
                }
                else
                {
                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist, e.Request));
                }
            }
            else if (e.Request.RequestLine.Method == SIP_Methods.INVITE)
            {
                // Supress INVITE retransmissions.
                e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x100_Trying, e.Request));

                // Create call.
                SIP_UA_Call call = new SIP_UA_Call(this, e.ServerTransaction);
                call.StateChanged += new EventHandler(Call_StateChanged);
                m_pCalls.Add(call);

                OnIncomingCall(call);
            }
            else
            {
                OnRequestReceived(e);
            }
        }