Ignore:
Timestamp:
Jul 17, 2008 2:19:10 PM (16 years ago)
Author:
bennylp
Message:

Ticket #192: Add callback to notify application about incoming SUBSCRIBE request, and add subscription state and termination reason in buddy info

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c

    r2130 r2150  
    164164    info->monitor_pres = buddy->monitor; 
    165165 
     166    /* subscription state and termination reason */ 
     167    if (buddy->sub) { 
     168        info->sub_state = pjsip_evsub_get_state(buddy->sub); 
     169        if (info->sub_state == PJSIP_EVSUB_STATE_TERMINATED && 
     170            total < sizeof(info->buf_))  
     171        { 
     172            info->sub_term_reason.ptr = info->buf_ + total; 
     173            pj_strncpy(&info->sub_term_reason, 
     174                       pjsip_evsub_get_termination_reason(buddy->sub), 
     175                       sizeof(info->buf_) - total); 
     176            total += info->sub_term_reason.slen; 
     177        } else { 
     178            info->sub_term_reason = pj_str(""); 
     179        } 
     180    } else if (total < sizeof(info->buf_)) { 
     181        info->sub_term_reason.ptr = info->buf_ + total; 
     182        pj_strncpy(&info->sub_term_reason, &buddy->term_reason, 
     183                   sizeof(info->buf_) - total); 
     184        total += info->sub_term_reason.slen; 
     185    } else { 
     186        info->sub_term_reason = pj_str(""); 
     187    } 
     188 
    166189    PJSUA_UNLOCK(); 
    167190    return PJ_SUCCESS; 
     
    223246        buddy->pool = pjsua_pool_create(name, 512, 256); 
    224247    } 
     248 
     249    /* Init buffers for presence subscription status */ 
     250    buddy->term_reason.ptr = (char*)  
     251                             pj_pool_alloc(buddy->pool,  
     252                                           PJSUA_BUDDY_SUB_TERM_REASON_LEN); 
    225253 
    226254    /* Get name and display name for buddy */ 
     
    525553    uapres = (pjsua_srv_pres*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
    526554    if (uapres) { 
     555        pjsip_evsub_state state; 
     556 
    527557        PJ_LOG(4,(THIS_FILE, "Server subscription to %s is %s", 
    528558                  uapres->remote, pjsip_evsub_get_state_name(sub))); 
    529559 
    530         if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
     560        state = pjsip_evsub_get_state(sub); 
     561 
     562        if (pjsua_var.ua_cfg.cb.on_srv_subscribe_state) { 
     563            pj_str_t from; 
     564 
     565            from = uapres->dlg->remote.info_str; 
     566            (*pjsua_var.ua_cfg.cb.on_srv_subscribe_state)(uapres->acc_id,  
     567                                                          uapres, &from, 
     568                                                          state, event); 
     569        } 
     570 
     571        if (state == PJSIP_EVSUB_STATE_TERMINATED) { 
    531572            pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 
    532573            pj_list_erase(uapres); 
     
    549590    pjsip_evsub *sub; 
    550591    pjsip_evsub_user pres_cb; 
    551     pjsip_tx_data *tdata; 
    552     pjsip_pres_status pres_status; 
    553592    pjsip_dialog *dlg; 
     593    pjsip_status_code st_code; 
     594    pj_str_t reason; 
    554595    pjsip_expires_hdr *expires_hdr; 
    555     pjsip_evsub_state ev_state; 
    556     pjsua_buddy_id buddy_id; 
     596    pjsua_msg_data msg_data; 
    557597    pj_status_t status; 
    558598 
     
    628668    uapres->sub = sub; 
    629669    uapres->remote = (char*) pj_pool_alloc(dlg->pool, PJSIP_MAX_URL_SIZE); 
     670    uapres->acc_id = acc_id; 
     671    uapres->dlg = dlg; 
    630672    status = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->remote.info->uri, 
    631673                             uapres->remote, PJSIP_MAX_URL_SIZE); 
     
    641683 
    642684 
    643     /* Create and send 200 (OK) to the SUBSCRIBE request: */ 
    644     status = pjsip_pres_accept(sub, rdata, 200, NULL); 
     685    /* Capture the value of Expires header. */ 
     686    expires_hdr = (pjsip_expires_hdr*) 
     687                  pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, 
     688                                     NULL); 
     689    if (expires_hdr) 
     690        uapres->expires = expires_hdr->ivalue; 
     691    else 
     692        uapres->expires = -1; 
     693 
     694    st_code = 200; 
     695    reason = pj_str("OK"); 
     696    pjsua_msg_data_init(&msg_data); 
     697 
     698    /* Notify application callback, if any */ 
     699    if (pjsua_var.ua_cfg.cb.on_incoming_subscribe) { 
     700        pjsua_buddy_id buddy_id; 
     701 
     702        buddy_id = pjsua_find_buddy(rdata->msg_info.from->uri); 
     703 
     704        (*pjsua_var.ua_cfg.cb.on_incoming_subscribe)(acc_id, uapres, buddy_id, 
     705                                                     &dlg->remote.info_str,  
     706                                                     rdata, &st_code, &reason, 
     707                                                     &msg_data); 
     708    } 
     709 
     710    /* Handle rejection case */ 
     711    if (st_code >= 300) { 
     712        pjsip_tx_data *tdata; 
     713 
     714        /* Create response */ 
     715        status = pjsip_dlg_create_response(dlg, rdata, st_code,  
     716                                           &reason, &tdata); 
     717        if (status != PJ_SUCCESS) { 
     718            pjsua_perror(THIS_FILE, "Error creating response",  status); 
     719            pj_list_erase(uapres); 
     720            pjsip_pres_terminate(sub, PJ_FALSE); 
     721            PJSUA_UNLOCK(); 
     722            return PJ_FALSE; 
     723        } 
     724 
     725        /* Add header list, if any */ 
     726        pjsua_process_msg_data(tdata, &msg_data); 
     727 
     728        /* Send the response */ 
     729        status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), 
     730                                         tdata); 
     731        if (status != PJ_SUCCESS) { 
     732            pjsua_perror(THIS_FILE, "Error sending response",  status); 
     733            /* This is not fatal */ 
     734        } 
     735 
     736        /* Terminate presence subscription */ 
     737        pj_list_erase(uapres); 
     738        pjsip_pres_terminate(sub, PJ_FALSE); 
     739        PJSUA_UNLOCK(); 
     740        return PJ_TRUE; 
     741    } 
     742 
     743    /* Create and send 2xx response to the SUBSCRIBE request: */ 
     744    status = pjsip_pres_accept(sub, rdata, st_code, &msg_data.hdr_list); 
    645745    if (status != PJ_SUCCESS) { 
    646746        pjsua_perror(THIS_FILE, "Unable to accept presence subscription",  
     
    652752    } 
    653753 
     754    /* If code is 200, send NOTIFY now */ 
     755    if (st_code == 200) { 
     756        pjsua_pres_notify(acc_id, uapres, PJSIP_EVSUB_STATE_ACTIVE,  
     757                          NULL, NULL, PJ_TRUE, &msg_data); 
     758    } 
     759 
     760    /* Done: */ 
     761 
     762    PJSUA_UNLOCK(); 
     763 
     764    return PJ_TRUE; 
     765} 
     766 
     767 
     768/* 
     769 * Send NOTIFY. 
     770 */ 
     771PJ_DEF(pj_status_t) pjsua_pres_notify( pjsua_acc_id acc_id, 
     772                                       pjsua_srv_pres *srv_pres, 
     773                                       pjsip_evsub_state ev_state, 
     774                                       const pj_str_t *state_str, 
     775                                       const pj_str_t *reason, 
     776                                       pj_bool_t with_body, 
     777                                       const pjsua_msg_data *msg_data) 
     778{ 
     779    pjsua_acc *acc; 
     780    pjsip_pres_status pres_status; 
     781    pjsua_buddy_id buddy_id; 
     782    pjsip_tx_data *tdata; 
     783    pj_status_t status; 
     784 
     785    /* Check parameters */ 
     786    PJ_ASSERT_RETURN(acc_id!=-1 && srv_pres, PJ_EINVAL); 
     787 
     788    /* Check that account ID is valid */ 
     789    PJ_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc), 
     790                     PJ_EINVAL); 
     791    /* Check that account is valid */ 
     792    PJ_ASSERT_RETURN(pjsua_var.acc[acc_id].valid, PJ_EINVALIDOP); 
     793 
     794    PJSUA_LOCK(); 
     795 
     796    acc = &pjsua_var.acc[acc_id]; 
     797 
     798    /* Check that the server presence subscription is still valid */ 
     799    if (pj_list_find_node(&acc->pres_srv_list, srv_pres) == NULL) { 
     800        /* Subscription has been terminated */ 
     801        PJSUA_UNLOCK(); 
     802        return PJ_EINVALIDOP; 
     803    } 
    654804 
    655805    /* Set our online status: */ 
    656806    pj_bzero(&pres_status, sizeof(pres_status)); 
    657807    pres_status.info_cnt = 1; 
    658     pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status; 
    659     pres_status.info[0].id = pjsua_var.acc[acc_id].cfg.pidf_tuple_id; 
     808    pres_status.info[0].basic_open = acc->online_status; 
     809    pres_status.info[0].id = acc->cfg.pidf_tuple_id; 
    660810    //Both pjsua_var.local_uri and pjsua_var.contact_uri are enclosed in "<" and ">" 
    661811    //causing XML parsing to fail. 
    662812    //pres_status.info[0].contact = pjsua_var.local_uri; 
    663813 
    664     pjsip_pres_set_status(sub, &pres_status); 
     814    pjsip_pres_set_status(srv_pres->sub, &pres_status); 
    665815 
    666816    /* Check expires value. If it's zero, send our presense state but 
    667817     * set subscription state to TERMINATED. 
    668818     */ 
    669     expires_hdr=(pjsip_expires_hdr*) 
    670                 pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL); 
    671  
    672     if (expires_hdr && expires_hdr->ivalue == 0) 
     819    if (srv_pres->expires == 0) 
    673820        ev_state = PJSIP_EVSUB_STATE_TERMINATED; 
    674     else 
    675         ev_state = PJSIP_EVSUB_STATE_ACTIVE; 
    676  
    677     /* Create and send the first NOTIFY to active subscription: */ 
    678     status = pjsip_pres_notify( sub, ev_state, NULL, NULL, &tdata); 
     821 
     822    /* Create and send the NOTIFY to active subscription: */ 
     823    status = pjsip_pres_notify(srv_pres->sub, ev_state, state_str,  
     824                               reason, &tdata); 
    679825    if (status == PJ_SUCCESS) { 
    680         pjsua_process_msg_data(tdata, NULL); 
    681         status = pjsip_pres_send_request( sub, tdata); 
     826        /* Force removal of message body if msg_body==FALSE */ 
     827        if (!with_body) { 
     828            tdata->msg->body = NULL; 
     829        } 
     830        pjsua_process_msg_data(tdata, msg_data); 
     831        status = pjsip_pres_send_request( srv_pres->sub, tdata); 
    682832    } 
    683833 
     
    685835        pjsua_perror(THIS_FILE, "Unable to create/send NOTIFY",  
    686836                     status); 
    687         pj_list_erase(uapres); 
    688         pjsip_pres_terminate(sub, PJ_FALSE); 
    689         PJSUA_UNLOCK(); 
    690         return PJ_FALSE; 
     837        pj_list_erase(srv_pres); 
     838        pjsip_pres_terminate(srv_pres->sub, PJ_FALSE); 
     839        PJSUA_UNLOCK(); 
     840        return status; 
    691841    } 
    692842 
    693843 
    694844    /* Subscribe to buddy's presence if we're not subscribed */ 
    695     buddy_id = pjsua_find_buddy(dlg->remote.info->uri); 
     845    buddy_id = pjsua_find_buddy(srv_pres->dlg->remote.info->uri); 
    696846    if (buddy_id != PJSUA_INVALID_ID) { 
    697847        pjsua_buddy *b = &pjsua_var.buddy[buddy_id]; 
     
    703853    } 
    704854 
    705     /* Done: */ 
    706  
    707855    PJSUA_UNLOCK(); 
    708856 
    709     return PJ_TRUE; 
     857    return PJ_SUCCESS; 
    710858} 
    711859 
     
    10101158 
    10111159        if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
     1160            if (buddy->term_reason.ptr == NULL) { 
     1161                buddy->term_reason.ptr = (char*)  
     1162                                         pj_pool_alloc(buddy->pool, 
     1163                                           PJSUA_BUDDY_SUB_TERM_REASON_LEN); 
     1164            } 
     1165            pj_strncpy(&buddy->term_reason,  
     1166                       pjsip_evsub_get_termination_reason(sub),  
     1167                       PJSUA_BUDDY_SUB_TERM_REASON_LEN); 
     1168        } else { 
     1169            buddy->term_reason.slen = 0; 
     1170        } 
     1171 
     1172        /* Call callback */ 
     1173        if (pjsua_var.ua_cfg.cb.on_buddy_state) 
     1174            (*pjsua_var.ua_cfg.cb.on_buddy_state)(buddy->index); 
     1175 
     1176        /* Clear subscription */ 
     1177        if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
    10121178            buddy->sub = NULL; 
    10131179            buddy->status.info_cnt = 0; 
    10141180            pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 
    10151181        } 
    1016  
    1017         /* Call callback */ 
    1018         if (pjsua_var.ua_cfg.cb.on_buddy_state) 
    1019             (*pjsua_var.ua_cfg.cb.on_buddy_state)(buddy->index); 
    10201182    } 
    10211183 
Note: See TracChangeset for help on using the changeset viewer.