Ignore:
Timestamp:
Jun 22, 2007 11:32:49 AM (17 years ago)
Author:
bennylp
Message:

Committed ticket #337: Ability to restart PJSIP UDP transport

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c

    r1269 r1382  
    6868    pjsip_rx_data     **rdata; 
    6969    int                 is_closing; 
     70    pj_bool_t           is_paused; 
    7071}; 
    7172 
     
    122123        return; 
    123124    } 
     125 
     126    /* Don't do anything if transport is being paused. */ 
     127    if (tp->is_paused) 
     128        return; 
    124129 
    125130    /* 
     
    205210            op_key = &rdata->tp_info.op_key.op_key; 
    206211        } 
     212 
     213        /* Only read next packet if transport is not being paused. This 
     214         * check handles the case where transport is paused while endpoint 
     215         * is still processing a SIP message. 
     216         */ 
     217        if (tp->is_paused) 
     218            return; 
    207219 
    208220        /* Read next packet. */ 
     
    296308    PJ_ASSERT_RETURN(tdata->op_key.tdata == NULL, PJSIP_EPENDINGTX); 
    297309     
     310    /* Return error if transport is paused */ 
     311    if (tp->is_paused) 
     312        return PJSIP_ETPNOTAVAIL; 
     313 
    298314    /* Init op key. */ 
    299315    tdata->op_key.tdata = tdata; 
     
    396412 
    397413 
    398 /* 
    399  * pjsip_udp_transport_attach() 
    400  * 
    401  * Attach UDP socket and start transport. 
    402  */ 
    403 PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt, 
    404                                                 pj_sock_t sock, 
    405                                                 const pjsip_host_port *a_name, 
    406                                                 unsigned async_cnt, 
    407                                                 pjsip_transport **p_transport) 
    408 { 
    409     enum { M = 80 }; 
    410     pj_pool_t *pool; 
    411     struct udp_transport *tp; 
    412     pj_ioqueue_t *ioqueue; 
    413     pj_ioqueue_callback ioqueue_cb; 
     414/* Create socket */ 
     415static pj_status_t create_socket(const pj_sockaddr_in *local_a, 
     416                                 pj_sock_t *p_sock) 
     417{ 
     418    pj_sock_t sock; 
     419    pj_sockaddr_in tmp_addr; 
     420    pj_status_t status; 
     421 
     422    status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock); 
     423    if (status != PJ_SUCCESS) 
     424        return status; 
     425 
     426    if (local_a == NULL) { 
     427        pj_sockaddr_in_init(&tmp_addr, NULL, 0); 
     428        local_a = &tmp_addr; 
     429    } 
     430 
     431    status = pj_sock_bind(sock, local_a, sizeof(*local_a)); 
     432    if (status != PJ_SUCCESS) { 
     433        pj_sock_close(sock); 
     434        return status; 
     435    } 
     436 
     437    *p_sock = sock; 
     438    return PJ_SUCCESS; 
     439} 
     440 
     441 
     442/* Generate transport's published address */ 
     443static pj_status_t get_published_name(pj_sock_t sock, 
     444                                      char hostbuf[], 
     445                                      pjsip_host_port *bound_name) 
     446{ 
     447    pj_sockaddr_in tmp_addr; 
     448    int addr_len; 
     449    pj_status_t status; 
     450 
     451    addr_len = sizeof(tmp_addr); 
     452    status = pj_sock_getsockname(sock, &tmp_addr, &addr_len); 
     453    if (status != PJ_SUCCESS) 
     454        return status; 
     455 
     456    bound_name->host.ptr = hostbuf; 
     457    bound_name->port = pj_ntohs(tmp_addr.sin_port); 
     458 
     459    /* If bound address specifies "0.0.0.0", get the IP address 
     460     * of local hostname. 
     461     */ 
     462    if (tmp_addr.sin_addr.s_addr == PJ_INADDR_ANY) { 
     463        pj_in_addr hostip; 
     464 
     465        status = pj_gethostip(&hostip); 
     466        if (status != PJ_SUCCESS) 
     467            return status; 
     468 
     469        pj_strcpy2(&bound_name->host, pj_inet_ntoa(hostip)); 
     470    } else { 
     471        /* Otherwise use bound address. */ 
     472        pj_strcpy2(&bound_name->host, pj_inet_ntoa(tmp_addr.sin_addr)); 
     473    } 
     474 
     475    return PJ_SUCCESS; 
     476} 
     477 
     478/* Set the published address of the transport */ 
     479static void udp_set_pub_name(struct udp_transport *tp, 
     480                             const pjsip_host_port *a_name) 
     481{ 
     482    enum { INFO_LEN = 80 }; 
     483 
     484    pj_assert(a_name->host.slen != 0); 
     485    pj_strdup_with_null(tp->base.pool, &tp->base.local_name.host,  
     486                        &a_name->host); 
     487    tp->base.local_name.port = a_name->port; 
     488 
     489    /* Update transport info. */ 
     490    if (tp->base.info == NULL) { 
     491        tp->base.info = (char*) pj_pool_alloc(tp->base.pool, INFO_LEN); 
     492    } 
     493    pj_ansi_snprintf(  
     494        tp->base.info, INFO_LEN, "udp %s:%d [published as %s:%d]", 
     495        pj_inet_ntoa(((pj_sockaddr_in*)&tp->base.local_addr)->sin_addr), 
     496        pj_ntohs(((pj_sockaddr_in*)&tp->base.local_addr)->sin_port), 
     497        tp->base.local_name.host.ptr, 
     498        tp->base.local_name.port); 
     499} 
     500 
     501/* Set the socket handle of the transport */ 
     502static void udp_set_socket(struct udp_transport *tp, 
     503                           pj_sock_t sock, 
     504                           const pjsip_host_port *a_name) 
     505{ 
    414506    long sobuf_size; 
    415     unsigned i; 
    416507    pj_status_t status; 
    417  
    418     PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0, 
    419                      PJ_EINVAL); 
    420  
    421508 
    422509    /* Adjust socket rcvbuf size */ 
     
    442529    } 
    443530 
    444     /* Create pool. */ 
    445     pool = pjsip_endpt_create_pool(endpt, "udp%p", PJSIP_POOL_LEN_TRANSPORT,  
    446                                    PJSIP_POOL_INC_TRANSPORT); 
    447     if (!pool) 
    448         return PJ_ENOMEM; 
    449  
    450     /* Create the UDP transport object. */ 
    451     tp = PJ_POOL_ZALLOC_T(pool, struct udp_transport); 
    452  
    453     /* Save pool. */ 
    454     tp->base.pool = pool; 
    455  
    456     /* Object name. */ 
    457     pj_ansi_snprintf(tp->base.obj_name, sizeof(tp->base.obj_name),  
    458                      "udp%p", tp); 
    459  
    460     /* Init reference counter. */ 
    461     status = pj_atomic_create(pool, 0, &tp->base.ref_cnt); 
    462     if (status != PJ_SUCCESS) 
    463         goto on_error; 
    464  
    465     /* Init lock. */ 
    466     status = pj_lock_create_recursive_mutex(pool, "udp%p", &tp->base.lock); 
    467     if (status != PJ_SUCCESS) 
    468         goto on_error; 
    469  
    470     /* Set type. */ 
    471     tp->base.key.type = PJSIP_TRANSPORT_UDP; 
    472  
    473     /* Remote address is left zero (except the family) */ 
    474     tp->base.key.rem_addr.addr.sa_family = PJ_AF_INET; 
    475  
    476     /* Type name. */ 
    477     tp->base.type_name = "UDP"; 
    478  
    479     /* Transport flag */ 
    480     tp->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP); 
    481  
    482  
    483     /* Length of addressess. */ 
    484     tp->base.addr_len = sizeof(pj_sockaddr_in); 
    485  
    486     /* Init local address. */ 
    487     status = pj_sock_getsockname(sock, &tp->base.local_addr,  
    488                                  &tp->base.addr_len); 
    489     if (status != PJ_SUCCESS) 
    490         goto on_error; 
     531    /* Set the socket. */ 
     532    tp->sock = sock; 
    491533 
    492534    /* Init address name (published address) */ 
    493     pj_strdup_with_null(pool, &tp->base.local_name.host, &a_name->host); 
    494     tp->base.local_name.port = a_name->port; 
    495  
    496     /* Init remote name. */ 
    497     tp->base.remote_name.host = pj_str("0.0.0.0"); 
    498     tp->base.remote_name.port = 0; 
    499  
    500     /* Transport info. */ 
    501     tp->base.info = (char*) pj_pool_alloc(pool, M); 
    502     pj_ansi_snprintf(  
    503         tp->base.info, M, "udp %s:%d [published as %s:%d]", 
    504         pj_inet_ntoa(((pj_sockaddr_in*)&tp->base.local_addr)->sin_addr), 
    505         pj_ntohs(((pj_sockaddr_in*)&tp->base.local_addr)->sin_port), 
    506         tp->base.local_name.host.ptr, 
    507         tp->base.local_name.port); 
    508  
    509     /* Set endpoint. */ 
    510     tp->base.endpt = endpt; 
    511  
    512     /* Transport manager and timer will be initialized by tpmgr */ 
    513  
    514     /* Attach socket. */ 
    515     tp->sock = sock; 
     535    udp_set_pub_name(tp, a_name); 
     536} 
     537 
     538/* Register socket to ioqueue */ 
     539static pj_status_t register_to_ioqueue(struct udp_transport *tp) 
     540{ 
     541    pj_ioqueue_t *ioqueue; 
     542    pj_ioqueue_callback ioqueue_cb; 
    516543 
    517544    /* Register to ioqueue. */ 
    518     ioqueue = pjsip_endpt_get_ioqueue(endpt); 
     545    ioqueue = pjsip_endpt_get_ioqueue(tp->base.endpt); 
    519546    pj_memset(&ioqueue_cb, 0, sizeof(ioqueue_cb)); 
    520547    ioqueue_cb.on_read_complete = &udp_on_read_complete; 
    521548    ioqueue_cb.on_write_complete = &udp_on_write_complete; 
    522     status = pj_ioqueue_register_sock(pool, ioqueue, tp->sock, tp,  
    523                                       &ioqueue_cb, &tp->key); 
    524     if (status != PJ_SUCCESS) 
    525         goto on_error; 
    526  
    527     /* Set functions. */ 
    528     tp->base.send_msg = &udp_send_msg; 
    529     tp->base.do_shutdown = &udp_shutdown; 
    530     tp->base.destroy = &udp_destroy; 
    531  
    532     /* This is a permanent transport, so we initialize the ref count 
    533      * to one so that transport manager don't destroy this transport 
    534      * when there's no user! 
    535      */ 
    536     pj_atomic_inc(tp->base.ref_cnt); 
    537  
    538     /* Register to transport manager. */ 
    539     tp->base.tpmgr = pjsip_endpt_get_tpmgr(endpt); 
    540     status = pjsip_transport_register( tp->base.tpmgr, (pjsip_transport*)tp); 
    541     if (status != PJ_SUCCESS) 
    542         goto on_error; 
    543  
    544  
    545     /* Create rdata and put it in the array. */ 
    546     tp->rdata_cnt = 0; 
    547     tp->rdata = (pjsip_rx_data**) 
    548                 pj_pool_calloc(tp->base.pool, async_cnt,  
    549                                sizeof(pjsip_rx_data*)); 
    550     for (i=0; i<async_cnt; ++i) { 
    551         pj_pool_t *rdata_pool = pjsip_endpt_create_pool(endpt, "rtd%p",  
    552                                                         PJSIP_POOL_RDATA_LEN, 
    553                                                         PJSIP_POOL_RDATA_INC); 
    554         if (!rdata_pool) { 
    555             pj_atomic_set(tp->base.ref_cnt, 0); 
    556             pjsip_transport_destroy(&tp->base); 
    557             return PJ_ENOMEM; 
    558         } 
    559  
    560         init_rdata(tp, i, rdata_pool, NULL); 
    561         tp->rdata_cnt++; 
    562     } 
     549 
     550    return pj_ioqueue_register_sock(tp->base.pool, ioqueue, tp->sock, tp, 
     551                                    &ioqueue_cb, &tp->key); 
     552} 
     553 
     554/* Start ioqueue asynchronous reading to all rdata */ 
     555static pj_status_t start_async_read(struct udp_transport *tp) 
     556{ 
     557    pj_ioqueue_t *ioqueue; 
     558    int i; 
     559    pj_status_t status; 
     560 
     561    ioqueue = pjsip_endpt_get_ioqueue(tp->base.endpt); 
    563562 
    564563    /* Start reading the ioqueue. */ 
    565     for (i=0; i<async_cnt; ++i) { 
     564    for (i=0; i<tp->rdata_cnt; ++i) { 
    566565        pj_ssize_t size; 
    567566 
     
    580579        } else if (status != PJ_EPENDING) { 
    581580            /* Error! */ 
     581            return status; 
     582        } 
     583    } 
     584 
     585    return PJ_SUCCESS; 
     586} 
     587 
     588 
     589/* 
     590 * pjsip_udp_transport_attach() 
     591 * 
     592 * Attach UDP socket and start transport. 
     593 */ 
     594PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt, 
     595                                                pj_sock_t sock, 
     596                                                const pjsip_host_port *a_name, 
     597                                                unsigned async_cnt, 
     598                                                pjsip_transport **p_transport) 
     599{ 
     600    pj_pool_t *pool; 
     601    struct udp_transport *tp; 
     602    unsigned i; 
     603    pj_status_t status; 
     604 
     605    PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0, 
     606                     PJ_EINVAL); 
     607 
     608    /* Create pool. */ 
     609    pool = pjsip_endpt_create_pool(endpt, "udp%p", PJSIP_POOL_LEN_TRANSPORT,  
     610                                   PJSIP_POOL_INC_TRANSPORT); 
     611    if (!pool) 
     612        return PJ_ENOMEM; 
     613 
     614    /* Create the UDP transport object. */ 
     615    tp = PJ_POOL_ZALLOC_T(pool, struct udp_transport); 
     616 
     617    /* Save pool. */ 
     618    tp->base.pool = pool; 
     619 
     620    /* Object name. */ 
     621    pj_ansi_snprintf(tp->base.obj_name, sizeof(tp->base.obj_name),  
     622                     "udp%p", tp); 
     623 
     624    /* Init reference counter. */ 
     625    status = pj_atomic_create(pool, 0, &tp->base.ref_cnt); 
     626    if (status != PJ_SUCCESS) 
     627        goto on_error; 
     628 
     629    /* Init lock. */ 
     630    status = pj_lock_create_recursive_mutex(pool, "udp%p", &tp->base.lock); 
     631    if (status != PJ_SUCCESS) 
     632        goto on_error; 
     633 
     634    /* Set type. */ 
     635    tp->base.key.type = PJSIP_TRANSPORT_UDP; 
     636 
     637    /* Remote address is left zero (except the family) */ 
     638    tp->base.key.rem_addr.addr.sa_family = PJ_AF_INET; 
     639 
     640    /* Type name. */ 
     641    tp->base.type_name = "UDP"; 
     642 
     643    /* Transport flag */ 
     644    tp->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP); 
     645 
     646 
     647    /* Length of addressess. */ 
     648    tp->base.addr_len = sizeof(pj_sockaddr_in); 
     649 
     650    /* Init local address. */ 
     651    status = pj_sock_getsockname(sock, &tp->base.local_addr,  
     652                                 &tp->base.addr_len); 
     653    if (status != PJ_SUCCESS) 
     654        goto on_error; 
     655 
     656    /* Init remote name. */ 
     657    tp->base.remote_name.host = pj_str("0.0.0.0"); 
     658    tp->base.remote_name.port = 0; 
     659 
     660    /* Set endpoint. */ 
     661    tp->base.endpt = endpt; 
     662 
     663    /* Transport manager and timer will be initialized by tpmgr */ 
     664 
     665    /* Attach socket and assign name. */ 
     666    udp_set_socket(tp, sock, a_name); 
     667 
     668    /* Register to ioqueue */ 
     669    status = register_to_ioqueue(tp); 
     670    if (status != PJ_SUCCESS) 
     671        goto on_error; 
     672 
     673    /* Set functions. */ 
     674    tp->base.send_msg = &udp_send_msg; 
     675    tp->base.do_shutdown = &udp_shutdown; 
     676    tp->base.destroy = &udp_destroy; 
     677 
     678    /* This is a permanent transport, so we initialize the ref count 
     679     * to one so that transport manager don't destroy this transport 
     680     * when there's no user! 
     681     */ 
     682    pj_atomic_inc(tp->base.ref_cnt); 
     683 
     684    /* Register to transport manager. */ 
     685    tp->base.tpmgr = pjsip_endpt_get_tpmgr(endpt); 
     686    status = pjsip_transport_register( tp->base.tpmgr, (pjsip_transport*)tp); 
     687    if (status != PJ_SUCCESS) 
     688        goto on_error; 
     689 
     690 
     691    /* Create rdata and put it in the array. */ 
     692    tp->rdata_cnt = 0; 
     693    tp->rdata = (pjsip_rx_data**) 
     694                pj_pool_calloc(tp->base.pool, async_cnt,  
     695                               sizeof(pjsip_rx_data*)); 
     696    for (i=0; i<async_cnt; ++i) { 
     697        pj_pool_t *rdata_pool = pjsip_endpt_create_pool(endpt, "rtd%p",  
     698                                                        PJSIP_POOL_RDATA_LEN, 
     699                                                        PJSIP_POOL_RDATA_INC); 
     700        if (!rdata_pool) { 
     701            pj_atomic_set(tp->base.ref_cnt, 0); 
    582702            pjsip_transport_destroy(&tp->base); 
    583             return status; 
    584         } 
     703            return PJ_ENOMEM; 
     704        } 
     705 
     706        init_rdata(tp, i, rdata_pool, NULL); 
     707        tp->rdata_cnt++; 
     708    } 
     709 
     710    /* Start reading the ioqueue. */ 
     711    status = start_async_read(tp); 
     712    if (status != PJ_SUCCESS) { 
     713        pjsip_transport_destroy(&tp->base); 
     714        return status; 
    585715    } 
    586716 
     
    616746    pj_status_t status; 
    617747    char addr_buf[16]; 
    618     pj_sockaddr_in tmp_addr; 
    619748    pjsip_host_port bound_name; 
    620749 
    621750    PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL); 
    622751 
    623     status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock); 
     752    status = create_socket(local_a, &sock); 
    624753    if (status != PJ_SUCCESS) 
    625754        return status; 
    626  
    627     if (local_a == NULL) { 
    628         pj_sockaddr_in_init(&tmp_addr, NULL, 0); 
    629         local_a = &tmp_addr; 
    630     } 
    631  
    632     status = pj_sock_bind(sock, local_a, sizeof(*local_a)); 
    633     if (status != PJ_SUCCESS) { 
    634         pj_sock_close(sock); 
    635         return status; 
    636     } 
    637755 
    638756    if (a_name == NULL) { 
     
    640758         * Build a name based on bound address. 
    641759         */ 
    642         int addr_len; 
    643  
    644         addr_len = sizeof(tmp_addr); 
    645         status = pj_sock_getsockname(sock, &tmp_addr, &addr_len); 
     760        status = get_published_name(sock, addr_buf, &bound_name); 
    646761        if (status != PJ_SUCCESS) { 
    647762            pj_sock_close(sock); 
     
    650765 
    651766        a_name = &bound_name; 
    652         bound_name.host.ptr = addr_buf; 
    653         bound_name.port = pj_ntohs(tmp_addr.sin_port); 
    654  
    655         /* If bound address specifies "0.0.0.0", get the IP address 
    656          * of local hostname. 
    657          */ 
    658         if (tmp_addr.sin_addr.s_addr == PJ_INADDR_ANY) { 
    659             pj_in_addr hostip; 
    660  
    661             status = pj_gethostip(&hostip); 
     767    } 
     768 
     769    return pjsip_udp_transport_attach( endpt, sock, a_name, async_cnt,  
     770                                       p_transport ); 
     771} 
     772 
     773 
     774/* 
     775 * Retrieve the internal socket handle used by the UDP transport. 
     776 */ 
     777PJ_DEF(pj_sock_t) pjsip_udp_transport_get_socket(pjsip_transport *transport) 
     778{ 
     779    struct udp_transport *tp; 
     780 
     781    PJ_ASSERT_RETURN(transport != NULL, PJ_INVALID_SOCKET); 
     782 
     783    tp = (struct udp_transport*) transport; 
     784 
     785    return tp->sock; 
     786} 
     787 
     788 
     789/* 
     790 * Temporarily pause or shutdown the transport.  
     791 */ 
     792PJ_DEF(pj_status_t) pjsip_udp_transport_pause(pjsip_transport *transport, 
     793                                              unsigned option) 
     794{ 
     795    struct udp_transport *tp; 
     796    unsigned i; 
     797 
     798    PJ_ASSERT_RETURN(transport != NULL, PJ_EINVAL); 
     799 
     800    /* Flag must be specified */ 
     801    PJ_ASSERT_RETURN((option & 0x03) != 0, PJ_EINVAL); 
     802 
     803    tp = (struct udp_transport*) transport; 
     804 
     805    /* Transport must not have been paused */ 
     806    PJ_ASSERT_RETURN(tp->is_paused==0, PJ_EINVALIDOP); 
     807 
     808    /* Set transport to paused first, so that when the read callback is  
     809     * called by pj_ioqueue_post_completion() it will not try to 
     810     * re-register the rdata. 
     811     */ 
     812    tp->is_paused = PJ_TRUE; 
     813 
     814    /* Cancel the ioqueue operation. */ 
     815    for (i=0; i<(unsigned)tp->rdata_cnt; ++i) { 
     816        pj_ioqueue_post_completion(tp->key,  
     817                                   &tp->rdata[i]->tp_info.op_key.op_key, -1); 
     818    } 
     819 
     820    /* Destroy the socket? */ 
     821    if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) { 
     822        if (tp->key) { 
     823            /* This implicitly closes the socket */ 
     824            pj_ioqueue_unregister(tp->key); 
     825            tp->key = NULL; 
     826        } else { 
     827            /* Close socket. */ 
     828            if (tp->sock && tp->sock != PJ_INVALID_SOCKET) { 
     829                pj_sock_close(tp->sock); 
     830                tp->sock = PJ_INVALID_SOCKET; 
     831            } 
     832        } 
     833        tp->sock = PJ_INVALID_SOCKET; 
     834    } 
     835 
     836    PJ_LOG(4,(tp->base.obj_name, "SIP UDP transport paused")); 
     837 
     838    return PJ_SUCCESS; 
     839} 
     840 
     841 
     842/* 
     843 * Restart transport. 
     844 * 
     845 * If option is KEEP_SOCKET, just re-activate ioqueue operation. 
     846 * 
     847 * If option is DESTROY_SOCKET: 
     848 *  - if socket is specified, replace. 
     849 *  - if socket is not specified, create and replace. 
     850 */ 
     851PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport, 
     852                                                unsigned option, 
     853                                                pj_sock_t sock, 
     854                                                const pj_sockaddr_in *local, 
     855                                                const pjsip_host_port *a_name) 
     856{ 
     857    struct udp_transport *tp; 
     858    pj_status_t status; 
     859 
     860    PJ_ASSERT_RETURN(transport != NULL, PJ_EINVAL); 
     861    /* Flag must be specified */ 
     862    PJ_ASSERT_RETURN((option & 0x03) != 0, PJ_EINVAL); 
     863 
     864    tp = (struct udp_transport*) transport; 
     865 
     866    if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) { 
     867        char addr_buf[16]; 
     868        pjsip_host_port bound_name; 
     869 
     870        /* Request to recreate transport */ 
     871 
     872        /* Destroy existing socket, if any. */ 
     873        if (tp->key) { 
     874            /* This implicitly closes the socket */ 
     875            pj_ioqueue_unregister(tp->key); 
     876            tp->key = NULL; 
     877        } else { 
     878            /* Close socket. */ 
     879            if (tp->sock && tp->sock != PJ_INVALID_SOCKET) { 
     880                pj_sock_close(tp->sock); 
     881                tp->sock = PJ_INVALID_SOCKET; 
     882            } 
     883        } 
     884        tp->sock = PJ_INVALID_SOCKET; 
     885 
     886        /* Create the socket if it's not specified */ 
     887        if (sock == PJ_INVALID_SOCKET) { 
     888            status = create_socket(local, &sock); 
    662889            if (status != PJ_SUCCESS) 
    663890                return status; 
    664  
    665             pj_strcpy2(&bound_name.host, pj_inet_ntoa(hostip)); 
    666         } else { 
    667             /* Otherwise use bound address. */ 
    668             pj_strcpy2(&bound_name.host, pj_inet_ntoa(tmp_addr.sin_addr)); 
    669         } 
    670          
    671     } 
    672  
    673     return pjsip_udp_transport_attach( endpt, sock, a_name, async_cnt,  
    674                                        p_transport ); 
    675 } 
    676  
    677  
     891        } 
     892 
     893        /* If transport published name is not specified, calculate it 
     894         * from the bound address. 
     895         */ 
     896        if (a_name == NULL) { 
     897            status = get_published_name(sock, addr_buf, &bound_name); 
     898            if (status != PJ_SUCCESS) { 
     899                pj_sock_close(sock); 
     900                return status; 
     901            } 
     902 
     903            a_name = &bound_name; 
     904        } 
     905 
     906        /* Assign the socket and published address to transport. */ 
     907        udp_set_socket(tp, sock, a_name); 
     908 
     909    } else { 
     910 
     911        /* For KEEP_SOCKET, transport must have been paused before */ 
     912        PJ_ASSERT_RETURN(tp->is_paused, PJ_EINVALIDOP); 
     913 
     914        /* If address name is specified, update it */ 
     915        if (a_name != NULL) 
     916            udp_set_pub_name(tp, a_name); 
     917    } 
     918 
     919    /* Re-register new or existing socket to ioqueue. */ 
     920    status = register_to_ioqueue(tp); 
     921    if (status != PJ_SUCCESS) { 
     922        return status; 
     923    } 
     924 
     925    /* Restart async read operation. */ 
     926    status = start_async_read(tp); 
     927    if (status != PJ_SUCCESS) 
     928        return status; 
     929 
     930    /* Everything has been set up */ 
     931    tp->is_paused = PJ_FALSE; 
     932 
     933    PJ_LOG(4,(tp->base.obj_name,  
     934              "SIP UDP transport restarted, published address is %.*s:%d", 
     935              (int)tp->base.local_name.host.slen, 
     936              tp->base.local_name.host.ptr, 
     937              tp->base.local_name.port)); 
     938 
     939    return PJ_SUCCESS; 
     940} 
     941 
Note: See TracChangeset for help on using the changeset viewer.