Ignore:
Timestamp:
Oct 18, 2006 5:16:34 PM (18 years ago)
Author:
bennylp
Message:

Some changes to REFER handling in PJSUA-LIB:

  • added callback to report call transfer progress
  • changed the call transfer request callback name in pjsua
  • added "--norefersub" option in pjsua.
  • fixed bug when call transfer is done more than once in the same dialog (dialog usage can not be added)

Also removed 7xx status from the SIP status codes.

And added pjsip_parse_status_line() to parse sipfrag.

File:
1 edited

Legend:

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

    r738 r780  
    7272 * has changed. 
    7373 */ 
    74 static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event); 
     74static void xfer_client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event); 
     75static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event); 
     76 
     77/* 
     78 * Callback called by event framework when NOTIFY is received for outgoing 
     79 * REFER subscription. 
     80 */ 
     81static void xfer_on_rx_notify(pjsip_evsub *sub,  
     82                              pjsip_rx_data *rdata, 
     83                              int *p_st_code, 
     84                              pj_str_t **p_st_text, 
     85                              pjsip_hdr *res_hdr, 
     86                              pjsip_msg_body **p_body); 
    7587 
    7688/* 
     
    10791091    /* Create xfer client subscription. */ 
    10801092    pj_bzero(&xfer_cb, sizeof(xfer_cb)); 
    1081     xfer_cb.on_evsub_state = &xfer_on_evsub_state; 
     1093    xfer_cb.on_evsub_state = &xfer_client_on_evsub_state; 
    10821094 
    10831095    status = pjsip_xfer_create_uac(call->inv->dlg, &xfer_cb, &sub); 
     
    10871099        return status; 
    10881100    } 
     1101 
     1102    /* Associate this call with the client subscription */ 
     1103    pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, call); 
    10891104 
    10901105    /* 
     
    21452160 * has changed. 
    21462161 */ 
    2147 static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) 
     2162static void xfer_client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) 
     2163{ 
     2164     
     2165    PJ_UNUSED_ARG(event); 
     2166 
     2167    /* 
     2168     * When subscription is accepted (got 200/OK to REFER), check if  
     2169     * subscription suppressed. 
     2170     */ 
     2171    if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACCEPTED) { 
     2172 
     2173        pjsip_rx_data *rdata; 
     2174        pjsip_generic_string_hdr *refer_sub; 
     2175        const pj_str_t REFER_SUB = { "Refer-Sub", 9 }; 
     2176        pjsua_call *call; 
     2177 
     2178        call = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
     2179 
     2180        /* Must be receipt of response message */ 
     2181        pj_assert(event->type == PJSIP_EVENT_TSX_STATE &&  
     2182                  event->body.tsx_state.type == PJSIP_EVENT_RX_MSG); 
     2183        rdata = event->body.tsx_state.src.rdata; 
     2184 
     2185        /* Find Refer-Sub header */ 
     2186        refer_sub = (pjsip_generic_string_hdr*) 
     2187                    pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,  
     2188                                               &REFER_SUB, NULL); 
     2189 
     2190        /* Check if subscription is suppressed */ 
     2191        if (refer_sub && pj_stricmp2(&refer_sub->hvalue, "false")==0) { 
     2192            /* Since no subscription is desired, assume that call has been 
     2193             * transfered successfully. 
     2194             */ 
     2195            if (call && pjsua_var.ua_cfg.cb.on_call_transfer_status) { 
     2196                const pj_str_t ACCEPTED = { "Accepted", 8 }; 
     2197                pj_bool_t cont = PJ_FALSE; 
     2198                (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,  
     2199                                                               200, 
     2200                                                               &ACCEPTED, 
     2201                                                               PJ_TRUE, 
     2202                                                               &cont); 
     2203            } 
     2204 
     2205            /* Yes, subscription is suppressed. 
     2206             * Terminate our subscription now. 
     2207             */ 
     2208            PJ_LOG(4,(THIS_FILE, "Xfer subscription suppressed, terminating " 
     2209                                 "event subcription...")); 
     2210            pjsip_evsub_terminate(sub, PJ_TRUE); 
     2211 
     2212        } else { 
     2213            /* Notify application about call transfer progress.  
     2214             * Initially notify with 100/Accepted status. 
     2215             */ 
     2216            if (call && pjsua_var.ua_cfg.cb.on_call_transfer_status) { 
     2217                const pj_str_t ACCEPTED = { "Accepted", 8 }; 
     2218                pj_bool_t cont = PJ_FALSE; 
     2219                (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,  
     2220                                                               100, 
     2221                                                               &ACCEPTED, 
     2222                                                               PJ_FALSE, 
     2223                                                               &cont); 
     2224            } 
     2225        } 
     2226    } 
     2227    /* 
     2228     * On incoming NOTIFY, notify application about call transfer progress. 
     2229     */ 
     2230    else if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACTIVE || 
     2231             pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED)  
     2232    { 
     2233        pjsua_call *call; 
     2234        pjsip_msg *msg; 
     2235        pjsip_msg_body *body; 
     2236        pjsip_status_line status_line; 
     2237        pj_bool_t is_last; 
     2238        pj_bool_t cont; 
     2239        pj_status_t status; 
     2240 
     2241        call = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
     2242 
     2243        /* When subscription is terminated, clear the xfer_sub member of  
     2244         * the inv_data. 
     2245         */ 
     2246        if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
     2247            pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 
     2248            PJ_LOG(4,(THIS_FILE, "Xfer client subscription terminated")); 
     2249 
     2250        } 
     2251 
     2252        if (!call || !event || !pjsua_var.ua_cfg.cb.on_call_transfer_status) { 
     2253            /* Application is not interested with call progress status */ 
     2254            return; 
     2255        } 
     2256 
     2257        /* This better be a NOTIFY request */ 
     2258        if (event->type == PJSIP_EVENT_TSX_STATE && 
     2259            event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) 
     2260        { 
     2261            pjsip_rx_data *rdata; 
     2262 
     2263            rdata = event->body.tsx_state.src.rdata; 
     2264 
     2265            /* Check if there's body */ 
     2266            msg = rdata->msg_info.msg; 
     2267            body = msg->body; 
     2268            if (!body) { 
     2269                PJ_LOG(4,(THIS_FILE,  
     2270                          "Warning: received NOTIFY without message body")); 
     2271                return; 
     2272            } 
     2273 
     2274            /* Check for appropriate content */ 
     2275            if (pj_stricmp2(&body->content_type.type, "message") != 0 || 
     2276                pj_stricmp2(&body->content_type.subtype, "sipfrag") != 0) 
     2277            { 
     2278                PJ_LOG(4,(THIS_FILE,  
     2279                          "Warning: received NOTIFY with non message/sipfrag " 
     2280                          "content")); 
     2281                return; 
     2282            } 
     2283 
     2284            /* Try to parse the content */ 
     2285            status = pjsip_parse_status_line(body->data, body->len,  
     2286                                             &status_line); 
     2287            if (status != PJ_SUCCESS) { 
     2288                PJ_LOG(4,(THIS_FILE,  
     2289                          "Warning: received NOTIFY with invalid " 
     2290                          "message/sipfrag content")); 
     2291                return; 
     2292            } 
     2293 
     2294        } else { 
     2295            status_line.code = 500; 
     2296            status_line.reason = *pjsip_get_status_text(500); 
     2297        } 
     2298 
     2299        /* Notify application */ 
     2300        is_last = (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED); 
     2301        cont = !is_last; 
     2302        (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,  
     2303                                                       status_line.code, 
     2304                                                       &status_line.reason, 
     2305                                                       is_last, &cont); 
     2306 
     2307        if (!cont) { 
     2308            pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 
     2309        } 
     2310    } 
     2311} 
     2312 
     2313 
     2314/* 
     2315 * Callback called by event framework when the xfer subscription state 
     2316 * has changed. 
     2317 */ 
     2318static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) 
    21482319{ 
    21492320     
     
    21642335        call->xfer_sub = NULL; 
    21652336 
    2166         PJ_LOG(4,(THIS_FILE, "Xfer subscription terminated")); 
    2167  
    2168     } 
    2169     /* 
    2170      * When subscription is accepted (got 200/OK to REFER), check if  
    2171      * subscription suppressed. 
    2172      */ 
    2173     else if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACCEPTED) { 
    2174  
    2175         pjsip_rx_data *rdata; 
    2176         pjsip_generic_string_hdr *refer_sub; 
    2177         const pj_str_t REFER_SUB = { "Refer-Sub", 9 }; 
    2178  
    2179         /* Must be receipt of response message */ 
    2180         pj_assert(event->type == PJSIP_EVENT_TSX_STATE &&  
    2181                   event->body.tsx_state.type == PJSIP_EVENT_RX_MSG); 
    2182         rdata = event->body.tsx_state.src.rdata; 
    2183  
    2184         /* Find Refer-Sub header */ 
    2185         refer_sub = (pjsip_generic_string_hdr*) 
    2186                     pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,  
    2187                                                &REFER_SUB, NULL); 
    2188  
    2189         /* Check if subscription is suppressed */ 
    2190         if (refer_sub && pj_stricmp2(&refer_sub->hvalue, "false")==0) { 
    2191             /* Yes, subscription is suppressed. 
    2192              * Terminate our subscription now. 
    2193              */ 
    2194             PJ_LOG(4,(THIS_FILE, "Xfer subscription suppressed, terminating " 
    2195                                  "event subcription...")); 
    2196             pjsip_evsub_terminate(sub, PJ_TRUE); 
    2197         } 
     2337        PJ_LOG(4,(THIS_FILE, "Xfer server subscription terminated")); 
    21982338    } 
    21992339} 
     
    22472387    /* Notify callback */ 
    22482388    code = PJSIP_SC_OK; 
    2249     if (pjsua_var.ua_cfg.cb.on_call_transfered) 
    2250         (*pjsua_var.ua_cfg.cb.on_call_transfered)(existing_call->index, 
    2251                                                   &refer_to->hvalue, &code); 
     2389    if (pjsua_var.ua_cfg.cb.on_call_transfer_request) 
     2390        (*pjsua_var.ua_cfg.cb.on_call_transfer_request)(existing_call->index, 
     2391                                                        &refer_to->hvalue,  
     2392                                                        &code); 
    22522393 
    22532394    if (code < 200) 
     
    23052446        /* Init callback */ 
    23062447        pj_bzero(&xfer_cb, sizeof(xfer_cb)); 
    2307         xfer_cb.on_evsub_state = &xfer_on_evsub_state; 
     2448        xfer_cb.on_evsub_state = &xfer_server_on_evsub_state; 
    23082449 
    23092450        /* Init additional header list to be sent with REFER response */ 
Note: See TracChangeset for help on using the changeset viewer.