Changeset 780 for pjproject/trunk
- Timestamp:
- Oct 18, 2006 5:16:34 PM (18 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r777 r780 38 38 pjsua_logging_config log_cfg; 39 39 pjsua_media_config media_cfg; 40 pj_bool_t no_refersub; 40 41 pj_bool_t no_tcp; 41 42 pj_bool_t no_udp; … … 161 162 puts (" --thread-cnt=N Number of worker threads (default:1)"); 162 163 puts (" --duration=SEC Set maximum call duration (default:no limit)"); 164 puts (" --norefersub Suppress event subscription when transfering calls"); 163 165 164 166 puts (""); … … 288 290 OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS, 289 291 OPT_DURATION, OPT_NO_TCP, OPT_NO_UDP, OPT_THREAD_CNT, 292 OPT_NOREFERSUB, 290 293 }; 291 294 struct pj_getopt_option long_options[] = { … … 302 305 { "no-tcp", 0, 0, OPT_NO_TCP}, 303 306 { "no-udp", 0, 0, OPT_NO_UDP}, 307 { "norefersub", 0, 0, OPT_NOREFERSUB}, 304 308 { "proxy", 1, 0, OPT_PROXY}, 305 309 { "outbound", 1, 0, OPT_OUTBOUND_PROXY}, … … 457 461 break; 458 462 463 case OPT_NOREFERSUB: /* norefersub */ 464 cfg->no_refersub = PJ_TRUE; 465 break; 466 459 467 case OPT_NO_TCP: /* no-tcp */ 460 468 if (cfg->no_udp) { … … 948 956 } 949 957 958 /* No TCP ? */ 959 if (config->no_tcp) { 960 pj_strcat2(&cfg, "--no-tcp\n"); 961 } 962 963 /* No UDP ? */ 964 if (config->no_udp) { 965 pj_strcat2(&cfg, "--no-udp\n"); 966 } 950 967 951 968 /* STUN */ … … 1090 1107 } 1091 1108 1109 /* norefersub ? */ 1110 if (config->no_refersub) { 1111 pj_strcat2(&cfg, "--norefersub\n"); 1112 } 1113 1114 1092 1115 pj_strcat2(&cfg, "\n#\n# Buddies:\n#\n"); 1093 1116 … … 1471 1494 (int)from->slen, from->ptr, 1472 1495 (is_typing?"is typing..":"has stopped typing"))); 1496 } 1497 1498 1499 /** 1500 * Call transfer request status. 1501 */ 1502 static void on_call_transfer_status(pjsua_call_id call_id, 1503 int status_code, 1504 const pj_str_t *status_text, 1505 pj_bool_t final, 1506 pj_bool_t *p_cont) 1507 { 1508 PJ_LOG(3,(THIS_FILE, "Call %d: transfer status=%d (%.*s) %s", 1509 call_id, status_code, 1510 (int)status_text->slen, status_text->ptr, 1511 (final ? "[final]" : ""))); 1512 1513 if (status_code/100 == 2) { 1514 PJ_LOG(3,(THIS_FILE, 1515 "Call %d: call transfered successfully, disconnecting call", 1516 call_id)); 1517 pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL); 1518 *p_cont = PJ_FALSE; 1519 } 1473 1520 } 1474 1521 … … 2148 2195 } 2149 2196 2150 /* Add Refer-Sub: false in outgoing REFER request */2151 2197 pjsua_msg_data_init(&msg_data); 2152 pjsip_generic_string_hdr_init2(&refer_sub, &STR_REFER_SUB, 2153 &STR_FALSE); 2154 pj_list_push_back(&msg_data.hdr_list, &refer_sub); 2155 2198 if (app_config.no_refersub) { 2199 /* Add Refer-Sub: false in outgoing REFER request */ 2200 pjsip_generic_string_hdr_init2(&refer_sub, &STR_REFER_SUB, 2201 &STR_FALSE); 2202 pj_list_push_back(&msg_data.hdr_list, &refer_sub); 2203 } 2156 2204 if (result.nb_result != NO_NB) { 2157 2205 if (result.nb_result == -1 || result.nb_result == 0) … … 2168 2216 pjsua_call_xfer( current_call, &tmp, &msg_data); 2169 2217 } 2170 2171 /* Hangup call regardless of xfer status */2172 pjsua_call_hangup(current_call, PJSIP_SC_GONE, NULL, NULL);2173 2218 } 2174 2219 break; … … 2462 2507 app_config.cfg.cb.on_pager = &on_pager; 2463 2508 app_config.cfg.cb.on_typing = &on_typing; 2509 app_config.cfg.cb.on_call_transfer_status = &on_call_transfer_status; 2464 2510 2465 2511 /* Initialize pjsua */ -
pjproject/trunk/pjsip/include/pjsip/sip_msg.h
r736 r780 432 432 PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE = 606, 433 433 434 PJSIP_SC_TSX_TIMEOUT = 701,434 PJSIP_SC_TSX_TIMEOUT = PJSIP_SC_REQUEST_TIMEOUT, 435 435 /*PJSIP_SC_TSX_RESOLVE_ERROR = 702,*/ 436 PJSIP_SC_TSX_TRANSPORT_ERROR = 703436 PJSIP_SC_TSX_TRANSPORT_ERROR = PJSIP_SC_SERVICE_UNAVAILABLE 437 437 438 438 } pjsip_status_code; -
pjproject/trunk/pjsip/include/pjsip/sip_parser.h
r622 r780 25 25 */ 26 26 27 #include <pjsip/sip_ types.h>27 #include <pjsip/sip_msg.h> 28 28 #include <pjlib-util/scanner.h> 29 29 #include <pj/list.h> … … 190 190 char *buf, pj_size_t size, 191 191 unsigned options); 192 193 /** 194 * Parse SIP status line. 195 * 196 * @param buf Text buffer to parse. 197 * @param size The size of the buffer. 198 * @param status_line Structure to receive the parsed elements. 199 * 200 * @return PJ_SUCCESS if a status line is parsed successfully. 201 */ 202 PJ_DECL(pj_status_t) pjsip_parse_status_line(char *buf, pj_size_t size, 203 pjsip_status_line *status_line); 204 192 205 193 206 /** -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r753 r780 310 310 * transfer. 311 311 */ 312 void (*on_call_transfered)(pjsua_call_id call_id, 313 const pj_str_t *dst, 314 pjsip_status_code *code); 312 void (*on_call_transfer_request)(pjsua_call_id call_id, 313 const pj_str_t *dst, 314 pjsip_status_code *code); 315 316 /** 317 * Notify application of the status of previously sent call 318 * transfer request. Application can monitor the status of the 319 * call transfer request, for example to decide whether to 320 * terminate existing call. 321 * 322 * @param call_id Call ID. 323 * @param status_code Status progress of the transfer request. 324 * @param status_text Status progress text. 325 * @param final If non-zero, no further notification will 326 * be reported. The status_code specified in 327 * this callback is the final status. 328 * @param p_cont Initially will be set to non-zero, application 329 * can set this to FALSE if it no longer wants 330 * to receie further notification (for example, 331 * after it hangs up the call). 332 */ 333 void (*on_call_transfer_status)(pjsua_call_id call_id, 334 int status_code, 335 const pj_str_t *status_text, 336 pj_bool_t final, 337 pj_bool_t *p_cont); 315 338 316 339 /** -
pjproject/trunk/pjsip/src/pjsip/sip_dialog.c
r729 r780 794 794 for (index=0; index<dlg->usage_cnt; ++index) { 795 795 if (dlg->usage[index] == mod) { 796 pj_assert(!"This module is already registered"); 796 /* Module may be registered more than once in the same dialog. 797 * For example, when call transfer fails, application may retry 798 * call transfer on the same dialog. 799 * So return PJ_SUCCESS here. 800 */ 801 PJ_LOG(4,(dlg->obj_name, 802 "Module %.*s already registered as dialog usage, " 803 "updating the data %p", 804 (int)mod->name.slen, mod->name.ptr, mod_data)); 805 dlg->mod_data[mod->id] = mod_data; 806 797 807 pjsip_dlg_dec_lock(dlg); 798 return PJSIP_ETYPEEXISTS; 808 return PJ_SUCCESS; 809 810 //pj_assert(!"This module is already registered"); 811 //pjsip_dlg_dec_lock(dlg); 812 //return PJSIP_ETYPEEXISTS; 799 813 } 800 814 -
pjproject/trunk/pjsip/src/pjsip/sip_parser.c
r735 r780 1472 1472 } 1473 1473 1474 1475 /* 1476 * Public API to parse SIP status line. 1477 */ 1478 PJ_DEF(pj_status_t) pjsip_parse_status_line( char *buf, pj_size_t size, 1479 pjsip_status_line *status_line) 1480 { 1481 pj_scanner scanner; 1482 PJ_USE_EXCEPTION; 1483 1484 pj_bzero(status_line, sizeof(*status_line)); 1485 pj_scan_init(&scanner, buf, size, 0, &on_syntax_error); 1486 1487 PJ_TRY { 1488 int_parse_status_line(&scanner, status_line); 1489 } 1490 PJ_CATCH_ANY { 1491 /* Tolerate the error if it is caused only by missing newline */ 1492 if (status_line->code == 0 && status_line->reason.slen == 0) { 1493 pj_scan_fini(&scanner); 1494 return PJSIP_EINVALIDMSG; 1495 } 1496 } 1497 PJ_END; 1498 1499 pj_scan_fini(&scanner); 1500 return PJ_SUCCESS; 1501 } 1502 1503 1474 1504 /* Parse ending of header. */ 1475 1505 static void parse_hdr_end( pj_scanner *scanner ) -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r738 r780 72 72 * has changed. 73 73 */ 74 static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event); 74 static void xfer_client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event); 75 static 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 */ 81 static 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); 75 87 76 88 /* … … 1079 1091 /* Create xfer client subscription. */ 1080 1092 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; 1082 1094 1083 1095 status = pjsip_xfer_create_uac(call->inv->dlg, &xfer_cb, &sub); … … 1087 1099 return status; 1088 1100 } 1101 1102 /* Associate this call with the client subscription */ 1103 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, call); 1089 1104 1090 1105 /* … … 2145 2160 * has changed. 2146 2161 */ 2147 static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) 2162 static 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 */ 2318 static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) 2148 2319 { 2149 2320 … … 2164 2335 call->xfer_sub = NULL; 2165 2336 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")); 2198 2338 } 2199 2339 } … … 2247 2387 /* Notify callback */ 2248 2388 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); 2252 2393 2253 2394 if (code < 200) … … 2305 2446 /* Init callback */ 2306 2447 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; 2308 2449 2309 2450 /* Init additional header list to be sent with REFER response */
Note: See TracChangeset
for help on using the changeset viewer.