Changeset 1091 for pjproject/trunk


Ignore:
Timestamp:
Mar 21, 2007 9:31:01 AM (18 years ago)
Author:
bennylp
Message:

s/stun_setting/stun_config

Location:
pjproject/trunk/pjnath
Files:
1 deleted
12 edited
1 moved

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/build/pjnath.dsp

    r1090 r1091  
    112112# Begin Source File 
    113113 
    114 SOURCE=..\src\pjnath\stun_setting.c 
    115 # End Source File 
    116 # Begin Source File 
    117  
    118114SOURCE=..\src\pjnath\stun_transaction.c 
    119115# End Source File 
     
    144140# Begin Source File 
    145141 
     142SOURCE=..\include\pjnath\stun_config.h 
     143# End Source File 
     144# Begin Source File 
     145 
    146146SOURCE=..\include\pjnath\stun_doc.h 
    147147# End Source File 
     
    153153 
    154154SOURCE=..\include\pjnath\stun_session.h 
    155 # End Source File 
    156 # Begin Source File 
    157  
    158 SOURCE=..\include\pjnath\stun_setting.h 
    159155# End Source File 
    160156# Begin Source File 
  • pjproject/trunk/pjnath/build/pjstun_client.dsp

    r1062 r1091  
    4343# PROP Target_Dir "" 
    4444# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 
    45 # ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c 
     45# ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c 
    4646# ADD BASE RSC /l 0x409 /d "NDEBUG" 
    4747# ADD RSC /l 0x409 /d "NDEBUG" 
     
    6767# PROP Target_Dir "" 
    6868# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 
    69 # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /GZ /c 
     69# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /GZ /c 
    7070# ADD BASE RSC /l 0x409 /d "_DEBUG" 
    7171# ADD RSC /l 0x409 /d "_DEBUG" 
  • pjproject/trunk/pjnath/build/pjstun_srv_test.dsp

    r1062 r1091  
    4343# PROP Target_Dir "" 
    4444# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 
    45 # ADD CPP /nologo /MD /W4 /GX /O2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c 
     45# ADD CPP /nologo /MD /W4 /GX /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c 
    4646# ADD BASE RSC /l 0x409 /d "NDEBUG" 
    4747# ADD RSC /l 0x409 /d "NDEBUG" 
     
    6767# PROP Target_Dir "" 
    6868# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 
    69 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /GZ /c 
     69# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /GZ /c 
    7070# ADD BASE RSC /l 0x409 /d "_DEBUG" 
    7171# ADD RSC /l 0x409 /d "_DEBUG" 
  • pjproject/trunk/pjnath/include/pjnath.h

    r1090 r1091  
    2121#include <pjnath/errno.h> 
    2222#include <pjnath/stun_auth.h> 
    23 #include <pjnath/stun_setting.h> 
     23#include <pjnath/stun_config.h> 
    2424#include <pjnath/stun_msg.h> 
    2525#include <pjnath/stun_session.h> 
  • pjproject/trunk/pjnath/include/pjnath/stun_config.h

    r1090 r1091  
    2626 
    2727#include <pjnath/stun_msg.h> 
     28#include <pj/string.h> 
    2829 
    2930 
     
    3334/* **************************************************************************/ 
    3435/** 
    35  * @defgroup PJNATH_STUN_SETTING STUN Settings 
    36  * @brief STUN settings. 
     36 * @defgroup PJNATH_STUN_CONFIG STUN Config 
     37 * @brief STUN config 
    3738 * @ingroup PJNATH_STUN 
    3839 * @{ 
     
    4041 
    4142/** 
    42  * Opaque declaration for STUN setting. 
     43 * STUN configuration. 
    4344 */ 
    4445typedef struct pj_stun_config 
    4546{ 
    4647    /** 
    47      * Pool factory to be used by the STUN endpoint and all objects created 
    48      * that use this STUN endpoint. 
     48     * Pool factory to be used. 
    4949     */ 
    5050    pj_pool_factory     *pf; 
    5151 
    5252    /** 
    53      * Ioqueue used by this endpoint. 
     53     * Ioqueue. 
    5454     */ 
    5555    pj_ioqueue_t        *ioqueue; 
    5656 
    5757    /** 
    58      * Timer heap instance used by this endpoint. 
     58     * Timer heap instance. 
    5959     */ 
    6060    pj_timer_heap_t     *timer_heap; 
    61  
    62     /** 
    63      * Internal pool used by this endpoint. This shouldn't be used by 
    64      * application. 
    65      */ 
    66     pj_pool_t           *pool; 
    6761 
    6862    /** 
  • pjproject/trunk/pjnath/include/pjnath/stun_session.h

    r1085 r1091  
    2222#include <pjnath/stun_msg.h> 
    2323#include <pjnath/stun_auth.h> 
    24 #include <pjnath/stun_endpoint.h> 
     24#include <pjnath/stun_config.h> 
    2525#include <pjnath/stun_transaction.h> 
    2626#include <pj/list.h> 
  • pjproject/trunk/pjnath/include/pjnath/stun_transaction.h

    r1080 r1091  
    2626 
    2727#include <pjnath/stun_msg.h> 
    28 #include <pjnath/stun_endpoint.h> 
     28#include <pjnath/stun_config.h> 
    2929 
    3030 
  • pjproject/trunk/pjnath/src/pjnath/ice.c

    r1090 r1091  
    212212 
    213213 
     214static void resolver_cb(void *user_data, 
     215                        pj_status_t status, 
     216                        pj_dns_parsed_packet *response) 
     217{ 
     218    pj_assert(!"Not implemented yet!"); 
     219    PJ_UNUSED_ARG(user_data); 
     220    PJ_UNUSED_ARG(status); 
     221    PJ_UNUSED_ARG(response); 
     222} 
     223 
     224PJ_DEF(pj_status_t) pj_ice_set_srv(pj_ice *ice, 
     225                                   pj_bool_t enable_relay, 
     226                                   pj_dns_resolver *resolver, 
     227                                   const pj_str_t *domain) 
     228{ 
     229    char namebuf[128]; 
     230    char *tp_name; 
     231    pj_str_t name; 
     232    pj_status_t status; 
     233 
     234 
     235    /* Not implemented yet! */ 
     236    return PJ_ENOTSUP; 
     237 
     238 
     239    PJ_ASSERT_RETURN(ice && resolver && domain, PJ_EINVAL); 
     240 
     241    /* Must not have a running resolver. This is because we couldn't 
     242     * safely cancel the query (there is a race condition situation 
     243     * between the callback acquiring the mutex and this function 
     244     * acquiring the mutex) 
     245     */ 
     246    PJ_ASSERT_RETURN(ice->resv_q==NULL, PJ_EBUSY); 
     247 
     248    pj_mutex_lock(ice->mutex); 
     249 
     250    /* Reset resolver and server addresses */ 
     251    ice->relay_enabled = enable_relay; 
     252    ice->resv = resolver; 
     253    pj_bzero(&ice->stun_srv, sizeof(ice->stun_srv)); 
     254 
     255    /* Build SRV record name */ 
     256    if (ice->sock_type == PJ_SOCK_DGRAM) { 
     257        tp_name = "_udp"; 
     258    } else if (ice->sock_type == PJ_SOCK_STREAM) { 
     259        tp_name = "_tcp"; 
     260    } else { 
     261        pj_assert(!"Invalid sock_type"); 
     262        pj_mutex_unlock(ice->mutex); 
     263        return PJ_EBUG; 
     264    } 
     265 
     266    if (enable_relay) { 
     267        name.ptr = namebuf; 
     268        name.slen = pj_ansi_snprintf(namebuf, sizeof(namebuf), 
     269                                     "_stun-relay.%s.%.*s", 
     270                                     tp_name, 
     271                                     (int)domain->slen, 
     272                                     domain->ptr); 
     273    } else { 
     274        name.ptr = namebuf; 
     275        name.slen = pj_ansi_snprintf(namebuf, sizeof(namebuf), 
     276                                     "_stun.%s.%.*s", 
     277                                     tp_name, 
     278                                     (int)domain->slen, 
     279                                     domain->ptr); 
     280    } 
     281 
     282    if (name.slen < 1 || name.slen >= sizeof(namebuf)) { 
     283        pj_mutex_unlock(ice->mutex); 
     284        return PJ_ENAMETOOLONG; 
     285    } 
     286 
     287    /* Start DNS query */ 
     288    status = pj_dns_resolver_start_query(ice->resv, &name,  
     289                                         PJ_DNS_TYPE_SRV, 0,  
     290                                         &resolver_cb,  
     291                                         ice, &ice->resv_q); 
     292    if (status != PJ_SUCCESS) { 
     293        pj_mutex_unlock(ice->mutex); 
     294        return status; 
     295    } 
     296 
     297    pj_mutex_unlock(ice->mutex); 
     298 
     299    return PJ_SUCCESS; 
     300} 
     301 
     302 
     303PJ_DEF(pj_status_t) pj_ice_set_srv_addr(pj_ice *ice, 
     304                                        pj_bool_t enable_relay, 
     305                                        const pj_sockaddr_t *srv_addr, 
     306                                        unsigned addr_len) 
     307{ 
     308    PJ_ASSERT_RETURN(ice && srv_addr, PJ_EINVAL); 
     309    /* Must not have a running resolver. This is because we couldn't 
     310     * safely cancel the query (there is a race condition situation 
     311     * between the callback acquiring the mutex and this function 
     312     * acquiring the mutex) 
     313     */ 
     314    PJ_ASSERT_RETURN(ice->resv_q==NULL, PJ_EBUSY); 
     315 
     316    pj_mutex_lock(ice->mutex); 
     317 
     318    ice->relay_enabled = enable_relay; 
     319    pj_memcpy(&ice->stun_srv, srv_addr, addr_len); 
     320 
     321    pj_mutex_unlock(ice->mutex); 
     322 
     323    return PJ_SUCCESS; 
     324 
     325} 
     326 
     327 
     328 
     329PJ_DEF(pj_status_t) pj_ice_add_comp(pj_ice *ice, 
     330                                    unsigned comp_id, 
     331                                    const pj_sockaddr_t *local_addr, 
     332                                    unsigned addr_len) 
     333{ 
     334    pj_status_t status; 
     335    pj_sock_t sock; 
     336 
     337    PJ_ASSERT_RETURN(ice && local_addr && addr_len, PJ_EINVAL); 
     338 
     339    status = pj_sock_socket(ice->af, ice->sock_type, 0, &sock); 
     340    if (status != PJ_SUCCESS) 
     341        return status; 
     342 
     343    status = pj_sock_bind(sock, local_addr, addr_len); 
     344    if (status != PJ_SUCCESS) 
     345        return status; 
     346 
     347    status = pj_ice_add_sock_comp(ice, comp_id, sock); 
     348    if (status != PJ_SUCCESS) { 
     349        pj_sock_close(sock); 
     350        return status; 
     351    } 
     352 
     353    return PJ_SUCCESS; 
     354} 
     355 
     356typedef struct stun_data 
     357{ 
     358    pj_ice      *ice; 
     359    unsigned     comp_id; 
     360    pj_ice_comp *comp; 
     361} stun_data; 
     362 
     363 
     364PJ_DEF(pj_status_t) pj_ice_add_sock_comp( pj_ice *ice, 
     365                                          unsigned comp_id, 
     366                                          pj_sock_t sock) 
     367{ 
     368    pj_stun_session_cb sess_cb; 
     369    pj_ice_comp *comp; 
     370    pj_stun_auth_cred auth_cred; 
     371    stun_data *sd; 
     372    int addr_len; 
     373    pj_status_t status; 
     374 
     375    PJ_ASSERT_RETURN(ice && sock != PJ_INVALID_SOCKET, PJ_EINVAL); 
     376    PJ_ASSERT_RETURN(ice->comp_cnt < PJ_ARRAY_SIZE(ice->comp), PJ_ETOOMANY); 
     377 
     378    pj_mutex_lock(ice->mutex); 
     379 
     380    comp = &ice->comp[ice->comp_cnt]; 
     381    comp->comp_id = comp_id; 
     382    comp->sock = sock; 
     383 
     384    addr_len = sizeof(comp->local_addr); 
     385    status = pj_sock_getsockname(sock, &comp->local_addr, &addr_len); 
     386    if (status != PJ_SUCCESS) { 
     387        pj_mutex_unlock(ice->mutex); 
     388        return status; 
     389    } 
     390 
     391 
     392    /* Init STUN callbacks */ 
     393    pj_bzero(&sess_cb, sizeof(sess_cb)); 
     394    sess_cb.on_request_complete = &on_stun_request_complete; 
     395    sess_cb.on_rx_indication = &on_stun_rx_indication; 
     396    sess_cb.on_rx_request = &on_stun_rx_request; 
     397    sess_cb.on_send_msg = &on_stun_send_msg; 
     398 
     399    /* Create STUN session for this component */ 
     400    status = pj_stun_session_create(&ice->stun_cfg, ice->obj_name,  
     401                                    &sess_cb, PJ_FALSE, 
     402                                    &comp->stun_sess); 
     403    if (status != PJ_SUCCESS) { 
     404        pj_mutex_unlock(ice->mutex); 
     405        return status; 
     406    } 
     407 
     408    /* Associate data with this STUN session */ 
     409    sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data); 
     410    sd->ice = ice; 
     411    sd->comp_id = comp_id; 
     412    sd->comp = comp; 
     413    pj_stun_session_set_user_data(comp->stun_sess, sd); 
     414 
     415    /* Init STUN authentication credential */ 
     416    pj_bzero(&auth_cred, sizeof(auth_cred)); 
     417    auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 
     418    auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth; 
     419    auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred; 
     420    auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 
     421    auth_cred.data.dyn_cred.verify_nonce = &stun_auth_verify_nonce; 
     422    auth_cred.data.dyn_cred.user_data = comp->stun_sess; 
     423    pj_stun_session_set_credential(comp->stun_sess, &auth_cred); 
     424 
     425    /* Done */ 
     426    ice->comp_cnt++; 
     427    pj_mutex_unlock(ice->mutex); 
     428 
     429    return PJ_SUCCESS; 
     430} 
     431 
     432 
     433static pj_status_t stun_auth_get_auth(void *user_data, 
     434                                      pj_pool_t *pool, 
     435                                      pj_str_t *realm, 
     436                                      pj_str_t *nonce) 
     437{ 
     438    PJ_UNUSED_ARG(user_data); 
     439    PJ_UNUSED_ARG(pool); 
     440 
     441    realm->slen = 0; 
     442    nonce->slen = 0; 
     443 
     444    return PJ_SUCCESS; 
     445} 
     446 
     447 
     448/* Get credential to be sent with outgoing message */ 
     449static pj_status_t stun_auth_get_cred(const pj_stun_msg *msg, 
     450                                      void *user_data, 
     451                                      pj_pool_t *pool, 
     452                                      pj_str_t *realm, 
     453                                      pj_str_t *username, 
     454                                      pj_str_t *nonce, 
     455                                      int *data_type, 
     456                                      pj_str_t *data) 
     457{ 
     458    pj_stun_session *sess = (pj_stun_session *)user_data; 
     459    stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess); 
     460    pj_ice *ice = sd->ice; 
     461 
     462    PJ_UNUSED_ARG(pool); 
     463    realm->slen = nonce->slen = 0; 
     464 
     465    if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || 
     466        PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) 
     467    { 
     468        /* Outgoing responses need to have the same credential as 
     469         * incoming requests. 
     470         */ 
     471        *username = ice->rx_uname; 
     472        *data_type = 0; 
     473        *data = ice->rx_pass; 
     474    } 
     475    else { 
     476        *username = ice->tx_uname; 
     477        *data_type = 0; 
     478        *data = ice->tx_pass; 
     479    } 
     480 
     481    return PJ_SUCCESS; 
     482} 
     483 
     484/* Get password to be used to authenticate incoming message */ 
     485static pj_status_t stun_auth_get_password(const pj_stun_msg *msg, 
     486                                          void *user_data,  
     487                                          const pj_str_t *realm, 
     488                                          const pj_str_t *username, 
     489                                          pj_pool_t *pool, 
     490                                          int *data_type, 
     491                                          pj_str_t *data) 
     492{ 
     493    pj_stun_session *sess = (pj_stun_session *)user_data; 
     494    stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess); 
     495    pj_ice *ice = sd->ice; 
     496 
     497    PJ_UNUSED_ARG(realm); 
     498    PJ_UNUSED_ARG(pool); 
     499 
     500    if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || 
     501        PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) 
     502    { 
     503        /* Incoming response is authenticated with TX credential */ 
     504        /* Verify username */ 
     505        if (pj_strcmp(username, &ice->tx_uname) != 0) 
     506            return -1; 
     507        *data_type = 0; 
     508        *data = ice->tx_pass; 
     509 
     510    } else { 
     511        /* Incoming request is authenticated with RX credential */ 
     512        /* The agent MUST accept a credential if the username consists 
     513         * of two values separated by a colon, where the first value is 
     514         * equal to the username fragment generated by the agent in an offer 
     515         * or answer for a session in-progress, and the MESSAGE-INTEGRITY  
     516         * is the output of a hash of the password and the STUN packet's  
     517         * contents.  
     518         */ 
     519        PJ_TODO(CHECK_USERNAME_FOR_INCOMING_STUN_REQUEST); 
     520        *data_type = 0; 
     521        *data = ice->rx_pass; 
     522 
     523    } 
     524 
     525    return PJ_SUCCESS; 
     526} 
     527 
     528 
     529static pj_bool_t stun_auth_verify_nonce(const pj_stun_msg *msg, 
     530                                        void *user_data, 
     531                                        const pj_str_t *realm, 
     532                                        const pj_str_t *username, 
     533                                        const pj_str_t *nonce) 
     534{ 
     535    /* We don't use NONCE */ 
     536    PJ_UNUSED_ARG(msg); 
     537    PJ_UNUSED_ARG(user_data); 
     538    PJ_UNUSED_ARG(realm); 
     539    PJ_UNUSED_ARG(username); 
     540    PJ_UNUSED_ARG(nonce); 
     541    return PJ_TRUE; 
     542} 
     543 
     544 
     545PJ_DEF(pj_status_t) pj_ice_set_credentials(pj_ice *ice, 
     546                                           const pj_str_t *local_ufrag, 
     547                                           const pj_str_t *local_pass, 
     548                                           const pj_str_t *remote_ufrag, 
     549                                           const pj_str_t *remote_pass) 
     550{ 
     551    char buf[128]; 
     552    pj_str_t username; 
     553 
     554    username.ptr = buf; 
     555 
     556    PJ_ASSERT_RETURN(ice && local_ufrag && local_pass && 
     557                     remote_ufrag && remote_pass, PJ_EINVAL); 
     558    PJ_ASSERT_RETURN(local_ufrag->slen + remote_ufrag->slen < 
     559                     sizeof(buf), PJ_ENAMETOOLONG); 
     560 
     561    pj_strcpy(&username, remote_ufrag); 
     562    pj_strcat2(&username, ":"); 
     563    pj_strcat(&username, local_ufrag); 
     564 
     565    pj_strdup(ice->pool, &ice->tx_uname, &username); 
     566    pj_strdup(ice->pool, &ice->tx_pass, remote_pass); 
     567 
     568    pj_strcpy(&username, local_ufrag); 
     569    pj_strcat2(&username, ":"); 
     570    pj_strcat(&username, remote_ufrag); 
     571 
     572    pj_strdup(ice->pool, &ice->rx_uname, &username); 
     573    pj_strdup(ice->pool, &ice->rx_pass, local_pass); 
     574 
     575    return PJ_SUCCESS; 
     576} 
     577 
     578 
     579static pj_status_t gather_host_cands(pj_ice *ice) 
     580{ 
     581    unsigned i; 
     582    pj_status_t status; 
     583 
     584    for (i=0; i<ice->comp_cnt; ++i) { 
     585        pj_ice_comp *comp = &ice->comp[i]; 
     586        pj_sockaddr addr; 
     587        int addr_len; 
     588 
     589        addr_len = sizeof(addr); 
     590        status = pj_sock_getsockname(comp->sock, &addr, &addr_len); 
     591        if (status != PJ_SUCCESS) 
     592            return status; 
     593 
     594        if (addr.ipv4.sin_addr.s_addr == 0) { 
     595            status = pj_gethostip(&addr.ipv4.sin_addr); 
     596            if (status != PJ_SUCCESS) 
     597                return status; 
     598        } 
     599 
     600        status = pj_ice_add_cand(ice, i, PJ_ICE_CAND_TYPE_HOST, 65535, 
     601                                 &host_foundation, &addr, &addr, NULL, 
     602                                 sizeof(pj_sockaddr_in), NULL); 
     603        if (status != PJ_SUCCESS) 
     604            return status; 
     605    } 
     606 
     607    return PJ_SUCCESS; 
     608} 
     609 
     610/* Eliminate redundant candidates. */ 
     611static void eliminate_redundant_cand(unsigned *cnt, 
     612                                     pj_ice_cand cand[]) 
     613{ 
     614 
     615    /* A candidate is redundant if its transport address equals another  
     616     * candidate, and its base equals the base of that other candidate. 
     617     * Note that two candidates can have the same transport address yet 
     618     * have different bases, and these would not be considered redundant. 
     619     */ 
     620    PJ_TODO(ELIMINATE_REDUNDANT_CANDIDATES); 
     621    PJ_UNUSED_ARG(cnt); 
     622    PJ_UNUSED_ARG(cand); 
     623} 
     624 
     625 
     626PJ_DEF(pj_status_t) pj_ice_start_gather(pj_ice *ice, 
     627                                        unsigned flags) 
     628{ 
     629    pj_status_t status; 
     630 
     631    PJ_UNUSED_ARG(flags); 
     632 
     633    /* Gather host candidate */ 
     634    status = gather_host_cands(ice); 
     635    if (status != PJ_SUCCESS) 
     636        return status; 
     637 
     638    /* Eliminate redundant host candidates. */ 
     639    eliminate_redundant_cand(&ice->lcand_cnt, ice->lcand); 
     640 
     641    PJ_TODO(GATHER_MAPPED_AND_RELAYED_CANDIDATES); 
     642 
     643    return PJ_SUCCESS; 
     644} 
     645 
     646 
     647static pj_uint32_t CALC_CAND_PRIO(pj_ice_cand_type type, 
     648                                  pj_uint32_t local_pref, 
     649                                  pj_uint32_t comp_id) 
     650{ 
     651    static pj_uint32_t type_pref[] = 
     652    { 
     653        PJ_ICE_HOST_PREF, 
     654        PJ_ICE_MAPPED_PREF, 
     655        PJ_ICE_PEER_MAPPED_PREF, 
     656        PJ_ICE_RELAYED_PREF 
     657    }; 
     658 
     659    return ((1 << 24) * type_pref[type]) +  
     660           ((1 << 8) * local_pref) + 
     661           (256 - comp_id); 
     662} 
     663 
     664 
     665PJ_DEF(pj_status_t) pj_ice_add_cand(pj_ice *ice, 
     666                                    unsigned comp_id, 
     667                                    pj_ice_cand_type type, 
     668                                    pj_uint16_t local_pref, 
     669                                    const pj_str_t *foundation, 
     670                                    const pj_sockaddr_t *addr, 
     671                                    const pj_sockaddr_t *base_addr, 
     672                                    const pj_sockaddr_t *srv_addr, 
     673                                    int addr_len, 
     674                                    unsigned *p_cand_id) 
     675{ 
     676    pj_ice_cand *lcand; 
     677    pj_status_t status = PJ_SUCCESS; 
     678    char tmp[128]; 
     679 
     680    PJ_ASSERT_RETURN(ice && comp_id && type && local_pref && 
     681                     foundation && addr && base_addr && addr_len, 
     682                     PJ_EINVAL); 
     683 
     684    pj_mutex_lock(ice->mutex); 
     685 
     686    if (ice->lcand_cnt >= PJ_ARRAY_SIZE(ice->lcand)) { 
     687        status = PJ_ETOOMANY; 
     688        goto on_error; 
     689    } 
     690 
     691    lcand = &ice->lcand[ice->lcand_cnt]; 
     692    lcand->comp_id = comp_id; 
     693    lcand->type = type; 
     694    pj_strdup(ice->pool, &lcand->foundation, foundation); 
     695    lcand->prio = CALC_CAND_PRIO(type, local_pref, lcand->comp_id); 
     696    pj_memcpy(&lcand->addr, addr, addr_len); 
     697    pj_memcpy(&lcand->base_addr, base_addr, addr_len); 
     698    if (srv_addr) 
     699        pj_memcpy(&lcand->srv_addr, srv_addr, addr_len); 
     700    else 
     701        pj_bzero(&lcand->srv_addr, sizeof(lcand->srv_addr)); 
     702 
     703    if (p_cand_id) 
     704        *p_cand_id = ice->lcand_cnt; 
     705 
     706    pj_ansi_strcpy(tmp, pj_inet_ntoa(lcand->addr.ipv4.sin_addr)); 
     707    LOG((ice->obj_name,  
     708         "Candidate %d added: comp_id=%d, type=%s, foundation=%.*s, " 
     709         "addr=%s:%d, base=%s:%d, prio=0x%x (%u)", 
     710         ice->lcand_cnt,  
     711         lcand->comp_id,  
     712         cand_type_names[lcand->type], 
     713         (int)lcand->foundation.slen, 
     714         lcand->foundation.ptr, 
     715         tmp,  
     716         (int)pj_ntohs(lcand->addr.ipv4.sin_port), 
     717         pj_inet_ntoa(lcand->base_addr.ipv4.sin_addr), 
     718         (int)pj_htons(lcand->base_addr.ipv4.sin_port), 
     719         lcand->prio, lcand->prio)); 
     720 
     721    ++ice->lcand_cnt; 
     722 
     723on_error: 
     724    pj_mutex_unlock(ice->mutex); 
     725    return status; 
     726} 
     727 
     728 
     729PJ_DEF(unsigned) pj_ice_get_cand_cnt(pj_ice *ice) 
     730{ 
     731    return ice->lcand_cnt; 
     732} 
     733 
     734 
     735PJ_DEF(pj_status_t) pj_ice_enum_cands(pj_ice *ice, 
     736                                      unsigned *p_count, 
     737                                      unsigned cand_ids[]) 
     738{ 
     739    unsigned i, count; 
     740 
     741    PJ_ASSERT_RETURN(ice && p_count && *p_count && cand_ids, PJ_EINVAL); 
     742 
     743    pj_mutex_lock(ice->mutex); 
     744 
     745    count = (*p_count < ice->lcand_cnt) ? *p_count : ice->lcand_cnt; 
     746    for (i=0; i<count; ++i) 
     747        cand_ids[i] = i; 
     748 
     749    *p_count = count; 
     750    pj_mutex_unlock(ice->mutex); 
     751 
     752    return PJ_SUCCESS; 
     753} 
     754 
     755 
     756PJ_DEF(pj_status_t) pj_ice_get_default_cand(pj_ice *ice, 
     757                                            unsigned comp_id, 
     758                                            int *cand_id) 
     759{ 
     760    PJ_ASSERT_RETURN(ice && comp_id && cand_id, PJ_EINVAL); 
     761 
     762    pj_mutex_lock(ice->mutex); 
     763 
     764    /* First find in valid list if we have nominated pair */ 
     765 
     766    /* If there's no nominated pair, find relayed candidate */ 
     767 
     768    /* If there's no relayed candidate, find server reflexive candidate */ 
     769 
     770    /* Otherwise return host candidate */ 
     771 
     772    pj_assert(!"Not implemented yet"); 
     773    PJ_TODO(IMPLEMENT_GET_DEFAULT_CAND); 
     774 
     775    pj_mutex_unlock(ice->mutex); 
     776 
     777    return PJ_SUCCESS; 
     778} 
     779 
     780 
     781PJ_DEF(pj_status_t) pj_ice_get_cand(pj_ice *ice, 
     782                                    unsigned cand_id, 
     783                                    pj_ice_cand **p_cand) 
     784{ 
     785    PJ_ASSERT_RETURN(ice && p_cand, PJ_EINVAL); 
     786    PJ_ASSERT_RETURN(cand_id <= ice->lcand_cnt, PJ_EINVAL); 
     787 
     788    *p_cand = &ice->lcand[cand_id]; 
     789 
     790    return PJ_SUCCESS; 
     791} 
     792 
     793#ifndef MIN 
     794#   define MIN(a,b) (a < b ? a : b) 
     795#endif 
     796 
     797#ifndef MAX 
     798#   define MAX(a,b) (a > b ? a : b) 
     799#endif 
     800 
     801static pj_uint64_t CALC_CHECK_PRIO(const pj_ice *ice,  
     802                                   const pj_ice_cand *lcand, 
     803                                   const pj_ice_cand *rcand) 
     804{ 
     805    pj_uint32_t O, A; 
     806 
     807    if (ice->role == PJ_ICE_ROLE_CONTROLLING) { 
     808        O = lcand->prio;  
     809        A = rcand->prio; 
     810    } else { 
     811        O = rcand->prio; 
     812        A = lcand->prio; 
     813    } 
     814 
     815    return ((pj_uint64_t)1 << 32) * MIN(O, A) + 
     816           (pj_uint64_t)2 * MAX(O, A) + (O>A ? 1 : 0); 
     817} 
     818 
     819static const char *dump_check(char *buffer, unsigned bufsize, 
     820                              const pj_ice_check *check) 
     821{ 
     822    const pj_ice_cand *lcand = check->lcand; 
     823    const pj_ice_cand *rcand = check->rcand; 
     824    char laddr[CHECK_NAME_LEN]; 
     825    int len; 
     826 
     827    pj_ansi_strcpy(laddr, pj_inet_ntoa(lcand->addr.ipv4.sin_addr)); 
     828 
     829    if (lcand->addr.addr.sa_family == PJ_AF_INET) { 
     830        len = pj_ansi_snprintf(buffer, bufsize, 
     831                               "%s:%d-->%s:%d", 
     832                               laddr, (int)pj_ntohs(lcand->addr.ipv4.sin_port), 
     833                               pj_inet_ntoa(rcand->addr.ipv4.sin_addr), 
     834                               (int)pj_ntohs(rcand->addr.ipv4.sin_port)); 
     835    } else { 
     836        len = pj_ansi_snprintf(buffer, bufsize, "IPv6->IPv6"); 
     837    } 
     838 
     839 
     840    if (len < 0) 
     841        len = 0; 
     842    else if (len >= (int)bufsize) 
     843        len = bufsize - 1; 
     844 
     845    buffer[len] = '\0'; 
     846    return buffer; 
     847} 
     848 
     849#if PJ_LOG_MAX_LEVEL >= 4 
     850static void dump_checklist(const char *title, const pj_ice *ice,  
     851                           const pj_ice_checklist *clist) 
     852{ 
     853    unsigned i; 
     854    char buffer[CHECK_NAME_LEN]; 
     855 
     856    LOG((ice->obj_name, "%s", title)); 
     857    for (i=0; i<clist->count; ++i) { 
     858        const pj_ice_check *c = &clist->checks[i]; 
     859        LOG((ice->obj_name, " %d: %s (prio=%u, state=%s)", 
     860             i, dump_check(buffer, sizeof(buffer), c), 
     861             c->prio, check_state_name[c->state])); 
     862    } 
     863} 
     864#else 
     865#define dump_checklist(ice, clist) 
     866#endif 
     867 
     868static void check_set_state(pj_ice *ice, pj_ice_check *check, 
     869                            pj_ice_check_state st,  
     870                            pj_status_t err_code) 
     871{ 
     872    char buf[CHECK_NAME_LEN]; 
     873    LOG((ice->obj_name, "Check %s: state changed from %s to %s", 
     874         dump_check(buf, sizeof(buf), check), 
     875         check_state_name[check->state], 
     876         check_state_name[st])); 
     877    check->state = st; 
     878    check->err_code = err_code; 
     879} 
     880 
     881static void clist_set_state(pj_ice *ice, pj_ice_checklist *clist, 
     882                            pj_ice_checklist_state st) 
     883{ 
     884    LOG((ice->obj_name, "Checklist: state changed from %s to %s", 
     885         clist_state_name[clist->state], 
     886         clist_state_name[st])); 
     887    clist->state = st; 
     888} 
     889 
     890/* Sort checklist based on priority */ 
     891static void sort_checklist(pj_ice_checklist *clist) 
     892{ 
     893    unsigned i; 
     894 
     895    for (i=0; i<clist->count-1; ++i) { 
     896        unsigned j, highest = i; 
     897        for (j=i+1; j<clist->count; ++j) { 
     898            if (clist->checks[j].prio > clist->checks[highest].prio) { 
     899                highest = j; 
     900            } 
     901        } 
     902 
     903        if (highest != i) { 
     904            pj_ice_check tmp; 
     905 
     906            pj_memcpy(&tmp, &clist->checks[i], sizeof(pj_ice_check)); 
     907            pj_memcpy(&clist->checks[i], &clist->checks[highest],  
     908                      sizeof(pj_ice_check)); 
     909            pj_memcpy(&clist->checks[highest], &tmp, sizeof(pj_ice_check)); 
     910        } 
     911    } 
     912} 
     913 
     914/* Sort valid list based on priority */ 
     915static void sort_valid_list(pj_ice *ice) 
     916{ 
     917    unsigned i; 
     918 
     919    for (i=0; i<ice->valid_cnt-1; ++i) { 
     920        unsigned j, highest = i; 
     921        pj_ice_check *ci = &ice->clist.checks[ice->valid_list[i]]; 
     922 
     923        for (j=i+1; j<ice->valid_cnt; ++j) { 
     924            pj_ice_check *cj = &ice->clist.checks[ice->valid_list[j]]; 
     925 
     926            if (cj->prio > ci->prio) { 
     927                highest = j; 
     928            } 
     929        } 
     930 
     931        if (highest != i) { 
     932            unsigned tmp = ice->valid_list[i]; 
     933            ice->valid_list[i] = ice->valid_list[j]; 
     934            ice->valid_list[j] = tmp; 
     935        } 
     936    } 
     937} 
     938 
     939 
     940enum  
     941{  
     942    SOCKADDR_EQUAL = 0,  
     943    SOCKADDR_NOT_EQUAL = 1  
     944}; 
     945 
     946/* Utility: compare sockaddr. 
     947 * Returns 0 if equal. 
     948 */ 
     949static int sockaddr_cmp(const pj_sockaddr *a1, const pj_sockaddr *a2) 
     950{ 
     951    if (a1->addr.sa_family != a2->addr.sa_family) 
     952        return SOCKADDR_NOT_EQUAL; 
     953 
     954    if (a1->addr.sa_family == PJ_AF_INET) { 
     955        return !(a1->ipv4.sin_addr.s_addr == a2->ipv4.sin_addr.s_addr && 
     956                 a1->ipv4.sin_port == a2->ipv4.sin_port); 
     957    } else if (a1->addr.sa_family == PJ_AF_INET6) { 
     958        return pj_memcmp(&a1->ipv6, &a2->ipv6, sizeof(a1->ipv6)); 
     959    } else { 
     960        pj_assert(!"Invalid address family!"); 
     961        return SOCKADDR_NOT_EQUAL; 
     962    } 
     963} 
     964 
     965 
     966/* Prune checklist, this must have been done after the checklist 
     967 * is sorted. 
     968 */ 
     969static void prune_checklist(pj_ice *ice, pj_ice_checklist *clist) 
     970{ 
     971    unsigned i; 
     972 
     973    /* Since an agent cannot send requests directly from a reflexive 
     974     * candidate, but only from its base, the agent next goes through the 
     975     * sorted list of candidate pairs.  For each pair where the local 
     976     * candidate is server reflexive, the server reflexive candidate MUST be 
     977     * replaced by its base.  Once this has been done, the agent MUST prune 
     978     * the list.  This is done by removing a pair if its local and remote 
     979     * candidates are identical to the local and remote candidates of a pair 
     980     * higher up on the priority list.  The result is a sequence of ordered 
     981     * candidate pairs, called the check list for that media stream.     
     982     */ 
     983    for (i=0; i<clist->count; ++i) { 
     984        pj_ice_cand *licand = clist->checks[i].lcand; 
     985        pj_ice_cand *ricand = clist->checks[i].rcand; 
     986        const pj_sockaddr *liaddr; 
     987        unsigned j; 
     988 
     989        if (licand->type == PJ_ICE_CAND_TYPE_MAPPED) 
     990            liaddr = &licand->base_addr; 
     991        else 
     992            liaddr = &licand->addr; 
     993 
     994        for (j=i+1; j<clist->count;) { 
     995            pj_ice_cand *ljcand = clist->checks[j].lcand; 
     996            pj_ice_cand *rjcand = clist->checks[j].rcand; 
     997            const pj_sockaddr *ljaddr; 
     998 
     999            if (ljcand->type == PJ_ICE_CAND_TYPE_MAPPED) 
     1000                ljaddr = &licand->base_addr; 
     1001            else 
     1002                ljaddr = &licand->addr; 
     1003 
     1004            if (sockaddr_cmp(liaddr, ljaddr) == SOCKADDR_EQUAL && 
     1005                sockaddr_cmp(&ricand->addr, &rjcand->addr) == SOCKADDR_EQUAL) 
     1006            { 
     1007                /* Found duplicate, remove it */ 
     1008                char buf[CHECK_NAME_LEN]; 
     1009 
     1010                LOG((ice->obj_name, "Check %s pruned", 
     1011                    dump_check(buf, sizeof(buf), &clist->checks[j]))); 
     1012 
     1013                pj_array_erase(clist->checks, sizeof(clist->checks[0]), 
     1014                               clist->count, j); 
     1015                --clist->count; 
     1016 
     1017            } else { 
     1018                ++j; 
     1019            } 
     1020        } 
     1021    } 
     1022} 
     1023 
    2141024/* This function is called when ICE processing completes */ 
    2151025static void on_ice_complete(pj_ice *ice, pj_status_t status) 
     
    2351045    if (check->nominated) { 
    2361046        for (i=0; i<ice->clist.count; ++i) { 
    237             pj_ice_check *c; 
     1047            pj_ice_check *c = &ice->clist.checks[i]; 
    2381048            if (c->lcand->comp_id == check->lcand->comp_id && 
    2391049                (c->state==PJ_ICE_CHECK_STATE_FROZEN || 
    240                  c->state==PJ_ICE_CHECK_STATE_WAITING) 
     1050                 c->state==PJ_ICE_CHECK_STATE_WAITING)) 
    2411051            { 
    2421052                check_set_state(ice, check, PJ_ICE_CHECK_STATE_FAILED, 
     
    2811091     */ 
    2821092    for (i=0; i<ice->valid_cnt; ++i) { 
    283         pj_ice_check *c = ice->clist.checks[ice->valid_list[i]]; 
     1093        pj_ice_check *c = &ice->clist.checks[ice->valid_list[i]]; 
    2841094        if (c->lcand->comp_id == 1) 
    2851095            break; 
     
    3141124 
    3151125 
    316 static void resolver_cb(void *user_data, 
    317                         pj_status_t status, 
    318                         pj_dns_parsed_packet *response) 
    319 { 
    320     pj_assert(!"Not implemented yet!"); 
    321     PJ_UNUSED_ARG(user_data); 
    322     PJ_UNUSED_ARG(status); 
    323     PJ_UNUSED_ARG(response); 
    324 } 
    325  
    326 PJ_DEF(pj_status_t) pj_ice_set_srv(pj_ice *ice, 
    327                                    pj_bool_t enable_relay, 
    328                                    pj_dns_resolver *resolver, 
    329                                    const pj_str_t *domain) 
    330 { 
    331     char namebuf[128]; 
    332     char *tp_name; 
    333     pj_str_t name; 
    334     pj_status_t status; 
    335  
    336  
    337     /* Not implemented yet! */ 
    338     return PJ_ENOTSUP; 
    339  
    340  
    341     PJ_ASSERT_RETURN(ice && resolver && domain, PJ_EINVAL); 
    342  
    343     /* Must not have a running resolver. This is because we couldn't 
    344      * safely cancel the query (there is a race condition situation 
    345      * between the callback acquiring the mutex and this function 
    346      * acquiring the mutex) 
    347      */ 
    348     PJ_ASSERT_RETURN(ice->resv_q==NULL, PJ_EBUSY); 
    349  
    350     pj_mutex_lock(ice->mutex); 
    351  
    352     /* Reset resolver and server addresses */ 
    353     ice->relay_enabled = enable_relay; 
    354     ice->resv = resolver; 
    355     pj_bzero(&ice->stun_srv, sizeof(ice->stun_srv)); 
    356  
    357     /* Build SRV record name */ 
    358     if (ice->sock_type == PJ_SOCK_DGRAM) { 
    359         tp_name = "_udp"; 
    360     } else if (ice->sock_type == PJ_SOCK_STREAM) { 
    361         tp_name = "_tcp"; 
    362     } else { 
    363         pj_assert(!"Invalid sock_type"); 
    364         pj_mutex_unlock(ice->mutex); 
    365         return PJ_EBUG; 
    366     } 
    367  
    368     if (enable_relay) { 
    369         name.ptr = namebuf; 
    370         name.slen = pj_ansi_snprintf(namebuf, sizeof(namebuf), 
    371                                      "_stun-relay.%s.%.*s", 
    372                                      tp_name, 
    373                                      (int)domain->slen, 
    374                                      domain->ptr); 
    375     } else { 
    376         name.ptr = namebuf; 
    377         name.slen = pj_ansi_snprintf(namebuf, sizeof(namebuf), 
    378                                      "_stun.%s.%.*s", 
    379                                      tp_name, 
    380                                      (int)domain->slen, 
    381                                      domain->ptr); 
    382     } 
    383  
    384     if (name.slen < 1 || name.slen >= sizeof(namebuf)) { 
    385         pj_mutex_unlock(ice->mutex); 
    386         return PJ_ENAMETOOLONG; 
    387     } 
    388  
    389     /* Start DNS query */ 
    390     status = pj_dns_resolver_start_query(ice->resv, &name,  
    391                                          PJ_DNS_TYPE_SRV, 0,  
    392                                          &resolver_cb,  
    393                                          ice, &ice->resv_q); 
    394     if (status != PJ_SUCCESS) { 
    395         pj_mutex_unlock(ice->mutex); 
    396         return status; 
    397     } 
    398  
    399     pj_mutex_unlock(ice->mutex); 
    400  
    401     return PJ_SUCCESS; 
    402 } 
    403  
    404  
    405 PJ_DEF(pj_status_t) pj_ice_set_srv_addr(pj_ice *ice, 
    406                                         pj_bool_t enable_relay, 
    407                                         const pj_sockaddr_t *srv_addr, 
    408                                         unsigned addr_len) 
    409 { 
    410     PJ_ASSERT_RETURN(ice && srv_addr, PJ_EINVAL); 
    411     /* Must not have a running resolver. This is because we couldn't 
    412      * safely cancel the query (there is a race condition situation 
    413      * between the callback acquiring the mutex and this function 
    414      * acquiring the mutex) 
    415      */ 
    416     PJ_ASSERT_RETURN(ice->resv_q==NULL, PJ_EBUSY); 
    417  
    418     pj_mutex_lock(ice->mutex); 
    419  
    420     ice->relay_enabled = enable_relay; 
    421     pj_memcpy(&ice->stun_srv, srv_addr, addr_len); 
    422  
    423     pj_mutex_unlock(ice->mutex); 
    424  
    425     return PJ_SUCCESS; 
    426  
    427 } 
    428  
    429  
    430  
    431 PJ_DEF(pj_status_t) pj_ice_add_comp(pj_ice *ice, 
    432                                     unsigned comp_id, 
    433                                     const pj_sockaddr_t *local_addr, 
    434                                     unsigned addr_len) 
    435 { 
    436     pj_status_t status; 
    437     pj_sock_t sock; 
    438  
    439     PJ_ASSERT_RETURN(ice && local_addr && addr_len, PJ_EINVAL); 
    440  
    441     status = pj_sock_socket(ice->af, ice->sock_type, 0, &sock); 
    442     if (status != PJ_SUCCESS) 
    443         return status; 
    444  
    445     status = pj_sock_bind(sock, local_addr, addr_len); 
    446     if (status != PJ_SUCCESS) 
    447         return status; 
    448  
    449     status = pj_ice_add_sock_comp(ice, comp_id, sock); 
    450     if (status != PJ_SUCCESS) { 
    451         pj_sock_close(sock); 
    452         return status; 
    453     } 
    454  
    455     return PJ_SUCCESS; 
    456 } 
    457  
    458 typedef struct stun_data 
    459 { 
    460     pj_ice      *ice; 
    461     unsigned     comp_id; 
    462     pj_ice_comp *comp; 
    463 } stun_data; 
    464  
    465  
    466 PJ_DEF(pj_status_t) pj_ice_add_sock_comp( pj_ice *ice, 
    467                                           unsigned comp_id, 
    468                                           pj_sock_t sock) 
    469 { 
    470     pj_stun_session_cb sess_cb; 
    471     pj_ice_comp *comp; 
    472     pj_stun_auth_cred auth_cred; 
    473     stun_data *sd; 
    474     int addr_len; 
    475     pj_status_t status; 
    476  
    477     PJ_ASSERT_RETURN(ice && sock != PJ_INVALID_SOCKET, PJ_EINVAL); 
    478     PJ_ASSERT_RETURN(ice->comp_cnt < PJ_ARRAY_SIZE(ice->comp), PJ_ETOOMANY); 
    479  
    480     pj_mutex_lock(ice->mutex); 
    481  
    482     comp = &ice->comp[ice->comp_cnt]; 
    483     comp->comp_id = comp_id; 
    484     comp->sock = sock; 
    485  
    486     addr_len = sizeof(comp->local_addr); 
    487     status = pj_sock_getsockname(sock, &comp->local_addr, &addr_len); 
    488     if (status != PJ_SUCCESS) { 
    489         pj_mutex_unlock(ice->mutex); 
    490         return status; 
    491     } 
    492  
    493  
    494     /* Init STUN callbacks */ 
    495     pj_bzero(&sess_cb, sizeof(sess_cb)); 
    496     sess_cb.on_request_complete = &on_stun_request_complete; 
    497     sess_cb.on_rx_indication = &on_stun_rx_indication; 
    498     sess_cb.on_rx_request = &on_stun_rx_request; 
    499     sess_cb.on_send_msg = &on_stun_send_msg; 
    500  
    501     /* Create STUN session for this component */ 
    502     status = pj_stun_session_create(&ice->stun_cfg, ice->obj_name,  
    503                                     &sess_cb, PJ_FALSE, 
    504                                     &comp->stun_sess); 
    505     if (status != PJ_SUCCESS) { 
    506         pj_mutex_unlock(ice->mutex); 
    507         return status; 
    508     } 
    509  
    510     /* Associate data with this STUN session */ 
    511     sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data); 
    512     sd->ice = ice; 
    513     sd->comp_id = comp_id; 
    514     sd->comp = comp; 
    515     pj_stun_session_set_user_data(comp->stun_sess, sd); 
    516  
    517     /* Init STUN authentication credential */ 
    518     pj_bzero(&auth_cred, sizeof(auth_cred)); 
    519     auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 
    520     auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth; 
    521     auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred; 
    522     auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 
    523     auth_cred.data.dyn_cred.verify_nonce = &stun_auth_verify_nonce; 
    524     auth_cred.data.dyn_cred.user_data = comp->stun_sess; 
    525     pj_stun_session_set_credential(comp->stun_sess, &auth_cred); 
    526  
    527     /* Done */ 
    528     ice->comp_cnt++; 
    529     pj_mutex_unlock(ice->mutex); 
    530  
    531     return PJ_SUCCESS; 
    532 } 
    533  
    534  
    535 static pj_status_t stun_auth_get_auth(void *user_data, 
    536                                       pj_pool_t *pool, 
    537                                       pj_str_t *realm, 
    538                                       pj_str_t *nonce) 
    539 { 
    540     PJ_UNUSED_ARG(user_data); 
    541     PJ_UNUSED_ARG(pool); 
    542  
    543     realm->slen = 0; 
    544     nonce->slen = 0; 
    545  
    546     return PJ_SUCCESS; 
    547 } 
    548  
    549  
    550 /* Get credential to be sent with outgoing message */ 
    551 static pj_status_t stun_auth_get_cred(const pj_stun_msg *msg, 
    552                                       void *user_data, 
    553                                       pj_pool_t *pool, 
    554                                       pj_str_t *realm, 
    555                                       pj_str_t *username, 
    556                                       pj_str_t *nonce, 
    557                                       int *data_type, 
    558                                       pj_str_t *data) 
    559 { 
    560     pj_stun_session *sess = (pj_stun_session *)user_data; 
    561     stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess); 
    562     pj_ice *ice = sd->ice; 
    563  
    564     PJ_UNUSED_ARG(pool); 
    565     realm->slen = nonce->slen = 0; 
    566  
    567     if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || 
    568         PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) 
    569     { 
    570         /* Outgoing responses need to have the same credential as 
    571          * incoming requests. 
    572          */ 
    573         *username = ice->rx_uname; 
    574         *data_type = 0; 
    575         *data = ice->rx_pass; 
    576     } 
    577     else { 
    578         *username = ice->tx_uname; 
    579         *data_type = 0; 
    580         *data = ice->tx_pass; 
    581     } 
    582  
    583     return PJ_SUCCESS; 
    584 } 
    585  
    586 /* Get password to be used to authenticate incoming message */ 
    587 static pj_status_t stun_auth_get_password(const pj_stun_msg *msg, 
    588                                           void *user_data,  
    589                                           const pj_str_t *realm, 
    590                                           const pj_str_t *username, 
    591                                           pj_pool_t *pool, 
    592                                           int *data_type, 
    593                                           pj_str_t *data) 
    594 { 
    595     pj_stun_session *sess = (pj_stun_session *)user_data; 
    596     stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess); 
    597     pj_ice *ice = sd->ice; 
    598  
    599     PJ_UNUSED_ARG(realm); 
    600     PJ_UNUSED_ARG(pool); 
    601  
    602     if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || 
    603         PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) 
    604     { 
    605         /* Incoming response is authenticated with TX credential */ 
    606         /* Verify username */ 
    607         if (pj_strcmp(username, &ice->tx_uname) != 0) 
    608             return -1; 
    609         *data_type = 0; 
    610         *data = ice->tx_pass; 
    611  
    612     } else { 
    613         /* Incoming request is authenticated with RX credential */ 
    614         /* The agent MUST accept a credential if the username consists 
    615          * of two values separated by a colon, where the first value is 
    616          * equal to the username fragment generated by the agent in an offer 
    617          * or answer for a session in-progress, and the MESSAGE-INTEGRITY  
    618          * is the output of a hash of the password and the STUN packet's  
    619          * contents.  
    620          */ 
    621         PJ_TODO(CHECK_USERNAME_FOR_INCOMING_STUN_REQUEST); 
    622         *data_type = 0; 
    623         *data = ice->rx_pass; 
    624  
    625     } 
    626  
    627     return PJ_SUCCESS; 
    628 } 
    629  
    630  
    631 static pj_bool_t stun_auth_verify_nonce(const pj_stun_msg *msg, 
    632                                         void *user_data, 
    633                                         const pj_str_t *realm, 
    634                                         const pj_str_t *username, 
    635                                         const pj_str_t *nonce) 
    636 { 
    637     /* We don't use NONCE */ 
    638     PJ_UNUSED_ARG(msg); 
    639     PJ_UNUSED_ARG(user_data); 
    640     PJ_UNUSED_ARG(realm); 
    641     PJ_UNUSED_ARG(username); 
    642     PJ_UNUSED_ARG(nonce); 
    643     return PJ_TRUE; 
    644 } 
    645  
    646  
    647 PJ_DEF(pj_status_t) pj_ice_set_credentials(pj_ice *ice, 
    648                                            const pj_str_t *local_ufrag, 
    649                                            const pj_str_t *local_pass, 
    650                                            const pj_str_t *remote_ufrag, 
    651                                            const pj_str_t *remote_pass) 
    652 { 
    653     char buf[128]; 
    654     pj_str_t username; 
    655  
    656     username.ptr = buf; 
    657  
    658     PJ_ASSERT_RETURN(ice && local_ufrag && local_pass && 
    659                      remote_ufrag && remote_pass, PJ_EINVAL); 
    660     PJ_ASSERT_RETURN(local_ufrag->slen + remote_ufrag->slen < 
    661                      sizeof(buf), PJ_ENAMETOOLONG); 
    662  
    663     pj_strcpy(&username, remote_ufrag); 
    664     pj_strcat2(&username, ":"); 
    665     pj_strcat(&username, local_ufrag); 
    666  
    667     pj_strdup(ice->pool, &ice->tx_uname, &username); 
    668     pj_strdup(ice->pool, &ice->tx_pass, remote_pass); 
    669  
    670     pj_strcpy(&username, local_ufrag); 
    671     pj_strcat2(&username, ":"); 
    672     pj_strcat(&username, remote_ufrag); 
    673  
    674     pj_strdup(ice->pool, &ice->rx_uname, &username); 
    675     pj_strdup(ice->pool, &ice->rx_pass, local_pass); 
    676  
    677     return PJ_SUCCESS; 
    678 } 
    679  
    680  
    681 static pj_status_t gather_host_cands(pj_ice *ice) 
    682 { 
    683     unsigned i; 
    684     pj_status_t status; 
    685  
    686     for (i=0; i<ice->comp_cnt; ++i) { 
    687         pj_ice_comp *comp = &ice->comp[i]; 
    688         pj_sockaddr addr; 
    689         int addr_len; 
    690  
    691         addr_len = sizeof(addr); 
    692         status = pj_sock_getsockname(comp->sock, &addr, &addr_len); 
    693         if (status != PJ_SUCCESS) 
    694             return status; 
    695  
    696         if (addr.ipv4.sin_addr.s_addr == 0) { 
    697             status = pj_gethostip(&addr.ipv4.sin_addr); 
    698             if (status != PJ_SUCCESS) 
    699                 return status; 
    700         } 
    701  
    702         status = pj_ice_add_cand(ice, i, PJ_ICE_CAND_TYPE_HOST, 65535, 
    703                                  &host_foundation, &addr, &addr, NULL, 
    704                                  sizeof(pj_sockaddr_in), NULL); 
    705         if (status != PJ_SUCCESS) 
    706             return status; 
    707     } 
    708  
    709     return PJ_SUCCESS; 
    710 } 
    711  
    712 /* Eliminate redundant candidates. */ 
    713 static void eliminate_redundant_cand(unsigned *cnt, 
    714                                      pj_ice_cand cand[]) 
    715 { 
    716  
    717     /* A candidate is redundant if its transport address equals another  
    718      * candidate, and its base equals the base of that other candidate. 
    719      * Note that two candidates can have the same transport address yet 
    720      * have different bases, and these would not be considered redundant. 
    721      */ 
    722     PJ_TODO(ELIMINATE_REDUNDANT_CANDIDATES); 
    723     PJ_UNUSED_ARG(cnt); 
    724     PJ_UNUSED_ARG(cand); 
    725 } 
    726  
    727  
    728 PJ_DEF(pj_status_t) pj_ice_start_gather(pj_ice *ice, 
    729                                         unsigned flags) 
    730 { 
    731     pj_status_t status; 
    732  
    733     PJ_UNUSED_ARG(flags); 
    734  
    735     /* Gather host candidate */ 
    736     status = gather_host_cands(ice); 
    737     if (status != PJ_SUCCESS) 
    738         return status; 
    739  
    740     /* Eliminate redundant host candidates. */ 
    741     eliminate_redundant_cand(&ice->lcand_cnt, ice->lcand); 
    742  
    743     PJ_TODO(GATHER_MAPPED_AND_RELAYED_CANDIDATES); 
    744  
    745     return PJ_SUCCESS; 
    746 } 
    747  
    748  
    749 static pj_uint32_t CALC_CAND_PRIO(pj_ice_cand_type type, 
    750                                   pj_uint32_t local_pref, 
    751                                   pj_uint32_t comp_id) 
    752 { 
    753     static pj_uint32_t type_pref[] = 
    754     { 
    755         PJ_ICE_HOST_PREF, 
    756         PJ_ICE_MAPPED_PREF, 
    757         PJ_ICE_PEER_MAPPED_PREF, 
    758         PJ_ICE_RELAYED_PREF 
    759     }; 
    760  
    761     return ((1 << 24) * type_pref[type]) +  
    762            ((1 << 8) * local_pref) + 
    763            (256 - comp_id); 
    764 } 
    765  
    766  
    767 PJ_DEF(pj_status_t) pj_ice_add_cand(pj_ice *ice, 
    768                                     unsigned comp_id, 
    769                                     pj_ice_cand_type type, 
    770                                     pj_uint16_t local_pref, 
    771                                     const pj_str_t *foundation, 
    772                                     const pj_sockaddr_t *addr, 
    773                                     const pj_sockaddr_t *base_addr, 
    774                                     const pj_sockaddr_t *srv_addr, 
    775                                     int addr_len, 
    776                                     unsigned *p_cand_id) 
    777 { 
    778     pj_ice_cand *lcand; 
    779     pj_status_t status = PJ_SUCCESS; 
    780     char tmp[128]; 
    781  
    782     PJ_ASSERT_RETURN(ice && comp_id && type && local_pref && 
    783                      foundation && addr && base_addr && addr_len, 
    784                      PJ_EINVAL); 
    785  
    786     pj_mutex_lock(ice->mutex); 
    787  
    788     if (ice->lcand_cnt >= PJ_ARRAY_SIZE(ice->lcand)) { 
    789         status = PJ_ETOOMANY; 
    790         goto on_error; 
    791     } 
    792  
    793     lcand = &ice->lcand[ice->lcand_cnt]; 
    794     lcand->comp_id = comp_id; 
    795     lcand->type = type; 
    796     pj_strdup(ice->pool, &lcand->foundation, foundation); 
    797     lcand->prio = CALC_CAND_PRIO(type, local_pref, lcand->comp_id); 
    798     pj_memcpy(&lcand->addr, addr, addr_len); 
    799     pj_memcpy(&lcand->base_addr, base_addr, addr_len); 
    800     if (srv_addr) 
    801         pj_memcpy(&lcand->srv_addr, srv_addr, addr_len); 
    802     else 
    803         pj_bzero(&lcand->srv_addr, sizeof(lcand->srv_addr)); 
    804  
    805     if (p_cand_id) 
    806         *p_cand_id = ice->lcand_cnt; 
    807  
    808     pj_ansi_strcpy(tmp, pj_inet_ntoa(lcand->addr.ipv4.sin_addr)); 
    809     LOG((ice->obj_name,  
    810          "Candidate %d added: comp_id=%d, type=%s, foundation=%.*s, " 
    811          "addr=%s:%d, base=%s:%d, prio=0x%x (%u)", 
    812          ice->lcand_cnt,  
    813          lcand->comp_id,  
    814          cand_type_names[lcand->type], 
    815          (int)lcand->foundation.slen, 
    816          lcand->foundation.ptr, 
    817          tmp,  
    818          (int)pj_ntohs(lcand->addr.ipv4.sin_port), 
    819          pj_inet_ntoa(lcand->base_addr.ipv4.sin_addr), 
    820          (int)pj_htons(lcand->base_addr.ipv4.sin_port), 
    821          lcand->prio, lcand->prio)); 
    822  
    823     ++ice->lcand_cnt; 
    824  
    825 on_error: 
    826     pj_mutex_unlock(ice->mutex); 
    827     return status; 
    828 } 
    829  
    830  
    831 PJ_DEF(unsigned) pj_ice_get_cand_cnt(pj_ice *ice) 
    832 { 
    833     return ice->lcand_cnt; 
    834 } 
    835  
    836  
    837 PJ_DEF(pj_status_t) pj_ice_enum_cands(pj_ice *ice, 
    838                                       unsigned *p_count, 
    839                                       unsigned cand_ids[]) 
    840 { 
    841     unsigned i, count; 
    842  
    843     PJ_ASSERT_RETURN(ice && p_count && *p_count && cand_ids, PJ_EINVAL); 
    844  
    845     pj_mutex_lock(ice->mutex); 
    846  
    847     count = (*p_count < ice->lcand_cnt) ? *p_count : ice->lcand_cnt; 
    848     for (i=0; i<count; ++i) 
    849         cand_ids[i] = i; 
    850  
    851     *p_count = count; 
    852     pj_mutex_unlock(ice->mutex); 
    853  
    854     return PJ_SUCCESS; 
    855 } 
    856  
    857  
    858 PJ_DEF(pj_status_t) pj_ice_get_default_cand(pj_ice *ice, 
    859                                             unsigned comp_id, 
    860                                             int *cand_id) 
    861 { 
    862     PJ_ASSERT_RETURN(ice && comp_id && cand_id, PJ_EINVAL); 
    863  
    864     pj_mutex_lock(ice->mutex); 
    865  
    866     /* First find in valid list if we have nominated pair */ 
    867  
    868     /* If there's no nominated pair, find relayed candidate */ 
    869  
    870     /* If there's no relayed candidate, find server reflexive candidate */ 
    871  
    872     /* Otherwise return host candidate */ 
    873  
    874     pj_assert(!"Not implemented yet"); 
    875     PJ_TODO(IMPLEMENT_GET_DEFAULT_CAND); 
    876  
    877     pj_mutex_unlock(ice->mutex); 
    878  
    879     return PJ_SUCCESS; 
    880 } 
    881  
    882  
    883 PJ_DEF(pj_status_t) pj_ice_get_cand(pj_ice *ice, 
    884                                     unsigned cand_id, 
    885                                     pj_ice_cand **p_cand) 
    886 { 
    887     PJ_ASSERT_RETURN(ice && p_cand, PJ_EINVAL); 
    888     PJ_ASSERT_RETURN(cand_id <= ice->lcand_cnt, PJ_EINVAL); 
    889  
    890     *p_cand = &ice->lcand[cand_id]; 
    891  
    892     return PJ_SUCCESS; 
    893 } 
    894  
    895 #ifndef MIN 
    896 #   define MIN(a,b) (a < b ? a : b) 
    897 #endif 
    898  
    899 #ifndef MAX 
    900 #   define MAX(a,b) (a > b ? a : b) 
    901 #endif 
    902  
    903 static pj_uint64_t CALC_CHECK_PRIO(const pj_ice *ice,  
    904                                    const pj_ice_cand *lcand, 
    905                                    const pj_ice_cand *rcand) 
    906 { 
    907     pj_uint32_t O, A; 
    908  
    909     if (ice->role == PJ_ICE_ROLE_CONTROLLING) { 
    910         O = lcand->prio;  
    911         A = rcand->prio; 
    912     } else { 
    913         O = rcand->prio; 
    914         A = lcand->prio; 
    915     } 
    916  
    917     return ((pj_uint64_t)1 << 32) * MIN(O, A) + 
    918            (pj_uint64_t)2 * MAX(O, A) + (O>A ? 1 : 0); 
    919 } 
    920  
    921 static const char *dump_check(char *buffer, unsigned bufsize, 
    922                               const pj_ice *ice, 
    923                               const pj_ice_check *check) 
    924 { 
    925     const pj_ice_cand *lcand = check->lcand; 
    926     const pj_ice_cand *rcand = check->rcand; 
    927     char laddr[CHECK_NAME_LEN]; 
    928     int len; 
    929  
    930     pj_ansi_strcpy(laddr, pj_inet_ntoa(lcand->addr.ipv4.sin_addr)); 
    931  
    932     if (lcand->addr.addr.sa_family == PJ_AF_INET) { 
    933         len = pj_ansi_snprintf(buffer, bufsize, 
    934                                "%s:%d-->%s:%d", 
    935                                laddr, (int)pj_ntohs(lcand->addr.ipv4.sin_port), 
    936                                pj_inet_ntoa(rcand->addr.ipv4.sin_addr), 
    937                                (int)pj_ntohs(rcand->addr.ipv4.sin_port)); 
    938     } else { 
    939         len = pj_ansi_snprintf(buffer, bufsize, "IPv6->IPv6"); 
    940     } 
    941  
    942  
    943     if (len < 0) 
    944         len = 0; 
    945     else if (len >= (int)bufsize) 
    946         len = bufsize - 1; 
    947  
    948     buffer[len] = '\0'; 
    949     return buffer; 
    950 } 
    951  
    952 #if PJ_LOG_MAX_LEVEL >= 4 
    953 static void dump_checklist(const char *title, const pj_ice *ice,  
    954                            const pj_ice_checklist *clist) 
    955 { 
    956     unsigned i; 
    957     char buffer[CHECK_NAME_LEN]; 
    958  
    959     LOG((ice->obj_name, "%s", title)); 
    960     for (i=0; i<clist->count; ++i) { 
    961         const pj_ice_check *c = &clist->checks[i]; 
    962         LOG((ice->obj_name, " %d: %s (prio=%u, state=%s)", 
    963              i, dump_check(buffer, sizeof(buffer), ice, c), 
    964              c->prio, check_state_name[c->state])); 
    965     } 
    966 } 
    967 #else 
    968 #define dump_checklist(ice, clist) 
    969 #endif 
    970  
    971 static void check_set_state(pj_ice *ice, pj_ice_check *check, 
    972                             pj_ice_check_state st,  
    973                             pj_status_t err_code) 
    974 { 
    975     char buf[CHECK_NAME_LEN]; 
    976     LOG((ice->obj_name, "Check %s: state changed from %s to %s", 
    977          dump_check(buf, sizeof(buf), ice, check), 
    978          check_state_name[check->state], 
    979          check_state_name[st])); 
    980     check->state = st; 
    981     check->err_code = err_code; 
    982 } 
    983  
    984 static void clist_set_state(pj_ice *ice, pj_ice_checklist *clist, 
    985                             pj_ice_checklist_state st) 
    986 { 
    987     LOG((ice->obj_name, "Checklist: state changed from %s to %s", 
    988          clist_state_name[clist->state], 
    989          clist_state_name[st])); 
    990     clist->state = st; 
    991 } 
    992  
    993 /* Sort checklist based on priority */ 
    994 static void sort_checklist(pj_ice_checklist *clist) 
    995 { 
    996     unsigned i; 
    997  
    998     for (i=0; i<clist->count-1; ++i) { 
    999         unsigned j, highest = i; 
    1000         for (j=i+1; j<clist->count; ++j) { 
    1001             if (clist->checks[j].prio > clist->checks[highest].prio) { 
    1002                 highest = j; 
    1003             } 
    1004         } 
    1005  
    1006         if (highest != i) { 
    1007             pj_ice_check tmp; 
    1008  
    1009             pj_memcpy(&tmp, &clist->checks[i], sizeof(pj_ice_check)); 
    1010             pj_memcpy(&clist->checks[i], &clist->checks[highest],  
    1011                       sizeof(pj_ice_check)); 
    1012             pj_memcpy(&clist->checks[highest], &tmp, sizeof(pj_ice_check)); 
    1013         } 
    1014     } 
    1015 } 
    1016  
    1017 /* Sort valid list based on priority */ 
    1018 static void sort_valid_list(pj_ice *ice) 
    1019 { 
    1020     unsigned i; 
    1021  
    1022     for (i=0; i<ice->valid_cnt-1; ++i) { 
    1023         unsigned j, highest = i; 
    1024         pj_ice_check *ci = ice->clist.checks[ice->valid_list[i]]; 
    1025  
    1026         for (j=i+1; j<ice->valid_cnt; ++j) { 
    1027             pj_ice_check *cj = ice->clist.checks[ice->valid_list[j]]; 
    1028  
    1029             if (cj->prio > ci->prio) { 
    1030                 highest = j; 
    1031             } 
    1032         } 
    1033  
    1034         if (highest != i) { 
    1035             unsigned tmp = ice->valid_list[i]; 
    1036             ice->valid_list[i] = ice->valid_list[j]; 
    1037             ice->valid_list[j] = tmp; 
    1038         } 
    1039     } 
    1040 } 
    1041  
    1042  
    1043 enum  
    1044 {  
    1045     SOCKADDR_EQUAL = 0,  
    1046     SOCKADDR_NOT_EQUAL = 1  
    1047 }; 
    1048  
    1049 /* Utility: compare sockaddr. 
    1050  * Returns 0 if equal. 
    1051  */ 
    1052 static int sockaddr_cmp(const pj_sockaddr *a1, const pj_sockaddr *a2) 
    1053 { 
    1054     if (a1->addr.sa_family != a2->addr.sa_family) 
    1055         return SOCKADDR_NOT_EQUAL; 
    1056  
    1057     if (a1->addr.sa_family == PJ_AF_INET) { 
    1058         return !(a1->ipv4.sin_addr.s_addr == a2->ipv4.sin_addr.s_addr && 
    1059                  a1->ipv4.sin_port == a2->ipv4.sin_port); 
    1060     } else if (a1->addr.sa_family == PJ_AF_INET6) { 
    1061         return pj_memcmp(&a1->ipv6, &a2->ipv6, sizeof(a1->ipv6)); 
    1062     } else { 
    1063         pj_assert(!"Invalid address family!"); 
    1064         return SOCKADDR_NOT_EQUAL; 
    1065     } 
    1066 } 
    1067  
    1068  
    1069 /* Prune checklist, this must have been done after the checklist 
    1070  * is sorted. 
    1071  */ 
    1072 static void prune_checklist(pj_ice *ice, pj_ice_checklist *clist) 
    1073 { 
    1074     unsigned i; 
    1075  
    1076     /* Since an agent cannot send requests directly from a reflexive 
    1077      * candidate, but only from its base, the agent next goes through the 
    1078      * sorted list of candidate pairs.  For each pair where the local 
    1079      * candidate is server reflexive, the server reflexive candidate MUST be 
    1080      * replaced by its base.  Once this has been done, the agent MUST prune 
    1081      * the list.  This is done by removing a pair if its local and remote 
    1082      * candidates are identical to the local and remote candidates of a pair 
    1083      * higher up on the priority list.  The result is a sequence of ordered 
    1084      * candidate pairs, called the check list for that media stream.     
    1085      */ 
    1086     for (i=0; i<clist->count; ++i) { 
    1087         pj_ice_cand *licand = clist->checks[i].lcand; 
    1088         pj_ice_cand *ricand = clist->checks[i].rcand; 
    1089         const pj_sockaddr *liaddr; 
    1090         unsigned j; 
    1091  
    1092         if (licand->type == PJ_ICE_CAND_TYPE_MAPPED) 
    1093             liaddr = &licand->base_addr; 
    1094         else 
    1095             liaddr = &licand->addr; 
    1096  
    1097         for (j=i+1; j<clist->count;) { 
    1098             pj_ice_cand *ljcand = clist->checks[j].lcand; 
    1099             pj_ice_cand *rjcand = clist->checks[j].rcand; 
    1100             const pj_sockaddr *ljaddr; 
    1101  
    1102             if (ljcand->type == PJ_ICE_CAND_TYPE_MAPPED) 
    1103                 ljaddr = &licand->base_addr; 
    1104             else 
    1105                 ljaddr = &licand->addr; 
    1106  
    1107             if (sockaddr_cmp(liaddr, ljaddr) == SOCKADDR_EQUAL && 
    1108                 sockaddr_cmp(&ricand->addr, &rjcand->addr) == SOCKADDR_EQUAL) 
    1109             { 
    1110                 /* Found duplicate, remove it */ 
    1111                 char buf[CHECK_NAME_LEN]; 
    1112  
    1113                 LOG((ice->obj_name, "Check %s pruned", 
    1114                     dump_check(buf, sizeof(buf), ice, &clist->checks[j]))); 
    1115  
    1116                 pj_array_erase(clist->checks, sizeof(clist->checks[0]), 
    1117                                clist->count, j); 
    1118                 --clist->count; 
    1119  
    1120             } else { 
    1121                 ++j; 
    1122             } 
    1123         } 
    1124     } 
    1125 } 
     1126 
     1127 
    11261128 
    11271129typedef struct timer_data 
     
    12421244    LOG((ice->obj_name,  
    12431245         "Sending connectivity check for check %d: %s",  
    1244          check_id, dump_check(buffer, sizeof(buffer), ice, check))); 
     1246         check_id, dump_check(buffer, sizeof(buffer), check))); 
    12451247 
    12461248    /* Create request */ 
     
    14341436    struct req_data *rd = (struct req_data*) tdata->user_data; 
    14351437    pj_ice *ice; 
    1436     pj_ice_check *check, *valid_check; 
     1438    pj_ice_check *check; 
    14371439    const pj_ice_cand *lcand; 
    14381440    const pj_ice_cand *rcand; 
     
    14561458         "Connectivity check %s for check %s", 
    14571459         (status==PJ_SUCCESS ? "SUCCESS" : "FAILED"),  
    1458          dump_check(buffer, sizeof(buffer), ice, check))); 
     1460         dump_check(buffer, sizeof(buffer), check))); 
    14591461 
    14601462    if (status != PJ_SUCCESS) { 
  • pjproject/trunk/pjnath/src/pjstun-client/client_main.c

    r1080 r1091  
    3333static struct global 
    3434{ 
    35     pj_stun_endpoint    *endpt; 
     35    pj_stun_config       stun_config; 
    3636    pj_pool_t           *pool; 
    3737    pj_caching_pool      cp; 
     
    105105                                           PJ_STUN_ATTR_RELAY_ADDR, 0); 
    106106                if (ar) { 
    107                     pj_memcpy(&g.relay_addr, &ar->addr.ipv4, 
     107                    pj_memcpy(&g.relay_addr, &ar->sockaddr.ipv4, 
    108108                              sizeof(pj_sockaddr_in)); 
    109109                    PJ_LOG(3,(THIS_FILE, "Relay address is %s:%d", 
     
    209209    pj_assert(status == PJ_SUCCESS); 
    210210 
    211     status = pj_stun_endpoint_create(&g.cp.factory, 0, NULL, g.th, &g.endpt); 
     211    pj_stun_config_init(&g.stun_config, &g.cp.factory, 0, NULL, g.th); 
    212212    pj_assert(status == PJ_SUCCESS); 
    213213 
     
    236236    stun_cb.on_request_complete = &on_request_complete; 
    237237 
    238     status = pj_stun_session_create(g.endpt, NULL, &stun_cb,  
     238    status = pj_stun_session_create(&g.stun_config, NULL, &stun_cb,  
    239239                                    o.use_fingerprint!=0, &g.sess); 
    240240    pj_assert(status == PJ_SUCCESS); 
     
    282282    if (g.sess) 
    283283        pj_stun_session_destroy(g.sess); 
    284     if (g.endpt) 
    285         pj_stun_endpoint_destroy(g.endpt); 
    286284    if (g.sock != PJ_INVALID_SOCKET) 
    287285        pj_sock_close(g.sock); 
  • pjproject/trunk/pjnath/src/pjstun-srv-test/bind_usage.c

    r1080 r1091  
    8686    sess_cb.on_send_msg = &sess_on_send_msg; 
    8787    sess_cb.on_rx_request = &sess_on_rx_request; 
    88     status = pj_stun_session_create(si->cfg, "bind%p", &sess_cb, PJ_FALSE, 
    89                                     &bu->session); 
     88    status = pj_stun_session_create(&si->stun_cfg, "bind%p", &sess_cb,  
     89                                    PJ_FALSE, &bu->session); 
    9090    if (status != PJ_SUCCESS) { 
    9191        pj_stun_usage_destroy(bu->usage); 
  • pjproject/trunk/pjnath/src/pjstun-srv-test/server.c

    r1080 r1091  
    8484        goto on_error; 
    8585 
    86     status = pj_stun_config_create(srv->si.pf, 0, srv->si.ioqueue,  
    87                                      srv->si.timer_heap, &srv->si.cfg); 
    88     if (status != PJ_SUCCESS) 
    89         goto on_error; 
     86    pj_stun_config_init(&srv->si.stun_cfg, srv->si.pf, 0, srv->si.ioqueue, 
     87                        srv->si.timer_heap); 
    9088 
    9189    srv->si.thread_cnt = thread_cnt; 
     
    175173    } 
    176174 
    177     pj_stun_config_destroy(srv->si.cfg); 
    178175    pj_timer_heap_destroy(srv->si.timer_heap); 
    179176    pj_ioqueue_destroy(srv->si.ioqueue); 
  • pjproject/trunk/pjnath/src/pjstun-srv-test/server.h

    r1080 r1091  
    3232{ 
    3333    pj_pool_factory     *pf; 
    34     pj_stun_config      *cfg; 
     34    pj_stun_config       stun_cfg; 
    3535    pj_ioqueue_t        *ioqueue; 
    3636    pj_timer_heap_t     *timer_heap; 
  • pjproject/trunk/pjnath/src/pjstun-srv-test/turn_usage.c

    r1080 r1091  
    166166    tu->type = type; 
    167167    tu->pf = si->pf; 
    168     tu->cfg = si->cfg; 
     168    tu->cfg = &si->stun_cfg; 
    169169    tu->ioqueue = si->ioqueue; 
    170170    tu->timer_heap = si->timer_heap; 
     
    198198    sess_cb.on_send_msg = &tu_sess_on_send_msg; 
    199199    sess_cb.on_rx_request = &tu_sess_on_rx_request; 
    200     status = pj_stun_session_create(si->cfg, "turns%p", &sess_cb, PJ_FALSE, 
    201                                     &tu->default_session); 
     200    status = pj_stun_session_create(&si->stun_cfg, "turns%p", &sess_cb,  
     201                                    PJ_FALSE, &tu->default_session); 
    202202    if (status != PJ_SUCCESS) { 
    203203        pj_stun_usage_destroy(tu->usage); 
     
    934934 
    935935    /* Process REQUESTED-IP attribute */ 
    936     if (a_rip && a_rip->addr.addr.sa_family != PJ_AF_INET) { 
     936    if (a_rip && a_rip->sockaddr.addr.sa_family != PJ_AF_INET) { 
    937937        client_respond(client, msg, PJ_STUN_SC_INVALID_IP_ADDR, NULL, 
    938938                       src_addr, src_addr_len); 
     
    940940         
    941941    } else if (a_rip) { 
    942         req_addr.sin_addr.s_addr = a_rip->addr.ipv4.sin_addr.s_addr; 
     942        req_addr.sin_addr.s_addr = a_rip->sockaddr.ipv4.sin_addr.s_addr; 
    943943    } 
    944944 
     
    11071107        client->active_peer = NULL; 
    11081108 
    1109     } else if (a_raddr->addr.addr.sa_family != PJ_AF_INET) { 
     1109    } else if (a_raddr->sockaddr.addr.sa_family != PJ_AF_INET) { 
    11101110        /* Bad request (not IPv4) */ 
    11111111        client_respond(client, msg, PJ_STUN_SC_BAD_REQUEST, NULL, 
     
    11261126 
    11271127        /* Add a new peer/permission if we don't have one for this address */ 
    1128         peer = client_get_peer(client, &a_raddr->addr.ipv4, &hval); 
     1128        peer = client_get_peer(client, &a_raddr->sockaddr.ipv4, &hval); 
    11291129        if (peer==NULL) { 
    1130             peer = client_add_peer(client, &a_raddr->addr.ipv4, hval); 
     1130            peer = client_add_peer(client, &a_raddr->sockaddr.ipv4, hval); 
    11311131        } 
    11321132 
     
    11731173        return PJ_SUCCESS; 
    11741174 
    1175     } else if (a_raddr->addr.addr.sa_family != PJ_AF_INET) { 
     1175    } else if (a_raddr->sockaddr.addr.sa_family != PJ_AF_INET) { 
    11761176        /* REMOTE-ADDRESS present but not IPv4, discard packet */ 
    11771177        return PJ_SUCCESS; 
     
    11961196 
    11971197    /* Add to peer table if necessary */ 
    1198     if (client_get_peer(client, &a_raddr->addr.ipv4, &hval)==NULL) 
    1199         client_add_peer(client, &a_raddr->addr.ipv4, hval); 
     1198    if (client_get_peer(client, &a_raddr->sockaddr.ipv4, &hval)==NULL) 
     1199        client_add_peer(client, &a_raddr->sockaddr.ipv4, hval); 
    12001200 
    12011201    /* Send the packet */ 
    12021202    pj_ioqueue_sendto(client->key, &client->pkt_write_key,  
    12031203                      data, &datalen, 0, 
    1204                       &a_raddr->addr.ipv4, sizeof(a_raddr->addr.ipv4)); 
     1204                      &a_raddr->sockaddr.ipv4, sizeof(pj_sockaddr_in)); 
    12051205 
    12061206    return PJ_SUCCESS; 
Note: See TracChangeset for help on using the changeset viewer.