Ignore:
Timestamp:
Aug 15, 2006 8:26:34 PM (18 years ago)
Author:
bennylp
Message:

Support for PUBLISH (RFC 3903):

  • API BREAK: pjsua_pres_create_uac() API CHANGED!! Added options in the function, to allow creating SUBSCRIBE without ";id=" parameter in the Event header.
  • the generic event publication in pjsip-simple/publish.[hc]
  • split PIDF and X-PIDF body generation and parsing into pjsip-simple/presence_body.c.
  • allow NULL in module parameter in pjsip_endpt_add_capability()
  • added "--publish" option in PJSUA.
  • by default, PJSUA-LIB will not add ";id=" parameter in Event header in the SUBSCRIBE request since lots of server and user agents don't support this correctly.
  • Set version to 0.5.7.6.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip-simple/publishc.c

    r683 r685  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1818 */ 
    19 #include <pjsip-ua/sip_regc.h> 
     19#include <pjsip-simple/publish.h> 
     20#include <pjsip/sip_auth.h> 
    2021#include <pjsip/sip_endpoint.h> 
    21 #include <pjsip/sip_parser.h> 
    22 #include <pjsip/sip_module.h> 
     22#include <pjsip/sip_errno.h> 
     23#include <pjsip/sip_event.h> 
     24#include <pjsip/sip_msg.h> 
    2325#include <pjsip/sip_transaction.h> 
    24 #include <pjsip/sip_event.h> 
     26#include <pjsip/sip_uri.h> 
    2527#include <pjsip/sip_util.h> 
    26 #include <pjsip/sip_auth_msg.h> 
    27 #include <pjsip/sip_errno.h> 
    2828#include <pj/assert.h> 
    2929#include <pj/guid.h> 
     30#include <pj/log.h> 
    3031#include <pj/os.h> 
    3132#include <pj/pool.h> 
    32 #include <pj/log.h> 
    3333#include <pj/rand.h> 
    3434#include <pj/string.h> 
     35#include <pj/timer.h> 
    3536 
    3637 
    3738#define REFRESH_TIMER           1 
    3839#define DELAY_BEFORE_REFRESH    5 
    39 #define THIS_FILE               "sip_regc.c" 
     40#define THIS_FILE               "publishc.c" 
     41 
     42 
     43const pjsip_method pjsip_publish_method =  
     44{ 
     45    PJSIP_OTHER_METHOD, 
     46    { "PUBLISH", 7 } 
     47}; 
     48 
    4049 
    4150/** 
    42  * SIP client registration structure. 
     51 * SIP client publication structure. 
    4352 */ 
    44 struct pjsip_regc 
     53struct pjsip_publishc 
    4554{ 
    4655    pj_pool_t                   *pool; 
     
    5059 
    5160    void                        *token; 
    52     pjsip_regc_cb               *cb; 
    53  
    54     pj_str_t                     str_srv_url; 
    55     pjsip_uri                   *srv_url; 
     61    pjsip_publishc_cb           *cb; 
     62 
     63    pj_str_t                     event; 
     64    pj_str_t                     str_target_uri; 
     65    pjsip_uri                   *target_uri; 
    5666    pjsip_cid_hdr               *cid_hdr; 
    5767    pjsip_cseq_hdr              *cseq_hdr; 
     
    5969    pjsip_from_hdr              *from_hdr; 
    6070    pjsip_to_hdr                *to_hdr; 
    61     char                        *contact_buf; 
    62     pjsip_generic_string_hdr    *contact_hdr; 
     71    pj_str_t                     etag; 
    6372    pjsip_expires_hdr           *expires_hdr; 
    64     pjsip_contact_hdr           *unreg_contact_hdr; 
    65     pjsip_expires_hdr           *unreg_expires_hdr; 
    6673    pj_uint32_t                  expires; 
    6774    pjsip_route_hdr              route_set; 
     
    7077    pjsip_auth_clt_sess          auth_sess; 
    7178 
    72     /* Auto refresh registration. */ 
    73     pj_bool_t                    auto_reg; 
    74     pj_time_val                  last_reg; 
    75     pj_time_val                  next_reg; 
     79    /* Auto refresh publication. */ 
     80    pj_bool_t                    auto_refresh; 
     81    pj_time_val                  last_refresh; 
     82    pj_time_val                  next_refresh; 
    7683    pj_timer_entry               timer; 
    7784}; 
     
    7986 
    8087 
    81 PJ_DEF(pj_status_t) pjsip_regc_create( pjsip_endpoint *endpt, void *token, 
    82                                        pjsip_regc_cb *cb, 
    83                                        pjsip_regc **p_regc) 
     88/* 
     89 * Initialize client publication module. 
     90 */ 
     91PJ_DEF(pj_status_t) pjsip_publishc_init_module(pjsip_endpoint *endpt) 
     92{ 
     93    return pjsip_endpt_add_capability( endpt, NULL, PJSIP_H_ALLOW, NULL, 
     94                                       1, &pjsip_publish_method.name); 
     95} 
     96 
     97 
     98PJ_DEF(pj_status_t) pjsip_publishc_create( pjsip_endpoint *endpt,  
     99                                           unsigned options, 
     100                                           void *token, 
     101                                           pjsip_publishc_cb *cb,        
     102                                           pjsip_publishc **p_pubc) 
    84103{ 
    85104    pj_pool_t *pool; 
    86     pjsip_regc *regc; 
     105    pjsip_publishc *pubc; 
    87106    pj_status_t status; 
    88107 
    89108    /* Verify arguments. */ 
    90     PJ_ASSERT_RETURN(endpt && cb && p_regc, PJ_EINVAL); 
    91  
    92     pool = pjsip_endpt_create_pool(endpt, "regc%p", 1024, 1024); 
     109    PJ_ASSERT_RETURN(endpt && cb && p_pubc, PJ_EINVAL); 
     110    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); 
     111 
     112    PJ_UNUSED_ARG(options); 
     113 
     114    pool = pjsip_endpt_create_pool(endpt, "pubc%p", 1024, 1024); 
    93115    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); 
    94116 
    95     regc = pj_pool_zalloc(pool, sizeof(struct pjsip_regc)); 
    96  
    97     regc->pool = pool; 
    98     regc->endpt = endpt; 
    99     regc->token = token; 
    100     regc->cb = cb; 
    101     regc->contact_buf = pj_pool_alloc(pool, PJSIP_REGC_CONTACT_BUF_SIZE); 
    102     regc->expires = PJSIP_REGC_EXPIRATION_NOT_SPECIFIED; 
    103  
    104     status = pjsip_auth_clt_init(&regc->auth_sess, endpt, regc->pool, 0); 
     117    pubc = pj_pool_zalloc(pool, sizeof(struct pjsip_publishc)); 
     118 
     119    pubc->pool = pool; 
     120    pubc->endpt = endpt; 
     121    pubc->token = token; 
     122    pubc->cb = cb; 
     123    pubc->expires = PJSIP_PUBC_EXPIRATION_NOT_SPECIFIED; 
     124 
     125    status = pjsip_auth_clt_init(&pubc->auth_sess, endpt, pubc->pool, 0); 
    105126    if (status != PJ_SUCCESS) 
    106127        return status; 
    107128 
    108     pj_list_init(&regc->route_set); 
     129    pj_list_init(&pubc->route_set); 
    109130 
    110131    /* Done */ 
    111     *p_regc = regc; 
    112     return PJ_SUCCESS; 
    113 } 
    114  
    115  
    116 PJ_DEF(pj_status_t) pjsip_regc_destroy(pjsip_regc *regc) 
    117 { 
    118     PJ_ASSERT_RETURN(regc, PJ_EINVAL); 
    119  
    120     if (regc->pending_tsx) { 
    121         regc->_delete_flag = 1; 
    122         regc->cb = NULL; 
     132    *p_pubc = pubc; 
     133    return PJ_SUCCESS; 
     134} 
     135 
     136 
     137PJ_DEF(pj_status_t) pjsip_publishc_destroy(pjsip_publishc *pubc) 
     138{ 
     139    PJ_ASSERT_RETURN(pubc, PJ_EINVAL); 
     140 
     141    if (pubc->pending_tsx) { 
     142        pubc->_delete_flag = 1; 
     143        pubc->cb = NULL; 
    123144    } else { 
    124         pjsip_endpt_release_pool(regc->endpt, regc->pool); 
    125     } 
    126  
    127     return PJ_SUCCESS; 
    128 } 
    129  
    130  
    131 PJ_DEF(pj_status_t) pjsip_regc_get_info( pjsip_regc *regc, 
    132                                          pjsip_regc_info *info ) 
    133 { 
    134     PJ_ASSERT_RETURN(regc && info, PJ_EINVAL); 
    135  
    136     info->server_uri = regc->str_srv_url; 
    137     info->client_uri = regc->from_uri; 
    138     info->is_busy = (regc->pending_tsx != 0); 
    139     info->auto_reg = regc->auto_reg; 
    140     info->interval = regc->expires; 
    141      
    142     if (regc->pending_tsx) 
    143         info->next_reg = 0; 
    144     else if (regc->auto_reg == 0) 
    145         info->next_reg = 0; 
    146     else if (regc->expires < 0) 
    147         info->next_reg = regc->expires; 
    148     else { 
    149         pj_time_val now, next_reg; 
    150  
    151         next_reg = regc->next_reg; 
    152         pj_gettimeofday(&now); 
    153         PJ_TIME_VAL_SUB(next_reg, now); 
    154         info->next_reg = next_reg.sec; 
    155     } 
    156  
    157     return PJ_SUCCESS; 
    158 } 
    159  
    160  
    161 PJ_DEF(pj_pool_t*) pjsip_regc_get_pool(pjsip_regc *regc) 
    162 { 
    163     return regc->pool; 
    164 } 
    165  
    166 static void set_expires( pjsip_regc *regc, pj_uint32_t expires) 
    167 { 
    168     if (expires != regc->expires) { 
    169         regc->expires_hdr = pjsip_expires_hdr_create(regc->pool, expires); 
     145        pjsip_endpt_release_pool(pubc->endpt, pubc->pool); 
     146    } 
     147 
     148    return PJ_SUCCESS; 
     149} 
     150 
     151 
     152PJ_DEF(pj_pool_t*) pjsip_publishc_get_pool(pjsip_publishc *pubc) 
     153{ 
     154    return pubc->pool; 
     155} 
     156 
     157static void set_expires( pjsip_publishc *pubc, pj_uint32_t expires) 
     158{ 
     159    if (expires != pubc->expires) { 
     160        pubc->expires_hdr = pjsip_expires_hdr_create(pubc->pool, expires); 
    170161    } else { 
    171         regc->expires_hdr = NULL; 
    172     } 
    173 } 
    174  
    175  
    176 static pj_status_t set_contact( pjsip_regc *regc, 
    177                                 int contact_cnt, 
    178                                 const pj_str_t contact[] ) 
    179 { 
    180     int i; 
    181     char *s; 
    182     const pj_str_t contact_STR = { "Contact", 7}; 
    183  
    184     /* Concatenate contacts. */ 
    185     for (i=0, s=regc->contact_buf; i<contact_cnt; ++i) { 
    186         if ((s-regc->contact_buf) + contact[i].slen + 2 > PJSIP_REGC_CONTACT_BUF_SIZE) { 
    187             return PJSIP_EURITOOLONG; 
    188         } 
    189         pj_memcpy(s, contact[i].ptr, contact[i].slen); 
    190         s += contact[i].slen; 
    191  
    192         if (i != contact_cnt - 1) { 
    193             *s++ = ','; 
    194             *s++ = ' '; 
    195         } 
    196     } 
    197  
    198     /* Set "Contact" header. */ 
    199     regc->contact_hdr = pjsip_generic_string_hdr_create(regc->pool,  
    200                                                         &contact_STR, 
    201                                                         NULL); 
    202     regc->contact_hdr->hvalue.ptr = regc->contact_buf; 
    203     regc->contact_hdr->hvalue.slen = (s - regc->contact_buf); 
    204  
    205     return PJ_SUCCESS; 
    206 } 
    207  
    208  
    209 PJ_DEF(pj_status_t) pjsip_regc_init( pjsip_regc *regc, 
    210                                      const pj_str_t *srv_url, 
    211                                      const pj_str_t *from_url, 
    212                                      const pj_str_t *to_url, 
    213                                      int contact_cnt, 
    214                                      const pj_str_t contact[], 
    215                                      pj_uint32_t expires) 
     162        pubc->expires_hdr = NULL; 
     163    } 
     164} 
     165 
     166 
     167PJ_DEF(pj_status_t) pjsip_publishc_init(pjsip_publishc *pubc, 
     168                                        const pj_str_t *event, 
     169                                        const pj_str_t *target_uri, 
     170                                        const pj_str_t *from_uri, 
     171                                        const pj_str_t *to_uri, 
     172                                        pj_uint32_t expires) 
    216173{ 
    217174    pj_str_t tmp; 
    218     pj_status_t status; 
    219  
    220     PJ_ASSERT_RETURN(regc && srv_url && from_url && to_url &&  
    221                      contact_cnt && contact && expires, PJ_EINVAL); 
     175 
     176    PJ_ASSERT_RETURN(pubc && event && target_uri && from_uri && to_uri &&  
     177                     expires, PJ_EINVAL); 
     178 
     179    /* Copy event type */ 
     180    pj_strdup_with_null(pubc->pool, &pubc->event, event); 
    222181 
    223182    /* Copy server URL. */ 
    224     pj_strdup_with_null(regc->pool, &regc->str_srv_url, srv_url); 
     183    pj_strdup_with_null(pubc->pool, &pubc->str_target_uri, target_uri); 
    225184 
    226185    /* Set server URL. */ 
    227     tmp = regc->str_srv_url; 
    228     regc->srv_url = pjsip_parse_uri( regc->pool, tmp.ptr, tmp.slen, 0); 
    229     if (regc->srv_url == NULL) { 
     186    tmp = pubc->str_target_uri; 
     187    pubc->target_uri = pjsip_parse_uri( pubc->pool, tmp.ptr, tmp.slen, 0); 
     188    if (pubc->target_uri == NULL) { 
    230189        return PJSIP_EINVALIDURI; 
    231190    } 
    232191 
    233192    /* Set "From" header. */ 
    234     pj_strdup_with_null(regc->pool, &regc->from_uri, from_url); 
    235     tmp = regc->from_uri; 
    236     regc->from_hdr = pjsip_from_hdr_create(regc->pool); 
    237     regc->from_hdr->uri = pjsip_parse_uri(regc->pool, tmp.ptr, tmp.slen,  
     193    pj_strdup_with_null(pubc->pool, &pubc->from_uri, from_uri); 
     194    tmp = pubc->from_uri; 
     195    pubc->from_hdr = pjsip_from_hdr_create(pubc->pool); 
     196    pubc->from_hdr->uri = pjsip_parse_uri(pubc->pool, tmp.ptr, tmp.slen,  
    238197                                          PJSIP_PARSE_URI_AS_NAMEADDR); 
    239     if (!regc->from_hdr->uri) { 
    240         PJ_LOG(4,(THIS_FILE, "regc: invalid source URI %.*s",  
    241                   from_url->slen, from_url->ptr)); 
     198    if (!pubc->from_hdr->uri) { 
    242199        return PJSIP_EINVALIDURI; 
    243200    } 
    244201 
    245202    /* Set "To" header. */ 
    246     pj_strdup_with_null(regc->pool, &tmp, to_url); 
    247     regc->to_hdr = pjsip_to_hdr_create(regc->pool); 
    248     regc->to_hdr->uri = pjsip_parse_uri(regc->pool, tmp.ptr, tmp.slen,  
     203    pj_strdup_with_null(pubc->pool, &tmp, to_uri); 
     204    pubc->to_hdr = pjsip_to_hdr_create(pubc->pool); 
     205    pubc->to_hdr->uri = pjsip_parse_uri(pubc->pool, tmp.ptr, tmp.slen,  
    249206                                        PJSIP_PARSE_URI_AS_NAMEADDR); 
    250     if (!regc->to_hdr->uri) { 
    251         PJ_LOG(4,(THIS_FILE, "regc: invalid target URI %.*s", to_url->slen, to_url->ptr)); 
     207    if (!pubc->to_hdr->uri) { 
    252208        return PJSIP_EINVALIDURI; 
    253209    } 
    254210 
    255211 
    256     /* Set "Contact" header. */ 
    257     status = set_contact( regc, contact_cnt, contact); 
    258     if (status != PJ_SUCCESS) 
    259         return status; 
    260  
    261212    /* Set "Expires" header, if required. */ 
    262     set_expires( regc, expires); 
     213    set_expires( pubc, expires); 
    263214 
    264215    /* Set "Call-ID" header. */ 
    265     regc->cid_hdr = pjsip_cid_hdr_create(regc->pool); 
    266     pj_create_unique_string(regc->pool, &regc->cid_hdr->id); 
     216    pubc->cid_hdr = pjsip_cid_hdr_create(pubc->pool); 
     217    pj_create_unique_string(pubc->pool, &pubc->cid_hdr->id); 
    267218 
    268219    /* Set "CSeq" header. */ 
    269     regc->cseq_hdr = pjsip_cseq_hdr_create(regc->pool); 
    270     regc->cseq_hdr->cseq = pj_rand() % 0xFFFF; 
    271     pjsip_method_set( &regc->cseq_hdr->method, PJSIP_REGISTER_METHOD); 
    272  
    273     /* Create "Contact" header used in unregistration. */ 
    274     regc->unreg_contact_hdr = pjsip_contact_hdr_create(regc->pool); 
    275     regc->unreg_contact_hdr->star = 1; 
    276  
    277     /* Create "Expires" header used in unregistration. */ 
    278     regc->unreg_expires_hdr = pjsip_expires_hdr_create( regc->pool, 0); 
     220    pubc->cseq_hdr = pjsip_cseq_hdr_create(pubc->pool); 
     221    pubc->cseq_hdr->cseq = pj_rand() % 0xFFFF; 
     222    pjsip_method_set( &pubc->cseq_hdr->method, PJSIP_REGISTER_METHOD); 
    279223 
    280224    /* Done. */ 
     
    282226} 
    283227 
    284 PJ_DEF(pj_status_t) pjsip_regc_set_credentials( pjsip_regc *regc, 
     228PJ_DEF(pj_status_t) pjsip_publishc_set_credentials( pjsip_publishc *pubc, 
    285229                                                int count, 
    286230                                                const pjsip_cred_info cred[] ) 
    287231{ 
    288     PJ_ASSERT_RETURN(regc && count && cred, PJ_EINVAL); 
    289     return pjsip_auth_clt_set_credentials(&regc->auth_sess, count, cred); 
    290 } 
    291  
    292 PJ_DEF(pj_status_t) pjsip_regc_set_route_set( pjsip_regc *regc, 
     232    PJ_ASSERT_RETURN(pubc && count && cred, PJ_EINVAL); 
     233    return pjsip_auth_clt_set_credentials(&pubc->auth_sess, count, cred); 
     234} 
     235 
     236PJ_DEF(pj_status_t) pjsip_publishc_set_route_set( pjsip_publishc *pubc, 
    293237                                              const pjsip_route_hdr *route_set) 
    294238{ 
    295239    const pjsip_route_hdr *chdr; 
    296240 
    297     PJ_ASSERT_RETURN(regc && route_set, PJ_EINVAL); 
    298  
    299     pj_list_init(&regc->route_set); 
     241    PJ_ASSERT_RETURN(pubc && route_set, PJ_EINVAL); 
     242 
     243    pj_list_init(&pubc->route_set); 
    300244 
    301245    chdr = route_set->next; 
    302246    while (chdr != route_set) { 
    303         pj_list_push_back(&regc->route_set, pjsip_hdr_clone(regc->pool, chdr)); 
     247        pj_list_push_back(&pubc->route_set, pjsip_hdr_clone(pubc->pool, chdr)); 
    304248        chdr = chdr->next; 
    305249    } 
     
    308252} 
    309253 
    310 static pj_status_t create_request(pjsip_regc *regc,  
     254static pj_status_t create_request(pjsip_publishc *pubc,  
    311255                                  pjsip_tx_data **p_tdata) 
    312256{ 
    313     pj_status_t status; 
     257    const pj_str_t STR_EVENT = { "Event", 5 }; 
     258    pj_status_t status; 
     259    pjsip_generic_string_hdr *hdr; 
    314260    pjsip_tx_data *tdata; 
    315261 
    316     PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL); 
     262    PJ_ASSERT_RETURN(pubc && p_tdata, PJ_EINVAL); 
    317263 
    318264    /* Create the request. */ 
    319     status = pjsip_endpt_create_request_from_hdr( regc->endpt,  
    320                                                   &pjsip_register_method, 
    321                                                   regc->srv_url, 
    322                                                   regc->from_hdr, 
    323                                                   regc->to_hdr, 
     265    status = pjsip_endpt_create_request_from_hdr( pubc->endpt,  
     266                                                  &pjsip_publish_method, 
     267                                                  pubc->target_uri, 
     268                                                  pubc->from_hdr, 
     269                                                  pubc->to_hdr, 
    324270                                                  NULL, 
    325                                                   regc->cid_hdr, 
    326                                                   regc->cseq_hdr->cseq, 
     271                                                  pubc->cid_hdr, 
     272                                                  pubc->cseq_hdr->cseq, 
    327273                                                  NULL, 
    328274                                                  &tdata); 
     
    331277 
    332278    /* Add cached authorization headers. */ 
    333     pjsip_auth_clt_init_req( &regc->auth_sess, tdata ); 
     279    pjsip_auth_clt_init_req( &pubc->auth_sess, tdata ); 
    334280 
    335281    /* Add Route headers from route set, ideally after Via header */ 
    336     if (!pj_list_empty(&regc->route_set)) { 
     282    if (!pj_list_empty(&pubc->route_set)) { 
    337283        pjsip_hdr *route_pos; 
    338284        const pjsip_route_hdr *route; 
     
    342288            route_pos = &tdata->msg->hdr; 
    343289 
    344         route = regc->route_set.next; 
    345         while (route != &regc->route_set) { 
     290        route = pubc->route_set.next; 
     291        while (route != &pubc->route_set) { 
    346292            pjsip_hdr *new_hdr = pjsip_hdr_shallow_clone(tdata->pool, route); 
    347293            pj_list_insert_after(route_pos, new_hdr); 
     
    351297    } 
    352298 
     299    /* Add Event header */ 
     300    hdr = pjsip_generic_string_hdr_create(tdata->pool, &STR_EVENT, 
     301                                          &pubc->event); 
     302    if (hdr) 
     303        pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hdr); 
     304 
     305 
     306    /* Add SIP-If-Match if we have etag */ 
     307    if (pubc->etag.slen) { 
     308        const pj_str_t STR_HNAME = { "SIP-If-Match", 12 }; 
     309 
     310        hdr = pjsip_generic_string_hdr_create(tdata->pool, &STR_HNAME, 
     311                                              &pubc->etag); 
     312        if (hdr) 
     313            pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hdr); 
     314    } 
     315 
     316 
    353317    /* Done. */ 
    354318    *p_tdata = tdata; 
     
    357321 
    358322 
    359 PJ_DEF(pj_status_t) pjsip_regc_register(pjsip_regc *regc, pj_bool_t autoreg, 
    360                                         pjsip_tx_data **p_tdata) 
    361 { 
    362     pjsip_msg *msg; 
     323PJ_DEF(pj_status_t) pjsip_publishc_publish(pjsip_publishc *pubc,  
     324                                           pj_bool_t auto_refresh, 
     325                                           pjsip_tx_data **p_tdata) 
     326{ 
    363327    pj_status_t status; 
    364328    pjsip_tx_data *tdata; 
    365329 
    366     PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL); 
    367  
    368     status = create_request(regc, &tdata); 
     330    PJ_ASSERT_RETURN(pubc && p_tdata, PJ_EINVAL); 
     331 
     332    status = create_request(pubc, &tdata); 
    369333    if (status != PJ_SUCCESS) 
    370334        return status; 
    371335 
    372     /* Add Contact header. */ 
    373     msg = tdata->msg; 
    374     pjsip_msg_add_hdr(msg, (pjsip_hdr*) regc->contact_hdr); 
    375     if (regc->expires_hdr) 
    376         pjsip_msg_add_hdr(msg, (pjsip_hdr*) regc->expires_hdr); 
    377  
    378     if (regc->timer.id != 0) { 
    379         pjsip_endpt_cancel_timer(regc->endpt, &regc->timer); 
    380         regc->timer.id = 0; 
    381     } 
    382  
    383     regc->auto_reg = autoreg; 
     336    /* Add Expires header */ 
     337    if (pubc->expires_hdr) { 
     338        pjsip_hdr *dup; 
     339 
     340        dup = pjsip_hdr_shallow_clone(tdata->pool, pubc->expires_hdr); 
     341        if (dup) 
     342            pjsip_msg_add_hdr(tdata->msg, dup); 
     343    } 
     344 
     345    /* Cancel existing timer */ 
     346    if (pubc->timer.id != 0) { 
     347        pjsip_endpt_cancel_timer(pubc->endpt, &pubc->timer); 
     348        pubc->timer.id = 0; 
     349    } 
     350 
     351    pubc->auto_refresh = auto_refresh; 
    384352 
    385353    /* Done */ 
     
    389357 
    390358 
    391 PJ_DEF(pj_status_t) pjsip_regc_unregister(pjsip_regc *regc, 
    392                                           pjsip_tx_data **p_tdata) 
     359PJ_DEF(pj_status_t) pjsip_publishc_unpublish(pjsip_publishc *pubc, 
     360                                             pjsip_tx_data **p_tdata) 
    393361{ 
    394362    pjsip_tx_data *tdata; 
    395363    pjsip_msg *msg; 
    396     pj_status_t status; 
    397  
    398     PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL); 
    399  
    400     if (regc->timer.id != 0) { 
    401         pjsip_endpt_cancel_timer(regc->endpt, &regc->timer); 
    402         regc->timer.id = 0; 
    403     } 
    404  
    405     status = create_request(regc, &tdata); 
     364    pjsip_expires_hdr *expires; 
     365    pj_status_t status; 
     366 
     367    PJ_ASSERT_RETURN(pubc && p_tdata, PJ_EINVAL); 
     368 
     369    if (pubc->timer.id != 0) { 
     370        pjsip_endpt_cancel_timer(pubc->endpt, &pubc->timer); 
     371        pubc->timer.id = 0; 
     372    } 
     373 
     374    status = create_request(pubc, &tdata); 
    406375    if (status != PJ_SUCCESS) 
    407376        return status; 
    408377 
    409378    msg = tdata->msg; 
    410     pjsip_msg_add_hdr( msg, (pjsip_hdr*)regc->unreg_contact_hdr); 
    411     pjsip_msg_add_hdr( msg, (pjsip_hdr*)regc->unreg_expires_hdr); 
     379 
     380    /* Add Expires:0 header */ 
     381    expires = pjsip_expires_hdr_create(tdata->pool, 0); 
     382    pjsip_msg_add_hdr( msg, (pjsip_hdr*)expires); 
    412383 
    413384    *p_tdata = tdata; 
     
    416387 
    417388 
    418 PJ_DEF(pj_status_t) pjsip_regc_update_contact(  pjsip_regc *regc, 
    419                                                 int contact_cnt, 
    420                                                 const pj_str_t contact[] ) 
    421 { 
    422     PJ_ASSERT_RETURN(regc, PJ_EINVAL); 
    423     return set_contact( regc, contact_cnt, contact ); 
    424 } 
    425  
    426  
    427 PJ_DEF(pj_status_t) pjsip_regc_update_expires(  pjsip_regc *regc, 
    428                                                 pj_uint32_t expires ) 
    429 { 
    430     PJ_ASSERT_RETURN(regc, PJ_EINVAL); 
    431     set_expires( regc, expires ); 
    432     return PJ_SUCCESS; 
    433 } 
    434  
    435  
    436 static void call_callback(pjsip_regc *regc, pj_status_t status, int st_code,  
    437                           const pj_str_t *reason, 
    438                           pjsip_rx_data *rdata, pj_int32_t expiration, 
    439                           int contact_cnt, pjsip_contact_hdr *contact[]) 
    440 { 
    441     struct pjsip_regc_cbparam cbparam; 
    442  
    443  
    444     cbparam.regc = regc; 
    445     cbparam.token = regc->token; 
     389PJ_DEF(pj_status_t) pjsip_publishc_update_expires( pjsip_publishc *pubc, 
     390                                                   pj_uint32_t expires ) 
     391{ 
     392    PJ_ASSERT_RETURN(pubc, PJ_EINVAL); 
     393    set_expires( pubc, expires ); 
     394    return PJ_SUCCESS; 
     395} 
     396 
     397 
     398static void call_callback(pjsip_publishc *pubc, pj_status_t status,  
     399                          int st_code, const pj_str_t *reason, 
     400                          pjsip_rx_data *rdata, pj_int32_t expiration) 
     401{ 
     402    struct pjsip_publishc_cbparam cbparam; 
     403 
     404 
     405    cbparam.pubc = pubc; 
     406    cbparam.token = pubc->token; 
    446407    cbparam.status = status; 
    447408    cbparam.code = st_code; 
    448409    cbparam.reason = *reason; 
    449410    cbparam.rdata = rdata; 
    450     cbparam.contact_cnt = contact_cnt; 
    451411    cbparam.expiration = expiration; 
    452     if (contact_cnt) { 
    453         pj_memcpy( cbparam.contact, contact,  
    454                    contact_cnt*sizeof(pjsip_contact_hdr*)); 
    455     } 
    456  
    457     (*regc->cb)(&cbparam); 
    458 } 
    459  
    460 static void regc_refresh_timer_cb( pj_timer_heap_t *timer_heap, 
     412 
     413    (*pubc->cb)(&cbparam); 
     414} 
     415 
     416static void pubc_refresh_timer_cb( pj_timer_heap_t *timer_heap, 
    461417                                   struct pj_timer_entry *entry) 
    462418{ 
    463     pjsip_regc *regc = entry->user_data; 
     419    pjsip_publishc *pubc = entry->user_data; 
    464420    pjsip_tx_data *tdata; 
    465421    pj_status_t status; 
     
    468424 
    469425    entry->id = 0; 
    470     status = pjsip_regc_register(regc, 1, &tdata); 
     426    status = pjsip_publishc_publish(pubc, 1, &tdata); 
    471427    if (status == PJ_SUCCESS) { 
    472         status = pjsip_regc_send(regc, tdata); 
     428        status = pjsip_publishc_send(pubc, tdata); 
    473429    }  
    474430     
     
    476432        char errmsg[PJ_ERR_MSG_SIZE]; 
    477433        pj_str_t reason = pj_strerror(status, errmsg, sizeof(errmsg)); 
    478         call_callback(regc, status, 400, &reason, NULL, -1, 0, NULL); 
     434        call_callback(pubc, status, 400, &reason, NULL, -1); 
    479435    } 
    480436} 
     
    483439{ 
    484440    pj_status_t status; 
    485     pjsip_regc *regc = token; 
     441    pjsip_publishc *pubc = token; 
    486442    pjsip_transaction *tsx = event->body.tsx_state.tsx; 
    487443     
    488444    /* Decrement pending transaction counter. */ 
    489     pj_assert(regc->pending_tsx > 0); 
    490     --regc->pending_tsx; 
    491  
    492     /* If registration data has been deleted by user then remove registration  
     445    pj_assert(pubc->pending_tsx > 0); 
     446    --pubc->pending_tsx; 
     447 
     448    /* If publication data has been deleted by user then remove publication  
    493449     * data from transaction's callback, and don't call callback. 
    494450     */ 
    495     if (regc->_delete_flag) { 
     451    if (pubc->_delete_flag) { 
    496452 
    497453        /* Nothing to do */ 
     
    504460        pjsip_tx_data *tdata; 
    505461 
    506         status = pjsip_auth_clt_reinit_req( &regc->auth_sess, 
     462        status = pjsip_auth_clt_reinit_req( &pubc->auth_sess, 
    507463                                            rdata,  
    508464                                            tsx->last_tx,   
     
    510466 
    511467        if (status == PJ_SUCCESS) { 
    512             status = pjsip_regc_send(regc, tdata); 
     468            status = pjsip_publishc_send(pubc, tdata); 
    513469        }  
    514470         
    515471        if (status != PJ_SUCCESS) { 
    516             call_callback(regc, status, tsx->status_code,  
     472            call_callback(pubc, status, tsx->status_code,  
    517473                          &rdata->msg_info.msg->line.status.reason, 
    518                           rdata, -1, 0, NULL); 
     474                          rdata, -1); 
    519475        } 
    520476 
     
    522478 
    523479    } else { 
    524         int contact_cnt = 0; 
    525         pjsip_contact_hdr *contact[PJSIP_REGC_MAX_CONTACT]; 
    526480        pjsip_rx_data *rdata; 
    527481        pj_int32_t expiration = 0xFFFF; 
    528482 
    529483        if (tsx->status_code/100 == 2) { 
    530             int i; 
    531             pjsip_contact_hdr *hdr; 
    532484            pjsip_msg *msg; 
    533485            pjsip_expires_hdr *expires; 
     486            pjsip_generic_string_hdr *etag_hdr; 
     487            const pj_str_t STR_ETAG = { "SIP-ETag", 8 }; 
    534488 
    535489            rdata = event->body.tsx_state.src.rdata; 
    536490            msg = rdata->msg_info.msg; 
    537             hdr = pjsip_msg_find_hdr( msg, PJSIP_H_CONTACT, NULL); 
    538             while (hdr) { 
    539                 contact[contact_cnt++] = hdr; 
    540                 hdr = hdr->next; 
    541                 if (hdr == (void*)&msg->hdr) 
    542                     break; 
    543                 hdr = pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, hdr); 
     491 
     492            /* Save ETag value */ 
     493            etag_hdr = (pjsip_generic_string_hdr*) 
     494                       pjsip_msg_find_hdr_by_name(msg, &STR_ETAG, NULL); 
     495            if (etag_hdr) { 
     496                pj_strdup(pubc->pool, &pubc->etag, &etag_hdr->hvalue); 
     497            } else { 
     498                pubc->etag.slen = 0; 
    544499            } 
    545500 
     501            /* Update expires value */ 
    546502            expires = pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL); 
    547503 
     
    549505                expiration = expires->ivalue; 
    550506             
    551             for (i=0; i<contact_cnt; ++i) { 
    552                 hdr = contact[i]; 
    553                 if (hdr->expires >= 0 && hdr->expires < expiration) 
    554                     expiration = contact[i]->expires; 
    555             } 
    556  
    557             if (regc->auto_reg && expiration != 0 && expiration != 0xFFFF) { 
     507            if (pubc->auto_refresh && expiration!=0 && expiration!=0xFFFF) { 
    558508                pj_time_val delay = { 0, 0}; 
    559509 
    560510                delay.sec = expiration - DELAY_BEFORE_REFRESH; 
    561                 if (regc->expires != PJSIP_REGC_EXPIRATION_NOT_SPECIFIED &&  
    562                     delay.sec > (pj_int32_t)regc->expires)  
     511                if (pubc->expires != PJSIP_PUBC_EXPIRATION_NOT_SPECIFIED &&  
     512                    delay.sec > (pj_int32_t)pubc->expires)  
    563513                { 
    564                     delay.sec = regc->expires; 
     514                    delay.sec = pubc->expires; 
    565515                } 
    566516                if (delay.sec < DELAY_BEFORE_REFRESH)  
    567517                    delay.sec = DELAY_BEFORE_REFRESH; 
    568                 regc->timer.cb = &regc_refresh_timer_cb; 
    569                 regc->timer.id = REFRESH_TIMER; 
    570                 regc->timer.user_data = regc; 
    571                 pjsip_endpt_schedule_timer( regc->endpt, &regc->timer, &delay); 
    572                 pj_gettimeofday(&regc->last_reg); 
    573                 regc->next_reg = regc->last_reg; 
    574                 regc->next_reg.sec += delay.sec; 
     518                pubc->timer.cb = &pubc_refresh_timer_cb; 
     519                pubc->timer.id = REFRESH_TIMER; 
     520                pubc->timer.user_data = pubc; 
     521                pjsip_endpt_schedule_timer( pubc->endpt, &pubc->timer, &delay); 
     522                pj_gettimeofday(&pubc->last_refresh); 
     523                pubc->next_refresh = pubc->last_refresh; 
     524                pubc->next_refresh.sec += delay.sec; 
    575525            } 
    576526 
     
    583533        /* Call callback. */ 
    584534        if (expiration == 0xFFFF) expiration = -1; 
    585         call_callback(regc, PJ_SUCCESS, tsx->status_code,  
     535        call_callback(pubc, PJ_SUCCESS, tsx->status_code,  
    586536                      (rdata ? &rdata->msg_info.msg->line.status.reason  
    587537                        : pjsip_get_status_text(tsx->status_code)), 
    588                       rdata, expiration,  
    589                       contact_cnt, contact); 
    590  
    591     } 
    592  
    593     /* Delete the record if user destroy regc during the callback. */ 
    594     if (regc->_delete_flag && regc->pending_tsx==0) { 
    595         pjsip_regc_destroy(regc); 
    596     } 
    597 } 
    598  
    599 PJ_DEF(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata) 
     538                      rdata, expiration); 
     539 
     540    } 
     541 
     542    /* Delete the record if user destroy pubc during the callback. */ 
     543    if (pubc->_delete_flag && pubc->pending_tsx==0) { 
     544        pjsip_publishc_destroy(pubc); 
     545    } 
     546} 
     547 
     548 
     549PJ_DEF(pj_status_t) pjsip_publishc_send(pjsip_publishc *pubc,  
     550                                        pjsip_tx_data *tdata) 
    600551{ 
    601552    pj_status_t status; 
     
    604555 
    605556    /* Make sure we don't have pending transaction. */ 
    606     if (regc->pending_tsx) { 
    607         PJ_LOG(4,(THIS_FILE, "Unable to send request, regc has another " 
     557    if (pubc->pending_tsx) { 
     558        PJ_LOG(4,(THIS_FILE, "Unable to send request, pubc has another " 
    608559                             "transaction pending")); 
    609560        pjsip_tx_data_dec_ref( tdata ); 
     
    615566 
    616567    /* Increment CSeq */ 
    617     cseq = ++regc->cseq_hdr->cseq; 
     568    cseq = ++pubc->cseq_hdr->cseq; 
    618569    cseq_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL); 
    619570    cseq_hdr->cseq = cseq; 
     
    622573     * may be called even before send_request() returns! 
    623574     */ 
    624     ++regc->pending_tsx; 
    625     status = pjsip_endpt_send_request(regc->endpt, tdata, -1, regc, &tsx_callback); 
     575    ++pubc->pending_tsx; 
     576    status = pjsip_endpt_send_request(pubc->endpt, tdata, -1, pubc,  
     577                                      &tsx_callback); 
    626578    if (status!=PJ_SUCCESS) { 
    627         --regc->pending_tsx; 
     579        --pubc->pending_tsx; 
    628580        PJ_LOG(4,(THIS_FILE, "Error sending request, status=%d", status)); 
    629581    } 
Note: See TracChangeset for help on using the changeset viewer.