Ignore:
Timestamp:
Oct 31, 2007 1:28:08 PM (12 years ago)
Author:
bennylp
Message:

Ticket #407: keep-alive for UDP transports in PJSUA-LIB

File:
1 edited

Legend:

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

    r1520 r1536  
    6565 * Copy account configuration. 
    6666 */ 
    67 static void copy_acc_config(pj_pool_t *pool, 
    68                             pjsua_acc_config *dst, 
    69                             const pjsua_acc_config *src) 
     67PJ_DEF(void) pjsua_acc_config_dup( pj_pool_t *pool, 
     68                                   pjsua_acc_config *dst, 
     69                                   const pjsua_acc_config *src) 
    7070{ 
    7171    unsigned i; 
     
    8888        pjsip_cred_dup(pool, &dst->cred_info[i], &src->cred_info[i]); 
    8989    } 
     90 
     91    dst->ka_interval = src->ka_interval; 
     92    pj_strdup(pool, &dst->ka_data, &src->ka_data); 
    9093} 
    9194 
     
    276279 
    277280    /* Copy config */ 
    278     copy_acc_config(pjsua_var.pool, &pjsua_var.acc[id].cfg, cfg); 
     281    pjsua_acc_config_dup(pjsua_var.pool, &pjsua_var.acc[id].cfg, cfg); 
    279282     
    280283    /* Normalize registration timeout */ 
     
    632635} 
    633636 
     637 
     638/* Keep alive timer callback */ 
     639static void keep_alive_timer_cb(pj_timer_heap_t *th, pj_timer_entry *te) 
     640{ 
     641    pjsua_acc *acc; 
     642    pjsip_tpselector tp_sel; 
     643    pj_time_val delay; 
     644    pj_status_t status; 
     645 
     646    PJ_UNUSED_ARG(th); 
     647 
     648    PJSUA_LOCK(); 
     649 
     650    te->id = PJ_FALSE; 
     651 
     652    acc = (pjsua_acc*) te->user_data; 
     653 
     654    /* Select the transport to send the packet */ 
     655    pj_bzero(&tp_sel, sizeof(tp_sel)); 
     656    tp_sel.type = PJSIP_TPSELECTOR_TRANSPORT; 
     657    tp_sel.u.transport = acc->ka_transport; 
     658 
     659    PJ_LOG(5,(THIS_FILE,  
     660              "Sending %d bytes keep-alive packet for acc %d to %s:%d", 
     661              acc->cfg.ka_data.slen, acc->index, 
     662              pj_inet_ntoa(acc->ka_target.ipv4.sin_addr), 
     663              pj_ntohs(acc->ka_target.ipv4.sin_port))); 
     664 
     665    /* Send raw packet */ 
     666    status = pjsip_tpmgr_send_raw(pjsip_endpt_get_tpmgr(pjsua_var.endpt), 
     667                                  PJSIP_TRANSPORT_UDP, &tp_sel, 
     668                                  NULL, acc->cfg.ka_data.ptr,  
     669                                  acc->cfg.ka_data.slen,  
     670                                  &acc->ka_target, acc->ka_target_len, 
     671                                  NULL, NULL); 
     672 
     673    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
     674        pjsua_perror(THIS_FILE, "Error sending keep-alive packet", status); 
     675    } 
     676 
     677    /* Reschedule next timer */ 
     678    delay.sec = acc->cfg.ka_interval; 
     679    delay.msec = 0; 
     680    status = pjsip_endpt_schedule_timer(pjsua_var.endpt, te, &delay); 
     681    if (status == PJ_SUCCESS) { 
     682        te->id = PJ_TRUE; 
     683    } else { 
     684        pjsua_perror(THIS_FILE, "Error starting keep-alive timer", status); 
     685    } 
     686 
     687    PJSUA_UNLOCK(); 
     688} 
     689 
     690 
     691/* Update keep-alive for the account */ 
     692static void update_keep_alive(pjsua_acc *acc, pj_bool_t start, 
     693                              struct pjsip_regc_cbparam *param) 
     694{ 
     695    /* In all cases, stop keep-alive timer if it's running. */ 
     696    if (acc->ka_timer.id) { 
     697        pjsip_endpt_cancel_timer(pjsua_var.endpt, &acc->ka_timer); 
     698        acc->ka_timer.id = PJ_FALSE; 
     699 
     700        pjsip_transport_dec_ref(acc->ka_transport); 
     701        acc->ka_transport = NULL; 
     702    } 
     703 
     704    if (start) { 
     705        pj_time_val delay; 
     706        pj_status_t status; 
     707 
     708        /* Only do keep-alive if: 
     709         *  - STUN is enabled in global config, and 
     710         *  - ka_interval is not zero in the account, and 
     711         *  - transport is UDP. 
     712         */ 
     713        if (pjsua_var.stun_srv.ipv4.sin_family == 0 || 
     714            acc->cfg.ka_interval == 0 || 
     715            param->rdata->tp_info.transport->key.type != PJSIP_TRANSPORT_UDP) 
     716        { 
     717            /* Keep alive is not necessary */ 
     718            return; 
     719        } 
     720 
     721        /* Save transport and destination address. */ 
     722        acc->ka_transport = param->rdata->tp_info.transport; 
     723        pjsip_transport_add_ref(acc->ka_transport); 
     724        pj_memcpy(&acc->ka_target, &param->rdata->pkt_info.src_addr, 
     725                  param->rdata->pkt_info.src_addr_len); 
     726        acc->ka_target_len = param->rdata->pkt_info.src_addr_len; 
     727 
     728        /* Setup and start the timer */ 
     729        acc->ka_timer.cb = &keep_alive_timer_cb; 
     730        acc->ka_timer.user_data = (void*)acc; 
     731 
     732        delay.sec = acc->cfg.ka_interval; 
     733        delay.msec = 0; 
     734        status = pjsip_endpt_schedule_timer(pjsua_var.endpt, &acc->ka_timer,  
     735                                            &delay); 
     736        if (status == PJ_SUCCESS) { 
     737            acc->ka_timer.id = PJ_TRUE; 
     738            PJ_LOG(4,(THIS_FILE, "Keep-alive timer started for acc %d, " 
     739                                 "destination:%s:%d, interval:%ds", 
     740                                 acc->index, 
     741                                 param->rdata->pkt_info.src_name, 
     742                                 param->rdata->pkt_info.src_port, 
     743                                 acc->cfg.ka_interval)); 
     744        } else { 
     745            acc->ka_timer.id = PJ_FALSE; 
     746            pjsip_transport_dec_ref(acc->ka_transport); 
     747            acc->ka_transport = NULL; 
     748            pjsua_perror(THIS_FILE, "Error starting keep-alive timer", status); 
     749        } 
     750    } 
     751} 
     752 
     753 
    634754/* 
    635755 * This callback is called by pjsip_regc when outgoing register 
     
    655775        acc->regc = NULL; 
    656776         
     777        /* Stop keep-alive timer if any. */ 
     778        update_keep_alive(acc, PJ_FALSE, NULL); 
     779 
    657780    } else if (param->code < 0 || param->code >= 300) { 
    658781        PJ_LOG(2, (THIS_FILE, "SIP registration failed, status=%d (%.*s)",  
     
    662785        acc->regc = NULL; 
    663786 
     787        /* Stop keep-alive timer if any. */ 
     788        update_keep_alive(acc, PJ_FALSE, NULL); 
     789 
    664790    } else if (PJSIP_IS_STATUS_IN_CLASS(param->code, 200)) { 
    665791 
     
    667793            pjsip_regc_destroy(acc->regc); 
    668794            acc->regc = NULL; 
     795 
     796            /* Stop keep-alive timer if any. */ 
     797            update_keep_alive(acc, PJ_FALSE, NULL); 
     798 
    669799            PJ_LOG(3,(THIS_FILE, "%s: unregistration success", 
    670800                      pjsua_var.acc[acc->index].cfg.id.ptr)); 
     
    687817                       (int)param->reason.slen, param->reason.ptr, 
    688818                       param->expiration)); 
     819 
     820            /* Start keep-alive timer if necessary. */ 
     821            update_keep_alive(acc, PJ_TRUE, param); 
    689822 
    690823            /* Send initial PUBLISH if it is enabled */ 
Note: See TracChangeset for help on using the changeset viewer.