Changeset 2940


Ignore:
Timestamp:
Oct 12, 2009 7:44:14 AM (10 years ago)
Author:
bennylp
Message:

Ticket #411: Cannot update account presence's status while previous PUBLISH is in progress (thanks Olivier Beytrison for the report)

  • enable request queueing. If PUBLISH is to be sent while another one is still in progress, queue the request and send it later when the ongoing request completes
  • this behavior is controlled by new pjsip_publishc_opt structure to control session's options
  • default behavior is to queue the request
Location:
pjproject/trunk/pjsip
Files:
6 edited

Legend:

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

    r2661 r2940  
    6565typedef struct pjsip_publishc pjsip_publishc; 
    6666 
     67 
     68/** 
     69 * Client publication options. Application should initialize this structure 
     70 * with its default values by calling #pjsip_publishc_opt_default() 
     71 */ 
     72typedef struct pjsip_publishc_opt 
     73{ 
     74    /** 
     75     * Specify whether the client publication session should queue the 
     76     * PUBLISH request should there be another PUBLISH transaction still 
     77     * pending. If this is set to false, the client will return error 
     78     * on the PUBLISH request if there is another PUBLISH transaction still 
     79     * in progress. 
     80     * 
     81     * Default: PJSIP_PUBLISHC_QUEUE_REQUEST 
     82     */ 
     83    pj_bool_t   queue_request; 
     84 
     85} pjsip_publishc_opt; 
    6786 
    6887 
     
    90109 
    91110/** 
     111 * Initialize client publication session option with default values. 
     112 * 
     113 * @param opt       The option. 
     114 */ 
     115PJ_DECL(void) pjsip_publishc_opt_default(pjsip_publishc_opt *opt); 
     116 
     117 
     118/** 
    92119 * Initialize client publication module. 
    93120 * 
     
    99126 
    100127 
    101  
    102128/** 
    103129 * Create client publication structure. 
    104130 * 
    105131 * @param endpt     Endpoint, used to allocate pool from. 
    106  * @param options   Option flags. 
     132 * @param opt       Options, or NULL to specify default options. 
    107133 * @param token     Opaque data to be associated with the client publication. 
    108134 * @param cb        Pointer to callback function to receive publication status. 
     
    112138 */ 
    113139PJ_DECL(pj_status_t) pjsip_publishc_create( pjsip_endpoint *endpt,  
    114                                             unsigned options, 
     140                                            const pjsip_publishc_opt *opt, 
    115141                                            void *token, 
    116142                                            pjsip_publishc_cb *cb,  
     
    270296 * completes. 
    271297 * 
     298 * If the session has another PUBLISH request outstanding, the behavior 
     299 * depends on whether request queueing is enabled in the session (this was 
     300 * set by setting \a queue_request field of #pjsip_publishc_opt to true 
     301 * when calling #pjsip_publishc_create(). Default is true). If request 
     302 * queueing is enabled, the request will be queued and the function will  
     303 * return PJ_EPENDING. One the outstanding request is complete, the queued 
     304 * request will be sent automatically. If request queueing is disabled, the 
     305 * function will reject the request and return PJ_EBUSY. 
     306 * 
    272307 * @param pubc      The client publication structure. 
    273308 * @param tdata     Transmit data. 
    274309 * 
    275  * @return          PJ_SUCCESS on success. 
     310 * @return          - PJ_SUCCESS on success, or  
     311 *                  - PJ_EPENDING if request is queued, or 
     312 *                  - PJ_EBUSY if request is rejected because another PUBLISH 
     313 *                    request is in progress, or 
     314 *                  - other status code to indicate the error. 
    276315 */ 
    277316PJ_DECL(pj_status_t) pjsip_publishc_send(pjsip_publishc *pubc,  
  • pjproject/trunk/pjsip/include/pjsip/sip_config.h

    r2859 r2940  
    897897 
    898898 
     899/** 
     900 * Specify whether the client publication session should queue the 
     901 * PUBLISH request should there be another PUBLISH transaction still 
     902 * pending. If this is set to false, the client will return error 
     903 * on the PUBLISH request if there is another PUBLISH transaction still 
     904 * in progress. 
     905 * 
     906 * Default: 1 (yes) 
     907 */ 
     908#ifndef PJSIP_PUBLISHC_QUEUE_REQUEST 
     909#   define PJSIP_PUBLISHC_QUEUE_REQUEST         1 
     910#endif 
     911 
     912 
    899913PJ_END_DECL 
    900914 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r2864 r2940  
    17981798 
    17991799    /** 
     1800     * Event publication options. 
     1801     */ 
     1802    pjsip_publishc_opt  publish_opt; 
     1803 
     1804    /** 
    18001805     * Authentication preference. 
    18011806     */ 
  • pjproject/trunk/pjsip/src/pjsip-simple/publishc.c

    r2939 r2940  
    5858 
    5959/** 
     60 * Pending request list. 
     61 */ 
     62typedef struct pending_publish 
     63{ 
     64    PJ_DECL_LIST_MEMBER(pjsip_tx_data); 
     65} pending_publish; 
     66 
     67 
     68/** 
    6069 * SIP client publication structure. 
    6170 */ 
     
    6675    pj_bool_t                    _delete_flag; 
    6776    int                          pending_tsx; 
    68  
     77    pj_mutex_t                  *mutex; 
     78 
     79    pjsip_publishc_opt           opt; 
    6980    void                        *token; 
    7081    pjsip_publishc_cb           *cb; 
     
    92103    pj_time_val                  next_refresh; 
    93104    pj_timer_entry               timer; 
     105 
     106    /* Pending PUBLISH request */ 
     107    pending_publish              pending_reqs; 
    94108}; 
    95109 
     110 
     111PJ_DEF(void) pjsip_publishc_opt_default(pjsip_publishc_opt *opt) 
     112{ 
     113    pj_bzero(opt, sizeof(*opt)); 
     114    opt->queue_request = PJSIP_PUBLISHC_QUEUE_REQUEST; 
     115} 
    96116 
    97117 
     
    128148 
    129149PJ_DEF(pj_status_t) pjsip_publishc_create( pjsip_endpoint *endpt,  
    130                                            unsigned options, 
     150                                           const pjsip_publishc_opt *opt, 
    131151                                           void *token, 
    132152                                           pjsip_publishc_cb *cb,        
     
    135155    pj_pool_t *pool; 
    136156    pjsip_publishc *pubc; 
     157    pjsip_publishc_opt default_opt; 
    137158    pj_status_t status; 
    138159 
    139160    /* Verify arguments. */ 
    140161    PJ_ASSERT_RETURN(endpt && cb && p_pubc, PJ_EINVAL); 
    141     PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); 
    142  
    143     PJ_UNUSED_ARG(options); 
    144162 
    145163    pool = pjsip_endpt_create_pool(endpt, "pubc%p", 1024, 1024); 
     
    154172    pubc->expires = PJSIP_PUBC_EXPIRATION_NOT_SPECIFIED; 
    155173 
     174    if (!opt) { 
     175        pjsip_publishc_opt_default(&default_opt); 
     176        opt = &default_opt; 
     177    } 
     178    pj_memcpy(&pubc->opt, opt, sizeof(*opt)); 
     179    pj_list_init(&pubc->pending_reqs); 
     180 
     181    status = pj_mutex_create_recursive(pubc->pool, "pubc%p", &pubc->mutex); 
     182    if (status != PJ_SUCCESS) { 
     183        pj_pool_release(pool); 
     184        return status; 
     185    } 
     186 
    156187    status = pjsip_auth_clt_init(&pubc->auth_sess, endpt, pubc->pool, 0); 
    157     if (status != PJ_SUCCESS) 
     188    if (status != PJ_SUCCESS) { 
     189        pj_mutex_destroy(pubc->mutex); 
     190        pj_pool_release(pool); 
    158191        return status; 
     192    } 
    159193 
    160194    pj_list_init(&pubc->route_set); 
     
    181215        } 
    182216 
     217        if (pubc->mutex) 
     218            pj_mutex_destroy(pubc->mutex); 
    183219        pjsip_endpt_release_pool(pubc->endpt, pubc->pool); 
    184220    } 
     
    576612            if (pubc->auto_refresh && expiration!=0 && expiration!=0xFFFF) { 
    577613                pj_time_val delay = { 0, 0}; 
     614 
     615                /* Cancel existing timer, if any */ 
     616                if (pubc->timer.id != 0) { 
     617                    pjsip_endpt_cancel_timer(pubc->endpt, &pubc->timer); 
     618                    pubc->timer.id = 0; 
     619                } 
    578620 
    579621                delay.sec = expiration - DELAY_BEFORE_REFRESH; 
     
    614656 
    615657        --pubc->pending_tsx; 
     658 
     659        /* If we have pending request(s), send them now */ 
     660        pj_mutex_lock(pubc->mutex); 
     661        while (!pj_list_empty(&pubc->pending_reqs)) { 
     662            pjsip_tx_data *tdata = pubc->pending_reqs.next; 
     663            pj_list_erase(tdata); 
     664            status = pjsip_publishc_send(pubc, tdata); 
     665            if (status == PJ_EPENDING) { 
     666                pj_assert(!"Not expected"); 
     667                pj_list_erase(tdata); 
     668                pjsip_tx_data_dec_ref(tdata); 
     669            } else if (status == PJ_SUCCESS) { 
     670                break; 
     671            } 
     672        } 
     673        pj_mutex_unlock(pubc->mutex); 
    616674    } 
    617675 
     
    630688    pj_uint32_t cseq; 
    631689 
     690    PJ_ASSERT_RETURN(pubc && tdata, PJ_EINVAL); 
     691 
    632692    /* Make sure we don't have pending transaction. */ 
     693    pj_mutex_lock(pubc->mutex); 
    633694    if (pubc->pending_tsx) { 
    634         PJ_LOG(4,(THIS_FILE, "Unable to send request, pubc has another " 
    635                              "transaction pending")); 
    636         pjsip_tx_data_dec_ref( tdata ); 
    637         return PJSIP_EBUSY; 
    638     } 
     695        if (pubc->opt.queue_request) { 
     696            pj_list_push_back(&pubc->pending_reqs, tdata); 
     697            pj_mutex_unlock(pubc->mutex); 
     698            PJ_LOG(4,(THIS_FILE, "Request is queued, pubc has another " 
     699                                 "transaction pending")); 
     700            return PJ_EPENDING; 
     701        } else { 
     702            pjsip_tx_data_dec_ref(tdata); 
     703            pj_mutex_unlock(pubc->mutex); 
     704            PJ_LOG(4,(THIS_FILE, "Unable to send request, pubc has another " 
     705                                 "transaction pending")); 
     706            return PJ_EBUSY; 
     707        } 
     708    } 
     709    pj_mutex_unlock(pubc->mutex); 
    639710 
    640711    /* Invalidate message buffer. */ 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r2895 r2940  
    162162 
    163163    cfg->reg_timeout = PJSUA_REG_INTERVAL; 
     164    pjsip_publishc_opt_default(&cfg->publish_opt); 
    164165    cfg->transport_id = PJSUA_INVALID_ID; 
    165166    cfg->allow_contact_rewrite = PJ_TRUE; 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c

    r2824 r2940  
    10741074    /* Send the PUBLISH request */ 
    10751075    status = pjsip_publishc_send(acc->publish_sess, tdata); 
    1076     if (status != PJ_SUCCESS) { 
     1076    if (status == PJ_EPENDING) { 
     1077        PJ_LOG(3,(THIS_FILE, "Previous request is in progress, " 
     1078                  "PUBLISH request is queued")); 
     1079    } else if (status != PJ_SUCCESS) { 
    10771080        pjsua_perror(THIS_FILE, "Error sending PUBLISH request", status); 
    10781081        goto on_error; 
     
    11031106 
    11041107        /* Create client publication */ 
    1105         status = pjsip_publishc_create(pjsua_var.endpt, 0, acc, &publish_cb, 
     1108        status = pjsip_publishc_create(pjsua_var.endpt, &acc_cfg->publish_opt,  
     1109                                       acc, &publish_cb, 
    11061110                                       &acc->publish_sess); 
    11071111        if (status != PJ_SUCCESS) { 
Note: See TracChangeset for help on using the changeset viewer.