/// <summary>
        /// InProgress --> (401/407/421/494) --> InProgress
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean InProgress_2_InProgress_X_401_407_421_494(params Object[] parameters)
        {
            TSIP_Response response = parameters[1] as TSIP_Response;
            Boolean       ret;

            if (!(ret = base.UpdateWithResponse(response)))
            {
                /* alert the user */
                TSIP_EventRegister.Signal(mUnRegsitering ? TSIP_EventRegister.tsip_register_event_type_t.AO_UNREGISTER : TSIP_EventRegister.tsip_register_event_type_t.AO_REGISTER,
                                          base.SipSession,
                                          response.StatusCode, response.ReasonPhrase, response);

                /* set last error (or info) */
                base.SetLastError((short)response.StatusCode, response.ReasonPhrase, response);

                return(ret);
            }

            /* Ensure IPSec SAs */
            //if (TSIP_DIALOG_GET_STACK(self)->security.secagree_mech && tsk_striequals(TSIP_DIALOG_GET_STACK(self)->security.secagree_mech, "ipsec-3gpp"))
            //{
            //    tsip_transport_ensureTempSAs(TSIP_DIALOG_GET_STACK(self)->layer_transport, response, TSIP_DIALOG(self)->expires);
            //}

            return(this.SendRegister(false));
        }
예제 #2
0
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //				== STATE MACHINE END ==
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        /* ======================== conds ======================== */
        private static Boolean IsResp2INVITE(Object self, Object message)
        {
            TSIP_Response response = message != null ? (message as TSIP_Response) : null;

            if (response != null)
            {
                return(response.CSeq.RequestType == TSIP_Message.tsip_request_type_t.INVITE);
            }
            return(false);
        }
        /// <summary>
        /// InProgress -> (2xx) -> Terminated
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean InProgress_2_Terminated_X_2xx(params Object[] parameters)
        {
            TSIP_Response response = parameters[1] as TSIP_Response;

            /* Alert the user */
            TSIP_EventRegister.Signal(TSIP_EventRegister.tsip_register_event_type_t.AO_UNREGISTER, base.SipSession,
                                      response.StatusCode, response.ReasonPhrase, response);

            return(true);
        }
        /// <summary>
        /// InProgress -> (1xx) -> InProgress
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean InProgress_2_InProgress_X_1xx(params Object[] parameters)
        {
            TSIP_Response response = parameters[1] as TSIP_Response;

            /* Alert the user (session) */
            TSIP_EventRegister.Signal(TSIP_EventRegister.tsip_register_event_type_t.AO_REGISTER,
                                      base.SipSession, response.StatusCode, response.ReasonPhrase, response);

            return(base.UpdateWithResponse(response));
        }
        /// <summary>
        /// InProgress -> (300-699) -> Terminated
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean InProgress_2_Terminated_X_300_to_699(params Object[] parameters)
        {
            TSIP_Response response = parameters[1] as TSIP_Response;

            base.SetLastError((short)response.StatusCode, response.ReasonPhrase, response);

            /* alert the user */
            TSIP_EventRegister.Signal(mUnRegsitering ? TSIP_EventRegister.tsip_register_event_type_t.AO_UNREGISTER : TSIP_EventRegister.tsip_register_event_type_t.AO_REGISTER,
                                      base.SipSession,
                                      response.StatusCode, response.ReasonPhrase, response);

            return(true);
        }
예제 #6
0
        /// <summary>
        /// Any -> (error) -> Terminated
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean Any_2_Terminated_X_Error(params Object[] parameters)
        {
            TSIP_Response response = parameters[2] as TSIP_Response;

            if (response != null)
            {
                base.SetLastError((short)response.StatusCode, response.ReasonPhrase, response);
                TSIP_EventRegister.Signal(mUnRegsitering ? TSIP_EventRegister.tsip_register_event_type_t.AO_UNREGISTER : TSIP_EventRegister.tsip_register_event_type_t.AO_REGISTER,
                                          base.SipSession, response.StatusCode, response.ReasonPhrase, response);
            }
            else
            {
                TSIP_EventDialog.Signal(TSIP_EventDialog.tsip_dialog_event_type_t.GlobalError, base.SipSession, "Global error", null);
            }

            return(false);
        }
        internal TSIP_Transac FindClientTransacByMsg(TSIP_Response response)
        {
            /* RFC 3261 - 17.1.3 Matching Responses to Client Transactions
             *
             * When the transport layer in the client receives a response, it has to
             * determine which client transaction will handle the response, so that
             * the processing of Sections 17.1.1 and 17.1.2 can take place.  The
             * branch parameter in the top Via header field is used for this
             * purpose.  A response matches a client transaction under two
             * conditions:
             *
             *   1.  If the response has the same value of the branch parameter in
             *       the top Via header field as the branch parameter in the top
             *       Via header field of the request that created the transaction.
             *
             *   2.  If the method parameter in the CSeq header field matches the
             *       method of the request that created the transaction.  The
             *       method is needed since a CANCEL request constitutes a
             *       different transaction, but shares the same value of the branch
             *       parameter.
             */
            if (response == null || response.FirstVia == null || response.CSeq == null)
            {
                return(null);
            }

            TSIP_Transac transac = null;

            mMutex.WaitOne();

            foreach (TSIP_Transac t in mTransactions.Values)
            {
                if (String.Equals(t.Branch, response.FirstVia.Branch) && String.Equals(t.CSeqMethod, response.CSeq.Method))
                {
                    transac = t;
                    break;
                }
            }

            mMutex.ReleaseMutex();

            return(transac);
        }
        /// <summary>
        /// InProgress -> (423) -> InProgress
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean InProgress_2_InProgress_X_423(params Object[] parameters)
        {
            TSIP_Response response = parameters[1] as TSIP_Response;

            /* FIXME
             *  RFC 3261 - 10.2.8 Error Responses
             *
             *  If a UA receives a 423 (Interval Too Brief) response, it MAY retry
             *  the registration after making the expiration interval of all contact
             *  addresses in the REGISTER request equal to or greater than the
             *  expiration interval within the Min-Expires header field of the 423
             *  (Interval Too Brief) response.
             */
            //hdr = (tsip_header_Min_Expires_t*)tsip_message_get_header(message, tsip_htype_Min_Expires);
            //if (hdr)
            //{
            //    TSIP_DIALOG(self)->expires = TSK_TIME_S_2_MS(hdr->value);

            //    if (tsk_striequals(TSIP_DIALOG_GET_STACK(self)->security.secagree_mech, "ipsec-3gpp"))
            //    {
            //        tsip_transport_cleanupSAs(TSIP_DIALOG_GET_STACK(self)->layer_transport);
            //        ret = tsip_dialog_register_send_REGISTER(self, tsk_true);
            //    }
            //    else
            //    {
            //        ret = tsip_dialog_register_send_REGISTER(self, tsk_false);
            //    }
            //}
            //else
            //{
            //    ret = -1;
            //}


            TSK_Debug.Error("Not implemented");
            return(false);
        }
        internal TSIP_Transac FindClientTransacByMsg(TSIP_Response response)
        {
            /* RFC 3261 - 17.1.3 Matching Responses to Client Transactions

               When the transport layer in the client receives a response, it has to
               determine which client transaction will handle the response, so that
               the processing of Sections 17.1.1 and 17.1.2 can take place.  The
               branch parameter in the top Via header field is used for this
               purpose.  A response matches a client transaction under two
               conditions:

                  1.  If the response has the same value of the branch parameter in
                      the top Via header field as the branch parameter in the top
                      Via header field of the request that created the transaction.

                  2.  If the method parameter in the CSeq header field matches the
                      method of the request that created the transaction.  The
                      method is needed since a CANCEL request constitutes a
                      different transaction, but shares the same value of the branch
                      parameter.
                */
            if (response == null || response.FirstVia == null || response.CSeq == null)
            {
                return null;
            }

            TSIP_Transac transac = null;

            mMutex.WaitOne();

            foreach (TSIP_Transac t in mTransactions.Values)
            {
                if (String.Equals(t.Branch, response.FirstVia.Branch) && String.Equals(t.CSeqMethod, response.CSeq.Method))
                {
                    transac = t;
                    break;
                }
            }

            mMutex.ReleaseMutex();

            return transac;
        }
예제 #10
0
        /// <summary>
        /// Callback function called to alert the dialog for new events from the transaction/transport layers
        /// </summary>
        /// <param name="type"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private Boolean OnCallbackEvent(tsip_dialog_event_type_t type, TSIP_Message message)
        {
            Boolean ret = false;

            switch (type)
            {
            case tsip_dialog_event_type_t.I_MSG:
            {
                if (message != null)
                {
                    if (message.IsResponse)
                    {
                        TSIP_Response response = message as TSIP_Response;
                        //
                        //	RESPONSE
                        //
                        if (response.Is1xx)
                        {
                            ret = base.ExecuteAction((Int32)FSMAction._1xx, message, null);
                        }
                        else if (response.Is2xx)
                        {
                            ret = base.ExecuteAction((Int32)FSMAction._2xx, message, null);
                        }
                        else if (response.StatusCode == 401 || response.StatusCode == 407 || response.StatusCode == 421 || response.StatusCode == 494)
                        {
                            ret = base.ExecuteAction((Int32)FSMAction._401_407_421_494, message, null);
                        }
                        else if (response.StatusCode == 423)
                        {
                            ret = base.ExecuteAction((Int32)FSMAction._423, message, null);
                        }
                        else
                        {
                            // Alert User
                            ret = base.ExecuteAction((Int32)FSMAction.Error, message, null);
                            /* TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg)); */
                        }
                    }
                    else
                    {
                        //
                        //	REQUEST
                        //
                        if (message.IsREGISTER)
                        {
                            ret = base.ExecuteAction((Int32)FSMAction.iREGISTER, message, null);
                        }
                    }
                }
                break;
            }

            case tsip_dialog_event_type_t.CANCELED:
            {
                ret = base.ExecuteAction((Int32)FSMAction.Cancel, message, null);
                break;
            }

            case tsip_dialog_event_type_t.TERMINATED:
            case tsip_dialog_event_type_t.TIMEDOUT:
            case tsip_dialog_event_type_t.ERROR:
            case tsip_dialog_event_type_t.TRANSPORT_ERROR:
            {
                ret = base.ExecuteAction((Int32)FSMAction.TransportError, message, null);
                break;
            }
            }

            return(true);
        }
예제 #11
0
        /// <summary>
        /// Updates the dialog state:
        /// - Authorizations (using challenges from the @a response message)
        /// - State (early, established, disconnected, ...)
        /// - Routes (and Service-Route)
        /// - Target (remote)
        /// - ...
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        protected Boolean UpdateWithResponse(TSIP_Response response)
        {
            if (response == null || response.To == null || response.CSeq == null)
            {
                return(false);
            }
            String tag = response.To.Tag;

            /*
             *	1xx (!100) or 2xx
             */
            /*
             *	401 or 407 or 421 or 494
             */
            if (response.StatusCode == 401 || response.StatusCode == 407 || response.StatusCode == 421 || response.StatusCode == 494)
            {
                Boolean acceptNewVector;

                /* 3GPP IMS - Each authentication vector is used only once.
                 *	==> Re-registration/De-registration ==> Allow 401/407 challenge.
                 */
                acceptNewVector = (response.CSeq.RequestType == TSIP_Message.tsip_request_type_t.REGISTER && this.State == tsip_dialog_state_t.Established);
                return(this.UpdateChallenges(response, acceptNewVector));
            }
            else if (100 < response.StatusCode && response.StatusCode < 300)
            {
                tsip_dialog_state_t state = this.State;

                /* 1xx */
                if (response.StatusCode <= 199)
                {
                    if (String.IsNullOrEmpty(response.To.Tag))
                    {
                        TSK_Debug.Error("Invalid tag  parameter");
                        return(false);
                    }
                    state = tsip_dialog_state_t.Early;
                }
                /* 2xx */
                else
                {
                    state = tsip_dialog_state_t.Established;
                }

                /* Remote target */
                {
                    /*	RFC 3261 12.2.1.2 Processing the Responses
                     *  When a UAC receives a 2xx response to a target refresh request, it
                     *  MUST replace the dialog's remote target URI with the URI from the
                     *  Contact header field in that response, if present.
                     *
                     *  FIXME: Because PRACK/UPDATE sent before the session is established MUST have
                     *  the rigth target URI to be delivered to the UAS ==> Do not not check that we are connected
                     */
                    if (response.CSeq.RequestType != TSIP_Message.tsip_request_type_t.REGISTER && response.Contact != null && response.Contact.Uri != null)
                    {
                        mUriRemoteTarget = response.Contact.Uri.Clone(true, false);
                    }
                }

                /* Route sets */
                {
                    int index;
                    TSIP_HeaderRecordRoute recordRoute;

                    mRecordRoutes.Clear();

                    for (index = 0; (recordRoute = response.GetHeaderAtIndex(TSIP_Header.tsip_header_type_t.Record_Route, index) as TSIP_HeaderRecordRoute) != null; index++)
                    {
                        mRecordRoutes.Insert(0, recordRoute); /* Copy reversed. */
                    }
                }

                /* cseq + tags + ... */
                if (this.State == tsip_dialog_state_t.Established && String.Equals(mTagRemote, tag, StringComparison.InvariantCultureIgnoreCase))
                {
                    return(true);
                }
                else
                {
                    if (response.CSeq.RequestType != TSIP_Message.tsip_request_type_t.REGISTER && response.CSeq.RequestType != TSIP_Message.tsip_request_type_t.PUBLISH)
                    { /* REGISTER and PUBLISH don't establish dialog */
                        mTagRemote = tag;
                    }
#if NEVER_EXECUTE_00    // PRACK and BYE will have same CSeq value ==> Let CSeq value to be incremented by "tsip_dialog_request_new()"
                    self->cseq_value = response->CSeq ? response->CSeq->seq : self->cseq_value;
#endif
                }

                this.State = state;
                return(true);
            }

            return(true);
        }
예제 #12
0
        private Boolean UpdateChallenges(TSIP_Response response, Boolean acceptNewVector)
        {
            Boolean ret = true;
            TSIP_HeaderWWWAuthenticate WWW_Authenticate;

            // TSIP_HeaderProxyAuthenticate Proxy_Authenticate;

            /* RFC 2617 - HTTP Digest Session
             *
             *	(A) The client response to a WWW-Authenticate challenge for a protection
             *          space starts an authentication session with that protection space.
             *          The authentication session lasts until the client receives another
             *          WWW-Authenticate challenge from any server in the protection space.
             *
             *          (B) The server may return a 401 response with a new nonce value, causing the client
             *          to retry the request; by specifying stale=TRUE with this response,
             *          the server tells the client to retry with the new nonce, but without
             *          prompting for a new username and password.
             */
            /* RFC 2617 - 1.2 Access Authentication Framework
             *  The realm directive (case-insensitive) is required for all authentication schemes that issue a challenge.
             */

            /* FIXME: As we perform the same task ==> Use only one loop.
             */

            for (int i = 0; (WWW_Authenticate = (TSIP_HeaderWWWAuthenticate)response.GetHeaderAtIndex(TSIP_Header.tsip_header_type_t.WWW_Authenticate, i)) != null; i++)
            {
                Boolean isnew = true;

                foreach (TSIP_Challenge challenge in mChallenges)
                {
                    //if(challenge.IProxy)
                    //{
                    //    continue;
                    //}

                    if (String.Equals(challenge.Realm, WWW_Authenticate.Realm, StringComparison.InvariantCultureIgnoreCase) && (WWW_Authenticate.Stale || acceptNewVector))
                    {
                        /*== (B) ==*/
                        if (!(ret = challenge.Update(WWW_Authenticate.Scheme,
                                                     WWW_Authenticate.Realm,
                                                     WWW_Authenticate.Nonce,
                                                     WWW_Authenticate.Opaque,
                                                     WWW_Authenticate.Algorithm,
                                                     WWW_Authenticate.Qop)))
                        {
                            return(ret);
                        }
                        else
                        {
                            isnew = false;
                            continue;
                        }
                    }
                    else
                    {
                        TSK_Debug.Error("Failed to handle new challenge");
                        return(false);
                    }
                }

                if (isnew)
                {
                    TSIP_Challenge challenge;
                    if ((challenge = new TSIP_Challenge(this.Stack,
                                                        false,
                                                        WWW_Authenticate.Scheme,
                                                        WWW_Authenticate.Realm,
                                                        WWW_Authenticate.Nonce,
                                                        WWW_Authenticate.Opaque,
                                                        WWW_Authenticate.Algorithm,
                                                        WWW_Authenticate.Qop)) != null)
                    {
                        mChallenges.Add(challenge);
                    }
                    else
                    {
                        TSK_Debug.Error("Failed to handle new challenge");
                        return(false);
                    }
                }
            }

            return(ret);
        }
예제 #13
0
        protected Int64 GetNewDelay(TSIP_Response response)
        {
            Int64       expires  = mExpires;
            Int64       newdelay = expires; /* default value */
            TSIP_Header hdr;
            int         i;

            /*== NOTIFY with subscription-state header with expires parameter */
            if (response.CSeq.RequestType == TSIP_Message.tsip_request_type_t.NOTIFY)
            {
                TSIP_HeaderSubscriptionState hdr_state = response.GetHeader(TSIP_Header.tsip_header_type_t.Subscription_State) as TSIP_HeaderSubscriptionState;
                if (hdr_state != null && hdr_state.Expires > 0)
                {
                    expires = TSK_Time.Seconds2Milliseconds(hdr_state.Expires);
                    goto compute;
                }
            }

            /*== Expires header */
            if ((hdr = response.GetHeader(TSIP_Header.tsip_header_type_t.Expires)) != null)
            {
                expires = TSK_Time.Seconds2Milliseconds((hdr as TSIP_HeaderExpires).DeltaSeconds);
                goto compute;
            }

            /*== Contact header */
            for (i = 0; (hdr = response.GetHeaderAtIndex(TSIP_Header.tsip_header_type_t.Contact, i)) != null; i++)
            {
                TSIP_HeaderContact contact = hdr as TSIP_HeaderContact;

                if (contact != null && contact.Uri != null)
                {
                    String   transport  = TSK_Param.GetValueByName(contact.Uri.Params, "transport");
                    TSIP_Uri contactUri = this.Stack.GetContactUri(String.IsNullOrEmpty(transport) ? "udp" : transport);
                    if (contactUri != null)
                    {
                        if (String.Equals(contact.Uri.UserName, contactUri.UserName) &&
                            String.Equals(contact.Uri.Host, contactUri.Host) &&
                            contact.Uri.Port == contactUri.Port)
                        {
                            if (contact.Expires >= 0) /* No expires parameter ==> -1*/
                            {
                                expires = TSK_Time.Seconds2Milliseconds(contact.Expires);
                                goto compute;
                            }
                        }
                    }
                }
            }

            /*
             *	3GPP TS 24.229 -
             *
             *	The UE shall reregister the public user identity either 600 seconds before the expiration time if the initial
             *	registration was for greater than 1200 seconds, or when half of the time has expired if the initial registration
             *	was for 1200 seconds or less.
             */
compute:
            expires  = TSK_Time.Milliseconds2Seconds(expires);
            newdelay = (expires > 1200) ? (expires - 600) : (expires / 2);

            return(TSK_Time.Seconds2Milliseconds(newdelay));
        }
예제 #14
0
        // this function is only called if no transaction match
        // for responses, the transaction will always match
        internal Boolean HandleIncomingMessage(TSIP_Message message)
        {
            TSIP_Dialog dialog = null;
            TSIP_Transac transac = null;
            Boolean cid_matched;
            Boolean ret = false;

            dialog = this.FindDialog(message.CallId.Value,
                message.IsResponse ? message.To.Tag : message.From.Tag,
                message.IsResponse ? message.From.Tag : message.To.Tag,
                message.IsRequest ? (message as TSIP_Request).RequestType : TSIP_Message.tsip_request_type_t.NONE,
                out cid_matched);

            if (dialog != null)
            {
                if (message.IsCANCEL || message.IsACK)
                {
                    ret = dialog.RaiseCallback(TSIP_Dialog.tsip_dialog_event_type_t.I_MSG, message);
                    goto bail;
                }
                else
                {
                    transac = mStack.LayerTransac.CreateTransac(false, message, dialog);
                }
            }
            else
            {
                if (message.IsRequest)
                {
                    TSIP_Dialog newdialog = null;

                    switch ((message as TSIP_Request).RequestType)
                    {
                        case TSIP_Message.tsip_request_type_t.REGISTER:
                            {
                                /* incoming REGISTER */
                                TSIP_SessionRegister session = new TSIP_SessionRegister(mStack, message);
                                newdialog = new TSIP_DialogRegister(session, message.CallId == null ? null : message.CallId.Value);
                                break;
                            }
                    }

                    // for new dialog, create a new transac and start it later
                    if (newdialog != null)
                    {
                        transac = mStack.LayerTransac.CreateTransac(false, message, newdialog);
                        this.AddDialog(newdialog);
                    }
                }
            }

            if (transac != null)
            {
                ret = transac.Start((message as TSIP_Request));
            }
            else if (message.IsRequest) /* No transaction match for the SIP request */
            {
                TSIP_Response response = null;

                if (cid_matched) /* We are receiving our own message. */
                {
                    response = new TSIP_Response(482, "Loop Detected (Check your iFCs)", (message as TSIP_Request));
                    if (String.IsNullOrEmpty(response.To.Tag))/* Early dialog? */
                    {
                        response.To.Tag = "doubango";
                    }
                }
                else
                {
                    switch ((message as TSIP_Request).RequestType)
                    {
                        case TSIP_Message.tsip_request_type_t.OPTIONS: // Hacked to work on Tiscali IMS networks
                        case TSIP_Message.tsip_request_type_t.INFO:
                            {
                                response = new TSIP_Response(405, "Method Not Allowed", (message as TSIP_Request));
                                break;
                            }
                        default:
                            {
                                response = new TSIP_Response(481, "Dialog/Transaction Does Not Exist", (message as TSIP_Request));
                                break;
                            }
                    }
                }

                if (response != null)
                {
                    // send the response
                    ret = mStack.LayerTransport.SendMessage(response.FirstVia != null ? response.FirstVia.Branch : "no-branch", response);
                }
            }

            bail:
            return ret;
        }
        /// <summary>
        /// InProgress -> (2xx) -> Connected
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean InProgress_2_Connected_X_2xx(params Object[] parameters)
        {
            Boolean       ret      = true;
            TSIP_Response response = parameters[1] as TSIP_Response;

            Boolean first_time_to_connect = base.State == tsip_dialog_state_t.Initial;

            /*	- Set P-associated-uriS
             *	- Update service-routes
             *	- Update Pats
             */
            {
                int index;
                // const tsip_header_Path_t *hdr_Path;
                // const tsip_header_Service_Route_t *hdr_Service_Route;
                // const tsip_header_P_Associated_URI_t *hdr_P_Associated_URI_t;
                TSIP_Uri uri;

                /* To avoid memory leaks ==> delete all concerned objects (it worth nothing) */
                //TSK_OBJECT_SAFE_FREE(TSIP_DIALOG_GET_STACK(self)->associated_uris);
                //TSK_OBJECT_SAFE_FREE(TSIP_DIALOG_GET_STACK(self)->service_routes);
                //TSK_OBJECT_SAFE_FREE(TSIP_DIALOG_GET_STACK(self)->paths);

                /* Associated URIs */

                /*for(index = 0; (hdr_P_Associated_URI_t = (const tsip_header_P_Associated_URI_t*)tsip_message_get_headerAt(response, tsip_htype_P_Associated_URI, index)); index++){
                 *  if(!TSIP_DIALOG_GET_STACK(self)->associated_uris){
                 *      TSIP_DIALOG_GET_STACK(self)->associated_uris = tsk_list_create();
                 *  }
                 *  uri = tsk_object_ref(hdr_P_Associated_URI_t->uri);
                 *  tsk_list_push_back_data(TSIP_DIALOG_GET_STACK(self)->associated_uris, (void**)&uri);
                 * }*/

                /*	Service-Route (3GPP TS 24.229)
                 *  store the list of service route values contained in the Service-Route header field and bind the list to the contact
                 *  address used in registration, in order to build a proper preloaded Route header field value for new dialogs and
                 *  standalone transactions when using the respective contact address.
                 */
                /*for(index = 0; (hdr_Service_Route = (const tsip_header_Service_Route_t*)tsip_message_get_headerAt(response, tsip_htype_Service_Route, index)); index++){
                 *  if(!TSIP_DIALOG_GET_STACK(self)->service_routes){
                 *      TSIP_DIALOG_GET_STACK(self)->service_routes = tsk_list_create();
                 *  }
                 *  uri = tsk_object_ref(hdr_Service_Route->uri);
                 *  tsk_list_push_back_data(TSIP_DIALOG_GET_STACK(self)->service_routes, (void**)&uri);
                 * }*/

                /* Paths */

                /*for(index = 0; (hdr_Path = (const tsip_header_Path_t*)tsip_message_get_headerAt(response, tsip_htype_Path, index)); index++){
                 *  if(TSIP_DIALOG_GET_STACK(self)->paths == 0){
                 *      TSIP_DIALOG_GET_STACK(self)->paths = tsk_list_create();
                 *  }
                 *  uri = tsk_object_ref(hdr_Path->uri);
                 *  tsk_list_push_back_data(TSIP_DIALOG_GET_STACK(self)->paths, (void**)&uri);
                 * }*/
            }

            /* 3GPP TS 24.229 - 5.1.1.2 Initial registration */
            if (first_time_to_connect)
            {
                Boolean barred = true;
                //const tsk_list_item_t *item;
                //const tsip_uri_t *uri;
                //const tsip_uri_t *uri_first = 0;

                /*
                 *  b) store as the default public user identity the first URI on the list of URIs present in the P-Associated-URI header
                 *  field and bind it to the respective contact address of the UE and the associated set of security associations or TLS
                 *  session;
                 *  NOTE 4: When using the respective contact address and associated set of security associations or TLS session, the
                 *  UE can utilize additional URIs contained in the P-Associated-URI header field and bound it to the
                 *  respective contact address of the UE and the associated set of security associations or TLS session, e.g. for
                 *  application purposes.
                 *  c) treat the identity under registration as a barred public user identity, if it is not included in the P-Associated-URI
                 *  header field;
                 */
                //tsk_list_foreach(item, TSIP_DIALOG_GET_STACK(self)->associated_uris){
                //    uri = item->data;
                //    if(item == TSIP_DIALOG_GET_STACK(self)->associated_uris->head){
                //        uri_first = item->data;
                //    }
                //    if(!tsk_object_cmp(TSIP_DIALOG_GET_STACK(self)->identity.preferred, uri)){
                //        barred = 0;
                //        break;
                //    }
                //}

                //if(barred && uri_first){
                //    TSK_OBJECT_SAFE_FREE(TSIP_DIALOG_GET_STACK(self)->identity.preferred);
                //    TSIP_DIALOG_GET_STACK(self)->identity.preferred = tsk_object_ref((void*)uri_first);
                //}
            }

            /* Update the dialog state */
            if (!(ret = this.UpdateWithResponse(response)))
            {
                return(ret);
            }

            /* Reset current action */
            base.CurrentAction = null;

            /* Request timeout for dialog refresh (re-registration). */
            this.TimerRefresh.Period = (UInt64)base.GetNewDelay(response);
            this.TimerRefresh.Start();

            /* Alert the user (session) */
            TSIP_EventRegister.Signal(TSIP_EventRegister.tsip_register_event_type_t.AO_REGISTER, base.SipSession,
                                      response.StatusCode, response.ReasonPhrase, response);

            /* Alert the user (dialog) */
            if (first_time_to_connect)
            {
                TSIP_EventDialog.Signal(TSIP_EventDialog.tsip_dialog_event_type_t.Connected, base.SipSession, response.ReasonPhrase, response);
            }

            return(ret);
        }
    private static TSIP_Message Execute(ref TSK_RagelState state, Boolean extractContent)
    {
        int cs  = state.CS;
        int p   = state.P;
        int pe  = state.PE;
        int eof = state.EOF;

        byte[]       data    = state.Data;
        TSIP_Message message = null;


/* #line 233 "../Parsers/TSIP_ParserMessage.cs" */
        {
            sbyte _klen;
            byte  _trans;
            int   _widec;
            sbyte _acts;
            sbyte _nacts;
            byte  _keys;

            if (p == pe)
            {
                goto _test_eof;
            }
            if (cs == 0)
            {
                goto _out;
            }
_resume:
            _widec = data[p];
            _klen  = _tsip_machine_parser_message_cond_lengths[cs];
            _keys  = (byte)(_tsip_machine_parser_message_cond_offsets[cs] * 2);
            if (_klen > 0)
            {
                short _lower = _keys;
                short _mid;
                short _upper = (short)(_keys + (_klen << 1) - 2);
                while (true)
                {
                    if (_upper < _lower)
                    {
                        break;
                    }

                    _mid = (short)(_lower + (((_upper - _lower) >> 1) & ~1));
                    if (_widec < _tsip_machine_parser_message_cond_keys[_mid])
                    {
                        _upper = (short)(_mid - 2);
                    }
                    else if (_widec > _tsip_machine_parser_message_cond_keys[_mid + 1])
                    {
                        _lower = (short)(_mid + 2);
                    }
                    else
                    {
                        switch (_tsip_machine_parser_message_cond_spaces[_tsip_machine_parser_message_cond_offsets[cs] + ((_mid - _keys) >> 1)])
                        {
                        case 0: {
                            _widec = (int)(65536u + (data[p] - 0u));
                            if (
/* #line 29 "./ragel/tsip_parser_message.rl" */

                                PrevNotComma(state, p)
                                )
                            {
                                _widec += 65536;
                            }
                            break;
                        }

                        default: break;
                        }
                        break;
                    }
                }
            }

            _keys  = _tsip_machine_parser_message_key_offsets[cs];
            _trans = (byte)_tsip_machine_parser_message_index_offsets[cs];

            _klen = _tsip_machine_parser_message_single_lengths[cs];
            if (_klen > 0)
            {
                short _lower = _keys;
                short _mid;
                short _upper = (short)(_keys + _klen - 1);
                while (true)
                {
                    if (_upper < _lower)
                    {
                        break;
                    }

                    _mid = (short)(_lower + ((_upper - _lower) >> 1));
                    if (_widec < _tsip_machine_parser_message_trans_keys[_mid])
                    {
                        _upper = (short)(_mid - 1);
                    }
                    else if (_widec > _tsip_machine_parser_message_trans_keys[_mid])
                    {
                        _lower = (short)(_mid + 1);
                    }
                    else
                    {
                        _trans += (byte)(_mid - _keys);
                        goto _match;
                    }
                }
                _keys  += (byte)_klen;
                _trans += (byte)_klen;
            }

            _klen = _tsip_machine_parser_message_range_lengths[cs];
            if (_klen > 0)
            {
                short _lower = _keys;
                short _mid;
                short _upper = (short)(_keys + (_klen << 1) - 2);
                while (true)
                {
                    if (_upper < _lower)
                    {
                        break;
                    }

                    _mid = (short)(_lower + (((_upper - _lower) >> 1) & ~1));
                    if (_widec < _tsip_machine_parser_message_trans_keys[_mid])
                    {
                        _upper = (short)(_mid - 2);
                    }
                    else if (_widec > _tsip_machine_parser_message_trans_keys[_mid + 1])
                    {
                        _lower = (short)(_mid + 2);
                    }
                    else
                    {
                        _trans += (byte)((_mid - _keys) >> 1);
                        goto _match;
                    }
                }
                _trans += (byte)_klen;
            }

_match:
            _trans = (byte)_tsip_machine_parser_message_indicies[_trans];
            cs     = _tsip_machine_parser_message_trans_targs[_trans];

            if (_tsip_machine_parser_message_trans_actions[_trans] == 0)
            {
                goto _again;
            }

            _acts  = _tsip_machine_parser_message_trans_actions[_trans];
            _nacts = _tsip_machine_parser_message_actions[_acts++];
            while (_nacts-- > 0)
            {
                switch (_tsip_machine_parser_message_actions[_acts++])
                {
                case 0:
/* #line 30 "./ragel/tsip_parser_message.rl" */
                {
                    state.TagStart = p;
                }
                break;

                case 1:
/* #line 36 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);
                    String method = Encoding.UTF8.GetString(data, state.TagStart, len);
                    if (message == null)
                    {
                        message = new TSIP_Request(method, null, null, null, null, 0);
                    }
                    else
                    {
                        state.CS = tsip_machine_parser_message_error;
                    }
                }
                break;

                case 2:
/* #line 53 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);
                    if ((message as TSIP_Request).Uri == null)
                    {
                        (message as TSIP_Request).Uri = TSIP_ParserUri.Parse(Encoding.UTF8.GetString(state.Data, state.TagStart, len));
                    }
                }
                break;

                case 3:
/* #line 65 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);

                    if (message == null)
                    {
                        message = new TSIP_Response(0, null, null);
                    }
                    message.Version = Encoding.UTF8.GetString(state.Data, state.TagStart, len);
                }
                break;

                case 4:
/* #line 79 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);

                    if (message == null)
                    {
                        message = new TSIP_Response(0, null, null);
                    }

                    UInt16 statusCode = 0;
                    if (UInt16.TryParse(Encoding.UTF8.GetString(state.Data, state.TagStart, len), out statusCode))
                    {
                        (message as TSIP_Response).StatusCode = statusCode;
                    }
                }
                break;

                case 5:
/* #line 98 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);
                    (message as TSIP_Response).ReasonPhrase = Encoding.UTF8.GetString(state.Data, state.TagStart, len);
                }
                break;

                case 6:
/* #line 107 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);

                    if (!TSIP_ParserHeader.Parse(state, ref message))
                    {
                        TSK_Debug.Error("Failed to parse header at {0}", state.TagStart);
                    }
                }
                break;

                case 7:
/* #line 119 "./ragel/tsip_parser_message.rl" */
                {
                    state.CS  = cs;
                    state.P   = p;
                    state.PE  = pe;
                    state.EOF = eof;

                    TSIP_ParserMessage.EoH(ref state, ref message, extractContent);

                    cs  = state.CS;
                    p   = state.P;
                    pe  = state.PE;
                    eof = state.EOF;
                }
                break;

/* #line 447 "../Parsers/TSIP_ParserMessage.cs" */
                default: break;
                }
            }

_again:
            if (cs == 0)
            {
                goto _out;
            }
            if (++p != pe)
            {
                goto _resume;
            }
            _test_eof : {}
            _out      : {}
        }

/* #line 192 "./ragel/tsip_parser_message.rl" */

        state.CS  = cs;
        state.P   = p;
        state.PE  = pe;
        state.EOF = eof;

        return(message);
    }
예제 #17
0
        // this function is only called if no transaction match
        // for responses, the transaction will always match
        internal Boolean HandleIncomingMessage(TSIP_Message message)
        {
            TSIP_Dialog  dialog  = null;
            TSIP_Transac transac = null;
            Boolean      cid_matched;
            Boolean      ret = false;

            dialog = this.FindDialog(message.CallId.Value,
                                     message.IsResponse ? message.To.Tag : message.From.Tag,
                                     message.IsResponse ? message.From.Tag : message.To.Tag,
                                     message.IsRequest ? (message as TSIP_Request).RequestType : TSIP_Message.tsip_request_type_t.NONE,
                                     out cid_matched);

            if (dialog != null)
            {
                if (message.IsCANCEL || message.IsACK)
                {
                    ret = dialog.RaiseCallback(TSIP_Dialog.tsip_dialog_event_type_t.I_MSG, message);
                    goto bail;
                }
                else
                {
                    transac = mStack.LayerTransac.CreateTransac(false, message, dialog);
                }
            }
            else
            {
                if (message.IsRequest)
                {
                    TSIP_Dialog newdialog = null;

                    switch ((message as TSIP_Request).RequestType)
                    {
                    case TSIP_Message.tsip_request_type_t.REGISTER:
                    {
                        /* incoming REGISTER */
                        TSIP_SessionRegister session = new TSIP_SessionRegister(mStack, message);
                        newdialog = new TSIP_DialogRegister(session, message.CallId == null ? null : message.CallId.Value);
                        break;
                    }
                    }

                    // for new dialog, create a new transac and start it later
                    if (newdialog != null)
                    {
                        transac = mStack.LayerTransac.CreateTransac(false, message, newdialog);
                        this.AddDialog(newdialog);
                    }
                }
            }

            if (transac != null)
            {
                ret = transac.Start((message as TSIP_Request));
            }
            else if (message.IsRequest) /* No transaction match for the SIP request */
            {
                TSIP_Response response = null;

                if (cid_matched) /* We are receiving our own message. */
                {
                    response = new TSIP_Response(482, "Loop Detected (Check your iFCs)", (message as TSIP_Request));
                    if (String.IsNullOrEmpty(response.To.Tag))/* Early dialog? */
                    {
                        response.To.Tag = "doubango";
                    }
                }
                else
                {
                    switch ((message as TSIP_Request).RequestType)
                    {
                    case TSIP_Message.tsip_request_type_t.OPTIONS:     // Hacked to work on Tiscali IMS networks
                    case TSIP_Message.tsip_request_type_t.INFO:
                    {
                        response = new TSIP_Response(405, "Method Not Allowed", (message as TSIP_Request));
                        break;
                    }

                    default:
                    {
                        response = new TSIP_Response(481, "Dialog/Transaction Does Not Exist", (message as TSIP_Request));
                        break;
                    }
                    }
                }

                if (response != null)
                {
                    // send the response
                    ret = mStack.LayerTransport.SendMessage(response.FirstVia != null ? response.FirstVia.Branch : "no-branch", response);
                }
            }

bail:
            return(ret);
        }