Ignore:
Timestamp:
Dec 1, 2007 8:59:25 AM (16 years ago)
Author:
bennylp
Message:

Ticket #421: initial IPv6 support: UDP transport

File:
1 edited

Legend:

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

    r1405 r1602  
    143143        if (bytes_read > MIN_SIZE) { 
    144144            pj_size_t size_eaten; 
    145             const pj_sockaddr_in *src_addr =  
    146                 (pj_sockaddr_in*)&rdata->pkt_info.src_addr; 
     145            const pj_sockaddr *src_addr = &rdata->pkt_info.src_addr; 
    147146 
    148147            /* Init pkt_info part. */ 
     
    150149            rdata->pkt_info.zero = 0; 
    151150            pj_gettimeofday(&rdata->pkt_info.timestamp); 
    152             pj_ansi_strcpy(rdata->pkt_info.src_name, 
    153                            pj_inet_ntoa(src_addr->sin_addr)); 
    154             rdata->pkt_info.src_port = pj_ntohs(src_addr->sin_port); 
     151            if (src_addr->addr.sa_family == pj_AF_INET()) { 
     152                pj_ansi_strcpy(rdata->pkt_info.src_name, 
     153                               pj_inet_ntoa(src_addr->ipv4.sin_addr)); 
     154                rdata->pkt_info.src_port = pj_ntohs(src_addr->ipv4.sin_port); 
     155            } else { 
     156                pj_inet_ntop(pj_AF_INET6(),  
     157                             pj_sockaddr_get_addr(&rdata->pkt_info.src_addr), 
     158                             rdata->pkt_info.src_name, 
     159                             sizeof(rdata->pkt_info.src_name)); 
     160                rdata->pkt_info.src_port = pj_ntohs(src_addr->ipv6.sin6_port); 
     161            } 
    155162 
    156163            size_eaten =  
     
    413420 
    414421/* Create socket */ 
    415 static pj_status_t create_socket(const pj_sockaddr_in *local_a, 
    416                                  pj_sock_t *p_sock) 
     422static pj_status_t create_socket(int af, const pj_sockaddr_t *local_a, 
     423                                 int addr_len, pj_sock_t *p_sock) 
    417424{ 
    418425    pj_sock_t sock; 
    419426    pj_sockaddr_in tmp_addr; 
     427    pj_sockaddr_in6 tmp_addr6; 
    420428    pj_status_t status; 
    421429 
    422     status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock); 
     430    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock); 
    423431    if (status != PJ_SUCCESS) 
    424432        return status; 
    425433 
    426434    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)); 
     435        if (af == pj_AF_INET6()) { 
     436            pj_bzero(&tmp_addr6, sizeof(tmp_addr6)); 
     437            tmp_addr6.sin6_family = (pj_uint16_t)af; 
     438            local_a = &tmp_addr6; 
     439            addr_len = sizeof(tmp_addr6); 
     440        } else { 
     441            pj_sockaddr_in_init(&tmp_addr, NULL, 0); 
     442            local_a = &tmp_addr; 
     443            addr_len = sizeof(tmp_addr); 
     444        } 
     445    } 
     446 
     447    status = pj_sock_bind(sock, local_a, addr_len); 
    432448    if (status != PJ_SUCCESS) { 
    433449        pj_sock_close(sock); 
     
    443459static pj_status_t get_published_name(pj_sock_t sock, 
    444460                                      char hostbuf[], 
     461                                      int hostbufsz, 
    445462                                      pjsip_host_port *bound_name) 
    446463{ 
    447     pj_sockaddr_in tmp_addr; 
     464    pj_sockaddr tmp_addr; 
    448465    int addr_len; 
    449466    pj_status_t status; 
     
    455472 
    456473    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)); 
     474    if (tmp_addr.addr.sa_family == pj_AF_INET()) { 
     475        bound_name->port = pj_ntohs(tmp_addr.ipv4.sin_port); 
     476 
     477        /* If bound address specifies "0.0.0.0", get the IP address 
     478         * of local hostname. 
     479         */ 
     480        if (tmp_addr.ipv4.sin_addr.s_addr == PJ_INADDR_ANY) { 
     481            pj_sockaddr hostip; 
     482 
     483            status = pj_gethostip(pj_AF_INET(), &hostip); 
     484            if (status != PJ_SUCCESS) 
     485                return status; 
     486 
     487            pj_strcpy2(&bound_name->host, pj_inet_ntoa(hostip.ipv4.sin_addr)); 
     488        } else { 
     489            /* Otherwise use bound address. */ 
     490            pj_strcpy2(&bound_name->host,  
     491                       pj_inet_ntoa(tmp_addr.ipv4.sin_addr)); 
     492            status = PJ_SUCCESS; 
     493        } 
     494 
    470495    } 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; 
     496        bound_name->port = pj_ntohs(tmp_addr.ipv6.sin6_port); 
     497        status = pj_inet_ntop(tmp_addr.addr.sa_family,  
     498                              pj_sockaddr_get_addr(&tmp_addr), 
     499                              hostbuf, hostbufsz); 
     500    } 
     501 
     502 
     503    return status; 
    476504} 
    477505 
     
    481509{ 
    482510    enum { INFO_LEN = 80 }; 
     511    char local_addr[PJ_INET6_ADDRSTRLEN]; 
    483512 
    484513    pj_assert(a_name->host.slen != 0); 
     
    491520        tp->base.info = (char*) pj_pool_alloc(tp->base.pool, INFO_LEN); 
    492521    } 
     522 
     523    pj_inet_ntop(tp->base.local_addr.addr.sa_family, 
     524                 pj_sockaddr_get_addr(&tp->base.local_addr),  
     525                 local_addr, sizeof(local_addr)); 
     526 
    493527    pj_ansi_snprintf(  
    494528        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), 
     529        local_addr, 
     530        pj_sockaddr_get_port(&tp->base.local_addr), 
    497531        tp->base.local_name.host.ptr, 
    498532        tp->base.local_name.port); 
     
    596630 * Attach UDP socket and start transport. 
    597631 */ 
    598 PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt, 
    599                                                 pj_sock_t sock, 
    600                                                 const pjsip_host_port *a_name, 
    601                                                 unsigned async_cnt, 
    602                                                 pjsip_transport **p_transport) 
     632static pj_status_t transport_attach( pjsip_endpoint *endpt, 
     633                                     pjsip_transport_type_e type, 
     634                                     pj_sock_t sock, 
     635                                     const pjsip_host_port *a_name, 
     636                                     unsigned async_cnt, 
     637                                     pjsip_transport **p_transport) 
    603638{ 
    604639    pj_pool_t *pool; 
    605640    struct udp_transport *tp; 
     641    const char *format; 
    606642    unsigned i; 
    607643    pj_status_t status; 
     
    610646                     PJ_EINVAL); 
    611647 
     648    /* Object name. */ 
     649    if (type & PJSIP_TRANSPORT_IPV6) 
     650        format = "udpv6%p"; 
     651    else 
     652        format = "udp%p"; 
     653 
    612654    /* Create pool. */ 
    613     pool = pjsip_endpt_create_pool(endpt, "udp%p", PJSIP_POOL_LEN_TRANSPORT,  
     655    pool = pjsip_endpt_create_pool(endpt, format, PJSIP_POOL_LEN_TRANSPORT,  
    614656                                   PJSIP_POOL_INC_TRANSPORT); 
    615657    if (!pool) 
     
    622664    tp->base.pool = pool; 
    623665 
    624     /* Object name. */ 
    625     pj_ansi_snprintf(tp->base.obj_name, sizeof(tp->base.obj_name),  
    626                      "udp%p", tp); 
     666    pj_memcpy(tp->base.obj_name, pool->obj_name, PJ_MAX_OBJ_NAME); 
    627667 
    628668    /* Init reference counter. */ 
     
    632672 
    633673    /* Init lock. */ 
    634     status = pj_lock_create_recursive_mutex(pool, "udp%p", &tp->base.lock); 
     674    status = pj_lock_create_recursive_mutex(pool, pool->obj_name,  
     675                                            &tp->base.lock); 
    635676    if (status != PJ_SUCCESS) 
    636677        goto on_error; 
    637678 
    638679    /* Set type. */ 
    639     tp->base.key.type = PJSIP_TRANSPORT_UDP; 
     680    tp->base.key.type = type; 
    640681 
    641682    /* Remote address is left zero (except the family) */ 
    642     tp->base.key.rem_addr.addr.sa_family = pj_AF_INET(); 
     683    tp->base.key.rem_addr.addr.sa_family = (pj_uint16_t) 
     684        ((type & PJSIP_TRANSPORT_IPV6) ? pj_AF_INET6() : pj_AF_INET()); 
    643685 
    644686    /* Type name. */ 
     
    646688 
    647689    /* Transport flag */ 
    648     tp->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP); 
     690    tp->base.flag = pjsip_transport_get_flag_from_type(type); 
    649691 
    650692 
    651693    /* Length of addressess. */ 
    652     tp->base.addr_len = sizeof(pj_sockaddr_in); 
     694    tp->base.addr_len = sizeof(tp->base.local_addr); 
    653695 
    654696    /* Init local address. */ 
     
    659701 
    660702    /* Init remote name. */ 
    661     tp->base.remote_name.host = pj_str("0.0.0.0"); 
     703    if (type == PJSIP_TRANSPORT_UDP) 
     704        tp->base.remote_name.host = pj_str("0.0.0.0"); 
     705    else 
     706        tp->base.remote_name.host = pj_str("::0"); 
    662707    tp->base.remote_name.port = 0; 
    663708 
     
    724769 
    725770    PJ_LOG(4,(tp->base.obj_name,  
    726               "SIP UDP transport started, published address is %.*s:%d", 
     771              "SIP %s started, published address is %.*s:%d", 
     772              pjsip_transport_get_type_desc((pjsip_transport_type_e)tp->base.key.type), 
    727773              (int)tp->base.local_name.host.slen, 
    728774              tp->base.local_name.host.ptr, 
     
    734780    udp_destroy((pjsip_transport*)tp); 
    735781    return status; 
     782} 
     783 
     784 
     785PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt, 
     786                                                pj_sock_t sock, 
     787                                                const pjsip_host_port *a_name, 
     788                                                unsigned async_cnt, 
     789                                                pjsip_transport **p_transport) 
     790{ 
     791    return transport_attach(endpt, PJSIP_TRANSPORT_UDP, sock, a_name, 
     792                            async_cnt, p_transport); 
     793} 
     794 
     795PJ_DEF(pj_status_t) pjsip_udp_transport_attach2( pjsip_endpoint *endpt, 
     796                                                 pjsip_transport_type_e type, 
     797                                                 pj_sock_t sock, 
     798                                                 const pjsip_host_port *a_name, 
     799                                                 unsigned async_cnt, 
     800                                                 pjsip_transport **p_transport) 
     801{ 
     802    return transport_attach(endpt, type, sock, a_name, 
     803                            async_cnt, p_transport); 
    736804} 
    737805 
     
    749817    pj_sock_t sock; 
    750818    pj_status_t status; 
    751     char addr_buf[16]; 
     819    char addr_buf[PJ_INET6_ADDRSTRLEN]; 
    752820    pjsip_host_port bound_name; 
    753821 
    754822    PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL); 
    755823 
    756     status = create_socket(local_a, &sock); 
     824    status = create_socket(pj_AF_INET(), local_a, sizeof(pj_sockaddr_in),  
     825                           &sock); 
    757826    if (status != PJ_SUCCESS) 
    758827        return status; 
     
    762831         * Build a name based on bound address. 
    763832         */ 
    764         status = get_published_name(sock, addr_buf, &bound_name); 
     833        status = get_published_name(sock, addr_buf, sizeof(addr_buf),  
     834                                    &bound_name); 
    765835        if (status != PJ_SUCCESS) { 
    766836            pj_sock_close(sock); 
     
    775845} 
    776846 
     847 
     848/* 
     849 * pjsip_udp_transport_start() 
     850 * 
     851 * Create a UDP socket in the specified address and start a transport. 
     852 */ 
     853PJ_DEF(pj_status_t) pjsip_udp_transport_start6(pjsip_endpoint *endpt, 
     854                                               const pj_sockaddr_in6 *local_a, 
     855                                               const pjsip_host_port *a_name, 
     856                                               unsigned async_cnt, 
     857                                               pjsip_transport **p_transport) 
     858{ 
     859    pj_sock_t sock; 
     860    pj_status_t status; 
     861    char addr_buf[PJ_INET_ADDRSTRLEN]; 
     862    pjsip_host_port bound_name; 
     863 
     864    PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL); 
     865 
     866    status = create_socket(pj_AF_INET6(), local_a, sizeof(pj_sockaddr_in6),  
     867                           &sock); 
     868    if (status != PJ_SUCCESS) 
     869        return status; 
     870 
     871    if (a_name == NULL) { 
     872        /* Address name is not specified.  
     873         * Build a name based on bound address. 
     874         */ 
     875        status = get_published_name(sock, addr_buf, sizeof(addr_buf),  
     876                                    &bound_name); 
     877        if (status != PJ_SUCCESS) { 
     878            pj_sock_close(sock); 
     879            return status; 
     880        } 
     881 
     882        a_name = &bound_name; 
     883    } 
     884 
     885    return pjsip_udp_transport_attach( endpt, sock, a_name, async_cnt,  
     886                                       p_transport); 
     887} 
    777888 
    778889/* 
     
    870981 
    871982    if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) { 
    872         char addr_buf[16]; 
     983        char addr_buf[PJ_INET_ADDRSTRLEN]; 
    873984        pjsip_host_port bound_name; 
    874985 
     
    8911002        /* Create the socket if it's not specified */ 
    8921003        if (sock == PJ_INVALID_SOCKET) { 
    893             status = create_socket(local, &sock); 
     1004            status = create_socket(pj_AF_INET(), local,  
     1005                                   sizeof(pj_sockaddr_in), &sock); 
    8941006            if (status != PJ_SUCCESS) 
    8951007                return status; 
     
    9001012         */ 
    9011013        if (a_name == NULL) { 
    902             status = get_published_name(sock, addr_buf, &bound_name); 
     1014            status = get_published_name(sock, addr_buf, sizeof(addr_buf), 
     1015                                        &bound_name); 
    9031016            if (status != PJ_SUCCESS) { 
    9041017                pj_sock_close(sock); 
Note: See TracChangeset for help on using the changeset viewer.