Changeset 283


Ignore:
Timestamp:
Mar 5, 2006 11:53:36 AM (18 years ago)
Author:
bennylp
Message:

Added API to terminate dialog prematurely. Affect: dialog, invite sessions, evsub, and presence

Location:
pjproject/trunk/pjsip
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsip-simple/evsub.h

    r228 r283  
    288288                                             pjsip_evsub **p_evsub); 
    289289 
     290/** 
     291 * Forcefully destroy the subscription session. This function should only 
     292 * be called on special condition, such as when the subscription  
     293 * initialization has failed. For other conditions, application MUST terminate 
     294 * the subscription by sending the appropriate un(SUBSCRIBE) or NOTIFY. 
     295 * 
     296 * @param sub           The event subscription. 
     297 * @param notify        Specify whether the state notification callback 
     298 *                      should be called. 
     299 * 
     300 * @return              PJ_SUCCESS if subscription session has been destroyed. 
     301 */ 
     302PJ_DECL(pj_status_t) pjsip_evsub_terminate( pjsip_evsub *sub, 
     303                                            pj_bool_t notify ); 
     304 
    290305 
    291306/** 
  • pjproject/trunk/pjsip/include/pjsip-simple/presence.h

    r212 r283  
    127127                                            pjsip_rx_data *rdata, 
    128128                                            pjsip_evsub **p_evsub ); 
     129 
     130 
     131/** 
     132 * Forcefully destroy the presence subscription. This function should only 
     133 * be called on special condition, such as when the subscription  
     134 * initialization has failed. For other conditions, application MUST terminate 
     135 * the subscription by sending the appropriate un(SUBSCRIBE) or NOTIFY. 
     136 * 
     137 * @param sub           The presence subscription. 
     138 * @param notify        Specify whether the state notification callback 
     139 *                      should be called. 
     140 * 
     141 * @return              PJ_SUCCESS if subscription session has been destroyed. 
     142 */ 
     143PJ_DECL(pj_status_t) pjsip_pres_terminate( pjsip_evsub *sub, 
     144                                           pj_bool_t notify ); 
     145 
    129146 
    130147 
  • pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h

    r223 r283  
    170170    pj_pool_t           *pool;                      /**< Dialog's pool.     */ 
    171171    pjsip_inv_state      state;                     /**< Invite sess state. */ 
     172    pjsip_status_code    cause;                     /**< Disconnect cause.  */ 
     173    pj_bool_t            notify;                    /**< Internal.          */ 
    172174    pjsip_dialog        *dlg;                       /**< Underlying dialog. */ 
    173175    pjsip_role_e         role;                      /**< Invite role.       */ 
     
    331333                                          unsigned options, 
    332334                                          pjsip_inv_session **p_inv); 
     335 
     336 
     337/** 
     338 * Forcefully terminate and destroy INVITE session, regardless of 
     339 * the state of the session. Note that this function should only be used 
     340 * when there is failure in the INVITE session creation. After the 
     341 * invite session has been created and initialized, normally application 
     342 * SHOULD use #pjsip_inv_end_session() to end the INVITE session instead. 
     343 * 
     344 * Note also that this function may terminate the underlying dialog, if 
     345 * there are no other sessions in the dialog. 
     346 * 
     347 * @param inv           The invite session. 
     348 * @param st_code       Status code for the reason of the termination. 
     349 * @param notify        If set to non-zero, then on_state_changed()  
     350 *                      callback will be called. 
     351 * 
     352 * @return              PJ_SUCCESS if the INVITE session has been 
     353 *                      terminated. 
     354 */ 
     355PJ_DECL(pj_status_t) pjsip_inv_terminate( pjsip_inv_session *inv, 
     356                                          int st_code, 
     357                                          pj_bool_t notify ); 
    333358 
    334359 
  • pjproject/trunk/pjsip/include/pjsip/sip_dialog.h

    r265 r283  
    6060 
    6161/** 
    62  * This structure describes the dialog structure. 
     62 * This structure describes the dialog structure. Application MUST NOT 
     63 * try to SET the values here directly, but instead it MUST use the 
     64 * appropriate dialog API. The dialog declaration only needs to be made  
     65 * visible because other PJSIP modules need to see it (e.g. INVITE session, 
     66 * the event framework, etc.). 
     67 * 
     68 * Application MAY READ the dialog contents directly after it acquires 
     69 * dialog lock. 
     70 * 
     71 * To acquire dialog lock, use #pjsip_dlg_inc_lock(), and to release it, 
     72 * use #pjsip_dlg_dec_lock(). DO NOT USE pj_mutex_lock()/pj_mutex_unlock() 
     73 * on the dialog's mutex directly, because this will not protect against 
     74 * dialog being destroyed. 
    6375 */ 
    6476struct pjsip_dialog 
     
    7082    char                obj_name[PJ_MAX_OBJ_NAME];  /**< Standard id.       */ 
    7183    pj_pool_t          *pool;       /**< Dialog's pool.                     */ 
    72     pj_mutex_t         *mutex;      /**< Dialog's mutex.                    */ 
     84    pj_mutex_t         *mutex;      /**< Dialog's mutex. Do not call!! 
     85                                         Use pjsip_dlg_inc_lock() instead!  */ 
    7386    pjsip_user_agent   *ua;         /**< User agent instance.               */ 
    7487    pjsip_endpoint     *endpt;      /**< Endpoint instance.                 */ 
     
    90103 
    91104    /** Session counter. */ 
    92     int                 sess_count; 
     105    int                 sess_count; /**< Number of sessions.                */ 
    93106 
    94107    /** Transaction counter. */ 
    95     int                 tsx_count; 
     108    int                 tsx_count;  /**< Number of pending transactions.    */ 
    96109 
    97110    /* Dialog usages. */ 
    98111    unsigned            usage_cnt;  /**< Number of registered usages.       */ 
    99     pjsip_module       *usage[PJSIP_MAX_MODULE]; /**< Array of usages, priority sorted   */ 
     112    pjsip_module       *usage[PJSIP_MAX_MODULE]; /**< Array of usages,  
     113                                         priority sorted                    */ 
    100114 
    101115    /** Module specific data. */ 
    102     void               *mod_data[PJSIP_MAX_MODULE]; 
     116    void               *mod_data[PJSIP_MAX_MODULE]; /**< Module data.       */ 
    103117}; 
    104118 
     
    108122 * dialog creating request. This method property is used to determine 
    109123 * whether Contact header should be included in outgoing request. 
     124 * 
     125 * @param m             The SIP method. 
     126 * 
     127 * @return              PJ_TRUE if the method creates a dialog. 
    110128 */ 
    111129PJ_DECL(pj_bool_t) pjsip_method_creates_dialog(const pjsip_method *m); 
     
    125143 * Note that initially, the session count in the dialog will be initialized  
    126144 * to zero. 
     145 * 
     146 * @param ua                The user agent module instance. 
     147 * @param local_uri         Dialog local URI (i.e. From header). 
     148 * @param local_contact_uri Optional dialog local Contact URI.  
     149 *                          If this argument is NULL, the Contact will be 
     150 *                          taken from the local URI. 
     151 * @param remote_uri        Dialog remote URI (i.e. To header). 
     152 * @param target            Optional initial remote target. If this argument 
     153 *                          is NULL, the initial target will be set to 
     154 *                          remote URI. 
     155 * @param p_dlg             Pointer to receive the dialog. 
     156 * 
     157 * @return                  PJ_SUCCESS on success. 
    127158 */ 
    128159PJ_DECL(pj_status_t) pjsip_dlg_create_uac( pjsip_user_agent *ua, 
     
    147178 * Note that initially, the session count in the dialog will be initialized  
    148179 * to zero. 
     180 * 
     181 * 
     182 * @param ua                The user agent module instance. 
     183 * @param rdata             The incoming request that creates the dialog, 
     184 *                          such as INVITE, SUBSCRIBE, or REFER. 
     185 * @param contact           Optional URI to be used as local Contact. If 
     186 *                          this argument is NULL, the local contact will be 
     187 *                          initialized from the value of To header in the 
     188 *                          request. 
     189 * @param p_dlg             Pointer to receive the dialog. 
     190 * 
     191 * @return                  PJ_SUCCESS on success. 
    149192 */ 
    150193PJ_DECL(pj_status_t) pjsip_dlg_create_uas(  pjsip_user_agent *ua, 
     
    163206 * Note that initially, the session count in the dialog will be initialized  
    164207 * to zero. 
     208 * 
     209 * @param original_dlg      The original UAC dialog. 
     210 * @param rdata             The incoming forked response message. 
     211 * @param new_dlg           Pointer to receive the new dialog. 
     212 * 
     213 * @return                  PJ_SUCCESS on success. 
    165214 */ 
    166215PJ_DECL(pj_status_t) pjsip_dlg_fork(const pjsip_dialog *original_dlg, 
     
    169218 
    170219/** 
     220 * Forcefully terminate the dialog. Application can only call this function 
     221 * when there is no session associated to the dialog. If there are sessions 
     222 * that use this dialog, this function will refuse to terminate the dialog. 
     223 * For this case, application MUST call the appropriate termination function  
     224 * for each dialog session (e.g. #pjsip_inv_terminate() to terminate INVITE 
     225 * session). 
     226 * 
     227 * @param dlg               The dialog. 
     228 * 
     229 * @return                  PJ_SUCCESS if dialog has been terminated. 
     230 */ 
     231PJ_DECL(pj_status_t) pjsip_dlg_terminate( pjsip_dialog *dlg ); 
     232 
     233 
     234/** 
    171235 * Set dialog's initial route set to route_set list. This can only be called 
    172236 * for UAC dialog, before any request is sent. After dialog has been  
     
    178242 * The route_set argument is standard list of Route headers (i.e. with  
    179243 * sentinel). 
     244 * 
     245 * @param dlg               The UAC dialog. 
     246 * @param route_set         List of Route header. 
     247 * 
     248 * @return                  PJ_SUCCESS on success. 
    180249 */ 
    181250PJ_DECL(pj_status_t) pjsip_dlg_set_route_set( pjsip_dialog *dlg, 
     
    185254 * Increment the number of sessions in the dialog. Note that initially  
    186255 * (after created) the dialog has the session counter set to zero. 
     256 * 
     257 * @param dlg               The dialog. 
     258 * @param mod               The module that increments the session counter. 
     259 * 
     260 * @return                  PJ_SUCCESS on success. 
    187261 */ 
    188262PJ_DECL(pj_status_t) pjsip_dlg_inc_session( pjsip_dialog *dlg, 
     
    195269 * destroyed. Note that this function may destroy the dialog immediately  
    196270 * if there is no pending transaction when this function is called. 
     271 * 
     272 * @param dlg               The dialog. 
     273 * @param mod               The module that decrements the session counter. 
     274 * 
     275 * @return                  PJ_SUCCESS on success. 
    197276 */ 
    198277PJ_DECL(pj_status_t) pjsip_dlg_dec_session( pjsip_dialog *dlg, 
     
    201280/** 
    202281 * Add a module as dialog usage, and optionally set the module specific data. 
     282 * 
     283 * @param dlg               The dialog. 
     284 * @param module            The module to be registered as dialog usage. 
     285 * @param mod_data          Optional arbitrary data to be attached to dialog's 
     286 *                          mod_data array at the module's index. 
     287 * 
     288 * @return                  PJ_SUCCESS on success. 
    203289 */ 
    204290PJ_DECL(pj_status_t) pjsip_dlg_add_usage( pjsip_dialog *dlg, 
     
    209295 * Attach module specific data to the dialog. Application can also set  
    210296 * the value directly by accessing dlg->mod_data[module_id]. 
     297 * 
     298 * @param dlg               The dialog 
     299 * @param mod_id            The ID of the module from which the data is to be 
     300 *                          set to the dialog. 
     301 * @param data              Arbitrary data. 
     302 * 
     303 * @return                  PJ_SUCCESS on success. 
    211304 */ 
    212305PJ_DECL(pj_status_t) pjsip_dlg_set_mod_data( pjsip_dialog *dlg, 
     
    217310 * Get module specific data previously attached to the dialog. Application 
    218311 * can also get value directly by accessing dlg->mod_data[module_id]. 
     312 * 
     313 * @param dlg               The dialog 
     314 * @param mod_id            The ID of the module from which the data is to be 
     315 *                          retrieved from the dialog. 
     316 * 
     317 * @return                  The data that was previously set, or NULL. 
    219318 */ 
    220319PJ_DECL(void*) pjsip_dlg_get_mod_data( pjsip_dialog *dlg, 
     
    225324 * Lock dialog and increment session counter termporarily, to prevent it  
    226325 * from being destroyed. 
     326 * 
     327 * @param dlg               The dialog. 
    227328 */ 
    228329PJ_DECL(void) pjsip_dlg_inc_lock( pjsip_dialog *dlg ); 
     
    231332 * Unlock dialog and decrement temporary session counter. After this function 
    232333 * is called, dialog may be destroyed. 
     334 * 
     335 * @param dlg               The dialog. 
    233336 */ 
    234337PJ_DECL(void) pjsip_dlg_dec_lock( pjsip_dialog *dlg ); 
     
    240343 * dialog instance in the rdata, or otherwise this function will return  
    241344 * NULL if the message didn't match any existing dialog. 
     345 * 
     346 * This function can only be called after endpoint distributes the message 
     347 * to the transaction layer or UA layer. In other words, application can 
     348 * only call this function in the context of module that runs in priority 
     349 * number higher than PJSIP_MOD_PRIORITY_UA_PROXY_LAYER. 
     350 * 
     351 * @param rdata             Incoming message buffer. 
     352 * 
     353 * @return                  The dialog instance that "owns" the message. 
    242354 */ 
    243355PJ_DECL(pjsip_dialog*) pjsip_rdata_get_dlg( pjsip_rx_data *rdata ); 
    244356 
    245357/** 
    246  * Get the associated dialog in a transaction. 
     358 * Get the associated dialog for the specified transaction, if any. 
     359 * 
     360 * @param tsx               The transaction. 
     361 * 
     362 * @return                  The dialog instance which has been registered 
     363 *                          to the transaction as transaction user, or 
     364 *                          NULL if the transaction is outside any dialogs. 
    247365 */ 
    248366PJ_DECL(pjsip_dialog*) pjsip_tsx_get_dlg( pjsip_transaction *tsx ); 
     
    257375 * 
    258376 * This function will also put Contact header where appropriate. 
     377 * 
     378 * @param dlg               The dialog instance. 
     379 * @param method            The method of the request. 
     380 * @param cseq              Optional CSeq, which only needs to be specified 
     381 *                          when creating ACK and CANCEL. For other requests, 
     382 *                          specify -1 to use dialog's internal counter. 
     383 * @param tdata             Pointer to receive the request's transmit 
     384 *                          data buffer. 
     385 * 
     386 * @return                  PJ_SUCCESS on success. 
    259387 */ 
    260388PJ_DECL(pj_status_t) pjsip_dlg_create_request(  pjsip_dialog *dlg, 
     
    278406 * This function will decrement the transmit data's reference counter 
    279407 * regardless the status of the operation. 
     408 * 
     409 * @param dlg               The dialog. 
     410 * @param tdata             The request message to be sent. 
     411 * @param p_tsx             Optional argument to receive the transaction  
     412 *                          instance used to send the request. 
     413 * 
     414 * @return                  PJ_SUCCESS on success. 
    280415 */ 
    281416PJ_DECL(pj_status_t) pjsip_dlg_send_request (   pjsip_dialog *dlg, 
     
    290425 * function adds Contact header and Record-Routes headers in the response  
    291426 * where appropriate. 
     427 * 
     428 * @param dlg               The dialog. 
     429 * @param rdata             The incoming request message for which the 
     430 *                          response will be created. 
     431 * @param st_code           Status code. 
     432 * @param st_text           Optional string for custom status reason text. 
     433 * @param tdata             Pointer to receive the response message transmit 
     434 *                          data buffer. 
     435 * 
     436 * @return                  PJ_SUCCESS on success. 
    292437 */ 
    293438PJ_DECL(pj_status_t) pjsip_dlg_create_response( pjsip_dialog *dlg, 
     
    301446 * Modify previously sent response with other status code. Contact header  
    302447 * will be added when appropriate. 
     448 * 
     449 * @param dlg               The dialog. 
     450 * @param tdata             The transmit data buffer containing response 
     451 *                          message to be modified. 
     452 * @param st_code           New status code to be set. 
     453 * @param st_text           Optional string for custom status reason text. 
     454 * 
     455 * @return                  PJ_SUCCESS on success. 
    303456 */ 
    304457PJ_DECL(pj_status_t) pjsip_dlg_modify_response( pjsip_dialog *dlg, 
     
    314467 * This function decrements the transmit data's reference counter regardless 
    315468 * the status of the operation. 
     469 * 
     470 * @param dlg               The dialog. 
     471 * @param tsx               The UAS transaction associated with the incoming 
     472 *                          request. If the request is within a dialog, or 
     473 *                          a dialog has been created for the request that 
     474 *                          creates the dialog, application can get the 
     475 *                          transaction instance for the request by calling 
     476 *                          #pjsip_rdata_get_tsx(). 
     477 * @param tdata             Response message to be sent. 
     478 * 
     479 * @return                  PJ_SUCCESS on success. 
    316480 */ 
    317481PJ_DECL(pj_status_t) pjsip_dlg_send_response(   pjsip_dialog *dlg, 
     
    341505                                        const pjsip_msg_body *body ); 
    342506 
     507 
     508/** 
     509 * @} 
     510 */ 
     511 
    343512/*  
    344513 * Internal (called by sip_ua_layer.c) 
     
    357526 
    358527 
    359 /** 
    360  * @} 
    361  */ 
    362528 
    363529PJ_END_DECL 
  • pjproject/trunk/pjsip/include/pjsip/sip_errno.h

    r212 r283  
    364364#define PJSIP_ENOREFERSESSION    (PJSIP_ERRNO_START_PJSIP+122)  /* 171122 */ 
    365365 
     366/************************************************************ 
     367 * INVITE SESSIONS ERRORS 
     368 ***********************************************************/ 
     369/** 
     370 * @hideinitializer 
     371 * Session already terminated. 
     372 */ 
     373#define PJSIP_ESESSIONTERMINATED (PJSIP_ERRNO_START_PJSIP+140)  /* 171140 */ 
     374 
    366375 
    367376 
  • pjproject/trunk/pjsip/src/pjsip-simple/evsub.c

    r275 r283  
    199199    unsigned              option;       /**< Options.                       */ 
    200200    pjsip_evsub_user      user;         /**< Callback.                      */ 
     201    pj_bool_t             call_cb;      /**< Notify callback?               */ 
    201202    pjsip_role_e          role;         /**< UAC=subscriber, UAS=notifier   */ 
    202203    pjsip_evsub_state     state;        /**< Subscription state.            */ 
     
    510511                       const pj_str_t *state_str, pjsip_event *event) 
    511512{ 
     513    pjsip_evsub_state prev_state = sub->state; 
    512514    pj_str_t old_state_str = sub->state_str; 
    513515 
     
    526528              sub->state_str.ptr)); 
    527529 
    528     if (sub->user.on_evsub_state) 
     530    if (sub->user.on_evsub_state && sub->call_cb) 
    529531        (*sub->user.on_evsub_state)(sub, event); 
    530532 
    531     if (state == PJSIP_EVSUB_STATE_TERMINATED) { 
    532          
     533    if (state == PJSIP_EVSUB_STATE_TERMINATED && 
     534        prev_state != PJSIP_EVSUB_STATE_TERMINATED)  
     535    { 
    533536        if (sub->pending_tsx == 0) { 
    534537            evsub_destroy(sub); 
     
    560563    case TIMER_TYPE_UAC_REFRESH: 
    561564        /* Time for UAC to refresh subscription */ 
    562         if (sub->user.on_client_refresh) { 
     565        if (sub->user.on_client_refresh && sub->call_cb) { 
    563566            (*sub->user.on_client_refresh)(sub); 
    564567        } else { 
     
    577580    case TIMER_TYPE_UAS_TIMEOUT: 
    578581        /* Refresh from UAC has not been received */ 
    579         if (sub->user.on_server_timeout) { 
     582        if (sub->user.on_server_timeout && sub->call_cb) { 
    580583            (*sub->user.on_server_timeout)(sub); 
    581584        } else { 
     
    653656    sub->pkg = pkg; 
    654657    sub->role = role; 
     658    sub->call_cb = PJ_TRUE; 
    655659    sub->option = option; 
    656660    sub->state = PJSIP_EVSUB_STATE_NULL; 
     
    838842} 
    839843 
     844 
     845/* 
     846 * Forcefully destroy subscription. 
     847 */ 
     848PJ_DEF(pj_status_t) pjsip_evsub_terminate( pjsip_evsub *sub, 
     849                                           pj_bool_t notify ) 
     850{ 
     851    PJ_ASSERT_RETURN(sub, PJ_EINVAL); 
     852 
     853    pjsip_dlg_inc_lock(sub->dlg); 
     854 
     855    if (sub->pending_tsx) { 
     856        pj_assert(!"Unable to terminate when there's pending tsx"); 
     857        pjsip_dlg_dec_lock(sub->dlg); 
     858        return PJ_EINVALIDOP; 
     859    } 
     860 
     861    sub->call_cb = notify; 
     862    set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL); 
     863 
     864    pjsip_dlg_dec_lock(sub->dlg); 
     865    return PJ_SUCCESS; 
     866} 
    840867 
    841868/* 
     
    16141641         * if any. 
    16151642         */ 
    1616         if (st_code==200 && sub->user.on_rx_notify) { 
     1643        if (st_code==200 && sub->user.on_rx_notify && sub->call_cb) { 
    16171644            (*sub->user.on_rx_notify)(sub, rdata, &st_code, &st_text,  
    16181645                                      &res_hdr, &body); 
     
    17821809        pj_list_init(&res_hdr); 
    17831810 
    1784         (*sub->user.on_rx_refresh)(sub, rdata, &st_code, &st_text,  
    1785                                    &res_hdr, &body); 
     1811        if (sub->user.on_rx_refresh && sub->call_cb) { 
     1812            (*sub->user.on_rx_refresh)(sub, rdata, &st_code, &st_text,  
     1813                                       &res_hdr, &body); 
     1814        } 
    17861815 
    17871816        /* Application MUST specify final response! */ 
     
    18871916 
    18881917    /* Call on_tsx_state callback, if any. */ 
    1889     if (sub->user.on_tsx_state) 
     1918    if (sub->user.on_tsx_state && sub->call_cb) 
    18901919        (*sub->user.on_tsx_state)(sub, tsx, event); 
    18911920 
  • pjproject/trunk/pjsip/src/pjsip-simple/iscomposing.c

    r268 r283  
    8181 
    8282    /* Add lastactive, if any. */ 
    83     if (!is_composing && lst_actv) { 
    84         PJ_TODO(IMPLEMENT_LAST_ACTIVE_ATTRIBUTE); 
    85     } 
     83    PJ_UNUSED_ARG(lst_actv); 
     84    //if (!is_composing && lst_actv) { 
     85    //  PJ_TODO(IMPLEMENT_LAST_ACTIVE_ATTRIBUTE); 
     86    //} 
    8687 
    8788    /* Add contenttype, if any. */ 
  • pjproject/trunk/pjsip/src/pjsip-simple/presence.c

    r268 r283  
    323323 
    324324/* 
     325 * Forcefully terminate presence. 
     326 */ 
     327PJ_DEF(pj_status_t) pjsip_pres_terminate( pjsip_evsub *sub, 
     328                                          pj_bool_t notify ) 
     329{ 
     330    return pjsip_evsub_terminate(sub, notify); 
     331} 
     332 
     333/* 
    325334 * Create SUBSCRIBE 
    326335 */ 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r267 r283  
    125125                   pjsip_event *e) 
    126126{ 
     127    pjsip_inv_state prev_state = inv->state; 
     128 
     129    /* Set state. */ 
    127130    inv->state = state; 
    128     if (mod_inv.cb.on_state_changed) 
     131 
     132    /* If state is DISCONNECTED, cause code MUST have been set. */ 
     133    pj_assert(inv->state != PJSIP_INV_STATE_DISCONNECTED || 
     134              inv->cause != 0); 
     135 
     136    /* Call on_state_changed() callback. */ 
     137    if (mod_inv.cb.on_state_changed && inv->notify) 
    129138        (*mod_inv.cb.on_state_changed)(inv, e); 
    130139 
    131     if (inv->state == PJSIP_INV_STATE_DISCONNECTED) 
     140    /* Only decrement when previous state is not already DISCONNECTED */ 
     141    if (inv->state == PJSIP_INV_STATE_DISCONNECTED && 
     142        prev_state != PJSIP_INV_STATE_DISCONNECTED)  
     143    { 
    132144        pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod); 
     145    } 
    133146} 
    134147 
     
    291304 
    292305    /* Call on_tsx_state */ 
    293     if (mod_inv.cb.on_tsx_state_changed) 
     306    if (mod_inv.cb.on_tsx_state_changed && inv->notify) 
    294307        (*mod_inv.cb.on_tsx_state_changed)(inv, tsx, e); 
    295308 
     
    379392    inv->dlg = dlg; 
    380393    inv->options = options; 
     394    inv->notify = PJ_TRUE; 
     395    inv->cause = 0; 
    381396 
    382397    /* Object name will use the same dialog pointer. */ 
     
    775790    inv->dlg = dlg; 
    776791    inv->options = options; 
     792    inv->notify = PJ_TRUE; 
     793    inv->cause = 0; 
    777794 
    778795    /* Object name will use the same dialog pointer. */ 
     
    834851} 
    835852 
     853/* 
     854 * Forcefully terminate the session. 
     855 */ 
     856PJ_DEF(pj_status_t) pjsip_inv_terminate( pjsip_inv_session *inv, 
     857                                         int st_code, 
     858                                         pj_bool_t notify) 
     859{ 
     860    PJ_ASSERT_RETURN(inv, PJ_EINVAL); 
     861 
     862    /* Lock dialog. */ 
     863    pjsip_dlg_inc_lock(inv->dlg); 
     864 
     865    /* Set callback notify flag. */ 
     866    inv->notify = notify; 
     867 
     868    /* If there's pending transaction, terminate the transaction.  
     869     * This may subsequently set the INVITE session state to 
     870     * disconnected. 
     871     */ 
     872    if (inv->invite_tsx &&  
     873        inv->invite_tsx->state <= PJSIP_TSX_STATE_COMPLETED) 
     874    { 
     875        pjsip_tsx_terminate(inv->invite_tsx, st_code); 
     876 
     877    } 
     878 
     879    /* Set cause. */ 
     880    inv->cause = st_code; 
     881 
     882    /* Forcefully terminate the session if state is not DISCONNECTED */ 
     883    if (inv->state != PJSIP_INV_STATE_DISCONNECTED) { 
     884        inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, NULL); 
     885    } 
     886 
     887    /* Done. 
     888     * The dec_lock() below will actually destroys the dialog if it 
     889     * has no other session. 
     890     */ 
     891    pjsip_dlg_dec_lock(inv->dlg); 
     892 
     893    return PJ_SUCCESS; 
     894} 
     895 
     896 
    836897static void *clone_sdp(pj_pool_t *pool, const void *data, unsigned len) 
    837898{ 
     
    9751036    PJ_LOG(5,(inv->obj_name, "SDP negotiation done, status=%d", status)); 
    9761037 
    977     if (mod_inv.cb.on_media_update) 
     1038    if (mod_inv.cb.on_media_update && inv->notify) 
    9781039        (*mod_inv.cb.on_media_update)(inv, status); 
    9791040 
     
    10641125        /* Inform application about remote offer. */ 
    10651126 
    1066         if (mod_inv.cb.on_rx_offer) { 
     1127        if (mod_inv.cb.on_rx_offer && inv->notify) { 
    10671128 
    10681129            (*mod_inv.cb.on_rx_offer)(inv, sdp); 
     
    13051366    PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL); 
    13061367 
     1368    /* Set cause code. */ 
     1369    if (inv->cause==0) inv->cause = st_code; 
     1370 
    13071371    /* Create appropriate message. */ 
    13081372    switch (inv->state) { 
     
    13591423    case PJSIP_INV_STATE_DISCONNECTED: 
    13601424        /* No need to do anything. */ 
    1361         PJ_TODO(RETURN_A_PROPER_STATUS_CODE_HERE); 
    1362         return PJ_EINVALIDOP; 
     1425        return PJSIP_ESESSIONTERMINATED; 
    13631426 
    13641427    default: 
     
    16131676    /* Terminate session: */ 
    16141677 
    1615     if (inv->state != PJSIP_INV_STATE_DISCONNECTED) 
     1678    if (inv->state != PJSIP_INV_STATE_DISCONNECTED) { 
     1679        if (inv->cause==0) inv->cause=PJSIP_SC_OK; 
    16161680        inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     1681    } 
    16171682} 
    16181683 
     
    16281693     
    16291694    if (e->body.tsx_state.type != PJSIP_EVENT_RX_MSG) { 
     1695        if (inv->cause==0) inv->cause=PJSIP_SC_OK; 
    16301696        inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    16311697        return; 
     
    16471713             * End the session anyway. 
    16481714             */ 
     1715            if (inv->cause==0) inv->cause=PJSIP_SC_OK; 
    16491716            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    16501717             
     
    16571724 
    16581725        /* End the session. */ 
    1659  
     1726        if (inv->cause==0) inv->cause=PJSIP_SC_OK; 
    16601727        inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    16611728    } 
     
    17751842                     * End the session. 
    17761843                     */ 
     1844                    if (inv->cause==0) inv->cause = tsx->status_code; 
    17771845                    inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    17781846 
     
    17891857            } else { 
    17901858 
     1859                if (inv->cause==0) inv->cause = tsx->status_code; 
    17911860                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    17921861 
     
    18161885 
    18171886            } else  { 
     1887                if (inv->cause==0) inv->cause = tsx->status_code; 
    18181888                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    18191889            } 
     
    18381908            PJSIP_SC_TSX_TRANSPORT_ERROR) 
    18391909        { 
     1910            if (inv->cause==0) inv->cause = tsx->status_code; 
    18401911            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    18411912        } 
     
    18781949             * Transaction sent final response. 
    18791950             */ 
    1880             if (tsx->status_code/100 == 2) 
     1951            if (tsx->status_code/100 == 2) { 
    18811952                inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e); 
    1882             else 
     1953            } else { 
     1954                if (inv->cause==0) inv->cause = tsx->status_code; 
    18831955                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     1956            } 
    18841957            break; 
    18851958 
     
    18891962             * response) 
    18901963             */ 
     1964            if (inv->cause==0) inv->cause = tsx->status_code; 
    18911965            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    18921966            break; 
     
    19492023                } 
    19502024 
    1951             } else 
     2025            } else { 
     2026                if (inv->cause==0) inv->cause = tsx->status_code; 
    19522027                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     2028            } 
    19532029            break; 
    19542030 
     
    19822058 
    19832059            } else  { 
     2060                if (inv->cause==0) inv->cause = tsx->status_code; 
    19842061                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    19852062            } 
     
    20172094            PJSIP_SC_TSX_TRANSPORT_ERROR) 
    20182095        { 
     2096            if (inv->cause==0) inv->cause = tsx->status_code; 
    20192097            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    20202098        } 
     
    20502128             */ 
    20512129            if (tsx->status_code/100 != 2) { 
     2130                if (inv->cause==0) inv->cause = tsx->status_code; 
    20522131                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    20532132            } 
     
    22412320             * Handle responses that terminates dialog. 
    22422321             */ 
     2322            if (inv->cause==0) inv->cause = tsx->status_code; 
    22432323            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    22442324        } 
  • pjproject/trunk/pjsip/src/pjsip/sip_dialog.c

    r265 r283  
    614614 
    615615/* 
     616 * Forcefully terminate dialog. 
     617 */ 
     618PJ_DEF(pj_status_t) pjsip_dlg_terminate( pjsip_dialog *dlg ) 
     619{ 
     620    /* Number of sessions must be zero. */ 
     621    PJ_ASSERT_RETURN(dlg->sess_count==0, PJ_EINVALIDOP); 
     622 
     623    /* MUST not have pending transactions. */ 
     624    PJ_ASSERT_RETURN(dlg->tsx_count==0, PJ_EINVALIDOP); 
     625 
     626    return unregister_and_destroy_dialog(dlg); 
     627} 
     628 
     629 
     630/* 
    616631 * Set route_set 
    617632 */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_errno.c

    r197 r283  
    8383 
    8484    /* UA/dialog layer. */ 
    85     { PJSIP_EMISSINGTAG,        "Missing From/To tag parameter" } 
     85    { PJSIP_EMISSINGTAG,        "Missing From/To tag parameter" }, 
     86    { PJSIP_ENOTREFER,          "Expecting REFER request"} , 
     87    { PJSIP_ENOREFERSESSION,    "Not associated with REFER subscription"}, 
     88 
     89    /* Invite session. */ 
     90    { PJSIP_ESESSIONTERMINATED, "Session already terminated" }, 
    8691}; 
    8792 
Note: See TracChangeset for help on using the changeset viewer.