Changeset 5649 for pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
- Timestamp:
- Sep 15, 2017 5:32:08 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r5636 r5649 306 306 307 307 cfg->media_stun_use = PJSUA_STUN_RETRY_ON_FAILURE; 308 cfg->ip_change_cfg.shutdown_tp = PJ_TRUE; 309 cfg->ip_change_cfg.hangup_calls = PJ_FALSE; 310 cfg->ip_change_cfg.reinvite_flags = PJSUA_CALL_REINIT_MEDIA | 311 PJSUA_CALL_UPDATE_CONTACT | 312 PJSUA_CALL_UPDATE_VIA; 308 313 } 309 314 … … 2368 2373 pj_memcpy(&tcp_cfg.sockopt_params, &cfg->sockopt_params, 2369 2374 sizeof(tcp_cfg.sockopt_params)); 2370 2375 2371 2376 /* Create the TCP transport */ 2372 2377 status = pjsip_tcp_transport_start3(pjsua_var.endpt, &tcp_cfg, &tcp); … … 2426 2431 a_name.host = cfg->public_addr; 2427 2432 2428 status = pjsip_tls_transport_start2(pjsua_var.endpt, 2429 &cfg->tls_setting, 2433 status = pjsip_tls_transport_start2(pjsua_var.endpt, &cfg->tls_setting, 2430 2434 &local_addr, &a_name, 1, &tls); 2431 2435 if (status != PJ_SUCCESS) { … … 2712 2716 2713 2717 2718 PJ_DEF(pj_status_t) pjsua_transport_lis_start(pjsua_transport_id id, 2719 const pjsua_transport_config *cfg) 2720 { 2721 pj_status_t status = PJ_SUCCESS; 2722 pjsip_transport_type_e tp_type; 2723 2724 /* Make sure id is in range. */ 2725 PJ_ASSERT_RETURN(id>=0 && id<(int)PJ_ARRAY_SIZE(pjsua_var.tpdata), 2726 PJ_EINVAL); 2727 2728 /* Make sure that transport exists */ 2729 PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL); 2730 2731 tp_type = pjsua_var.tpdata[id].type & ~PJSIP_TRANSPORT_IPV6; 2732 2733 if ((tp_type == PJSIP_TRANSPORT_TLS) || (tp_type == PJSIP_TRANSPORT_TCP)) { 2734 pj_sockaddr bind_addr; 2735 pjsip_host_port addr_name; 2736 pjsip_tpfactory *factory = pjsua_var.tpdata[id].data.factory; 2737 2738 int af = pjsip_transport_type_get_af(factory->type); 2739 2740 if (cfg->port) 2741 pj_sockaddr_set_port(&bind_addr, (pj_uint16_t)cfg->port); 2742 2743 if (cfg->bound_addr.slen) { 2744 status = pj_sockaddr_set_str_addr(af, 2745 &bind_addr, 2746 &cfg->bound_addr); 2747 if (status != PJ_SUCCESS) { 2748 pjsua_perror(THIS_FILE, 2749 "Unable to resolve transport bound address", 2750 status); 2751 return status; 2752 } 2753 } 2754 2755 /* Set published name */ 2756 if (cfg->public_addr.slen) 2757 addr_name.host = cfg->public_addr; 2758 2759 if (tp_type == PJSIP_TRANSPORT_TCP) { 2760 status = pjsip_tcp_transport_lis_start(factory, &bind_addr, 2761 &addr_name); 2762 } 2763 #if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0 2764 else { 2765 status = pjsip_tls_transport_lis_start(factory, &bind_addr, 2766 &addr_name); 2767 } 2768 #endif 2769 } else if (tp_type == PJSIP_TRANSPORT_UDP) { 2770 status = PJ_SUCCESS; 2771 } else { 2772 status = PJ_EINVAL; 2773 } 2774 return status; 2775 } 2776 2777 2714 2778 /* 2715 2779 * Add additional headers etc in msg_data specified by application … … 2863 2927 sel->u.listener = tpdata->data.factory; 2864 2928 } 2929 } 2930 2931 2932 PJ_DEF(void) pjsua_ip_change_param_default(pjsua_ip_change_param *param) 2933 { 2934 pj_bzero(param, sizeof(*param)); 2935 param->restart_listener = PJ_TRUE; 2936 param->restart_lis_delay = PJSUA_TRANSPORT_RESTART_DELAY_TIME; 2865 2937 } 2866 2938 … … 3272 3344 } 3273 3345 3346 3347 /* Forward declaration. */ 3348 static void restart_listener_cb(void *user_data); 3349 3350 3351 static pj_status_t handle_ip_change_on_acc() 3352 { 3353 int i = 0; 3354 pj_status_t status = PJ_SUCCESS; 3355 pj_bool_t acc_done[PJSUA_MAX_ACC]; 3356 3357 /* Reset ip_change_active flag. */ 3358 for (; i < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { 3359 pjsua_var.acc[i].ip_change_op = PJSUA_IP_CHANGE_OP_NULL; 3360 acc_done[i] = PJ_FALSE; 3361 } 3362 3363 for (i = 0; i < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { 3364 pj_bool_t shutdown_transport = PJ_FALSE; 3365 pjsip_regc_info regc_info; 3366 char acc_id[PJSUA_MAX_ACC * 4]; 3367 pjsua_acc *acc = &pjsua_var.acc[i]; 3368 pjsip_transport *transport = NULL; 3369 pjsua_acc_id shut_acc_ids[PJSUA_MAX_ACC]; 3370 unsigned shut_acc_cnt = 0; 3371 3372 if (!acc->valid || (acc_done[i])) 3373 continue; 3374 3375 if (acc->regc) { 3376 pjsip_regc_get_info(acc->regc, ®c_info); 3377 if ((regc_info.transport) && 3378 ((regc_info.transport->flag & PJSIP_TRANSPORT_DATAGRAM) == 0)) 3379 { 3380 transport = regc_info.transport; 3381 shutdown_transport = acc->cfg.ip_change_cfg.shutdown_tp; 3382 shut_acc_ids[shut_acc_cnt++] = acc->index; 3383 } 3384 } else if (acc->reg_last_code != PJSIP_SC_BAD_GATEWAY && 3385 acc->reg_last_code != PJSIP_SC_REQUEST_TIMEOUT && 3386 acc->reg_last_code != PJSIP_SC_INTERNAL_SERVER_ERROR && 3387 acc->reg_last_code != PJSIP_SC_BAD_GATEWAY && 3388 acc->reg_last_code != PJSIP_SC_SERVICE_UNAVAILABLE && 3389 acc->reg_last_code != PJSIP_SC_SERVER_TIMEOUT && 3390 acc->reg_last_code != PJSIP_SC_TEMPORARILY_UNAVAILABLE) 3391 { 3392 continue; 3393 } 3394 pj_ansi_snprintf(acc_id, sizeof(acc_id), "#%d", i); 3395 3396 if (transport) { 3397 unsigned j = i + 1; 3398 3399 /* Find other account that uses the same transport. */ 3400 for (; j < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++j) { 3401 pjsip_regc_info tmp_regc_info; 3402 pjsua_acc *next_acc = &pjsua_var.acc[j]; 3403 3404 if (!next_acc->valid || !next_acc->regc || 3405 (next_acc->ip_change_op > PJSUA_IP_CHANGE_OP_NULL)) 3406 { 3407 continue; 3408 } 3409 3410 pjsip_regc_get_info(next_acc->regc, &tmp_regc_info); 3411 if (transport == tmp_regc_info.transport) { 3412 char tmp_buf[PJSUA_MAX_ACC * 4]; 3413 3414 pj_ansi_strncpy(tmp_buf, acc_id, sizeof(acc_id)); 3415 pj_ansi_snprintf(acc_id, sizeof(acc_id), "%s #%d", 3416 tmp_buf, j); 3417 shut_acc_ids[shut_acc_cnt++] = j; 3418 if (!shutdown_transport) { 3419 shutdown_transport = 3420 next_acc->cfg.ip_change_cfg.shutdown_tp; 3421 } 3422 } 3423 } 3424 } 3425 3426 if (shutdown_transport) { 3427 unsigned j; 3428 /* Shutdown the transport. */ 3429 PJ_LOG(3, (THIS_FILE, "Shutdown transport %s used by account %s " 3430 "triggered by IP change", transport->obj_name, acc_id)); 3431 3432 for (j = 0; j < shut_acc_cnt; ++j) { 3433 pjsua_acc *tmp_acc = &pjsua_var.acc[shut_acc_ids[j]]; 3434 tmp_acc->ip_change_op = PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP; 3435 acc_done[shut_acc_ids[j]] = PJ_TRUE; 3436 } 3437 3438 status = pjsip_transport_shutdown2(transport, PJ_TRUE); 3439 3440 /* Report progress to each acc which uses the same transport. */ 3441 for (j = 0; j < shut_acc_cnt; ++j) { 3442 pjsua_acc *tmp_acc = &pjsua_var.acc[shut_acc_ids[j]]; 3443 3444 if (pjsua_var.ua_cfg.cb.on_ip_change_progress) { 3445 pjsua_ip_change_op_info info; 3446 3447 pj_bzero(&info, sizeof(info)); 3448 info.acc_shutdown_tp.acc_id = tmp_acc->index; 3449 3450 pjsua_var.ua_cfg.cb.on_ip_change_progress( 3451 tmp_acc->ip_change_op, 3452 status, 3453 &info); 3454 } 3455 3456 } 3457 } else { 3458 acc_done[i] = PJ_TRUE; 3459 if (acc->cfg.allow_contact_rewrite) { 3460 status = pjsua_acc_update_contact_on_ip_change(acc); 3461 } else { 3462 status = pjsua_acc_handle_call_on_ip_change(acc); 3463 } 3464 } 3465 } 3466 return status; 3467 } 3468 3469 3470 static pj_status_t restart_listener(pjsua_transport_id id, 3471 unsigned restart_lis_delay) 3472 { 3473 pj_sockaddr bind_addr; 3474 pjsua_transport_info tp_info; 3475 pj_status_t status; 3476 3477 pjsua_transport_get_info(id, &tp_info); 3478 pj_sockaddr_init(pjsip_transport_type_get_af(tp_info.type), 3479 &bind_addr, 3480 NULL, 3481 pj_sockaddr_get_port(&tp_info.local_addr)); 3482 3483 switch (tp_info.type) { 3484 case PJSIP_TRANSPORT_UDP: 3485 case PJSIP_TRANSPORT_UDP6: 3486 status = pjsip_udp_transport_restart2( 3487 pjsua_var.tpdata[id].data.tp, 3488 PJSIP_UDP_TRANSPORT_DESTROY_SOCKET, 3489 PJ_INVALID_SOCKET, 3490 &bind_addr, 3491 NULL); 3492 break; 3493 3494 #if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0 3495 case PJSIP_TRANSPORT_TLS: 3496 case PJSIP_TRANSPORT_TLS6: 3497 status = pjsip_tls_transport_restart( 3498 pjsua_var.tpdata[id].data.factory, 3499 &bind_addr, 3500 NULL); 3501 break; 3502 #endif 3503 case PJSIP_TRANSPORT_TCP: 3504 case PJSIP_TRANSPORT_TCP6: 3505 status = pjsip_tcp_transport_restart( 3506 pjsua_var.tpdata[id].data.factory, 3507 &bind_addr, 3508 NULL); 3509 break; 3510 3511 default: 3512 status = PJ_EINVAL; 3513 } 3514 if (status != PJ_SUCCESS && (restart_lis_delay > 0)) { 3515 /* Try restarting again, with delay. */ 3516 pjsua_schedule_timer2(&restart_listener_cb, 3517 (void*)(pj_size_t)id, 3518 restart_lis_delay); 3519 } else { 3520 int i = 0; 3521 pj_bool_t all_done = PJ_TRUE; 3522 3523 pjsua_var.tpdata[id].is_restarting = PJ_FALSE; 3524 if (pjsua_var.ua_cfg.cb.on_ip_change_progress) { 3525 pjsua_ip_change_op_info info; 3526 3527 pj_bzero(&info, sizeof(info)); 3528 info.lis_restart.transport_id = id; 3529 pjsua_var.ua_cfg.cb.on_ip_change_progress( 3530 PJSUA_IP_CHANGE_OP_RESTART_LIS, 3531 status, 3532 &info); 3533 } 3534 3535 /* Move forward if all listener has been restarted. */ 3536 for (; i < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) { 3537 if (pjsua_var.tpdata[i].data.ptr != NULL && 3538 pjsua_var.tpdata[i].is_restarting) 3539 { 3540 all_done = PJ_FALSE; 3541 break; 3542 } 3543 } 3544 if (all_done) 3545 status = handle_ip_change_on_acc(); 3546 } 3547 return status; 3548 } 3549 3550 3551 static void restart_listener_cb(void *user_data) 3552 { 3553 pjsua_transport_id transport_id = (pjsua_transport_id)(pj_size_t)user_data; 3554 restart_listener(transport_id, 0); 3555 } 3556 3557 3558 PJ_DEF(pj_status_t) pjsua_handle_ip_change(const pjsua_ip_change_param *param) 3559 { 3560 pj_status_t status = PJ_SUCCESS; 3561 int i = 0; 3562 3563 PJ_ASSERT_RETURN(param, PJ_EINVAL); 3564 3565 PJ_LOG(3, (THIS_FILE, "Start handling IP address change")); 3566 3567 if (param->restart_listener) { 3568 /* Restart listener/transport, handle_ip_change_on_acc() will 3569 * be called after listener restart is completed successfully. 3570 */ 3571 for (i = 0; i < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) { 3572 if (pjsua_var.tpdata[i].data.ptr != NULL) { 3573 pjsua_var.tpdata[i].is_restarting = PJ_TRUE; 3574 } 3575 } 3576 for (i = 0; i < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) { 3577 if (pjsua_var.tpdata[i].data.ptr != NULL) { 3578 status = restart_listener(i, param->restart_lis_delay); 3579 } 3580 } 3581 } else { 3582 status = handle_ip_change_on_acc(); 3583 } 3584 3585 return status; 3586 }
Note: See TracChangeset
for help on using the changeset viewer.