Changeset 1085


Ignore:
Timestamp:
Mar 20, 2007 8:44:26 AM (13 years ago)
Author:
bennylp
Message:

--

Location:
pjproject/trunk/pjnath
Files:
6 edited

Legend:

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

    r1080 r1085  
    4242# PROP Target_Dir "" 
    4343# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c 
    44 # ADD CPP /nologo /MD /W4 /GX /Zi /O2 /Ob2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c 
     44# ADD CPP /nologo /MD /W4 /GX /Zi /O2 /Ob2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c 
    4545# SUBTRACT CPP /YX 
    4646# ADD BASE RSC /l 0x409 /d "NDEBUG" 
     
    6666# PROP Target_Dir "" 
    6767# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c 
    68 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c 
     68# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c 
    6969# SUBTRACT CPP /YX 
    7070# ADD BASE RSC /l 0x409 /d "_DEBUG" 
  • pjproject/trunk/pjnath/include/pjnath/ice.h

    r1080 r1085  
    2525 */ 
    2626#include <pjnath/types.h> 
    27 #include <pjnath/stun_endpoint.h> 
     27#include <pjnath/stun_session.h> 
    2828#include <pjlib-util/resolver.h> 
    2929#include <pj/sock.h> 
     
    6565 
    6666 
    67 #define PJ_ICE_MAX_CAND     32 
     67#define PJ_ICE_MAX_CAND     16 
    6868#define PJ_ICE_MAX_COMP     8 
    69  
     69#define PJ_ICE_MAX_CHECKS   32 
    7070 
    7171/** 
     
    105105typedef struct pj_ice_check 
    106106{ 
    107     unsigned            local_cand_id; 
     107    unsigned            cand_id; 
     108    pj_uint32_t         comp_id; 
     109    pj_str_t            foundation; 
     110 
    108111    pj_uint64_t         check_prio; 
    109112    pj_ice_check_state  check_state; 
     
    128131    pj_ice_checklist_state   state; 
    129132    unsigned                 count; 
    130     pj_ice_check            *checks; 
     133    pj_ice_check             checks[PJ_ICE_MAX_CHECKS]; 
    131134} pj_ice_checklist; 
    132135 
     
    137140typedef struct pj_ice_cb 
    138141{ 
    139     pj_bool_t (*on_found_cand)(pj_ice *sock, 
    140                                pj_ice_cand_type type, 
    141                                const pj_sockaddr_t *addr, 
    142                                int addr_len); 
     142    pj_status_t (*on_send_pkt)(pj_ice *ice,  
     143                               const void *pkt, pj_size_t size, 
     144                               const pj_sockaddr_t *dst_addr, 
     145                               unsigned addr_len); 
    143146} pj_ice_cb; 
    144147 
     
    154157} pj_ice_state; 
    155158 
     159typedef enum pj_ice_role 
     160{ 
     161    PJ_ICE_ROLE_CONTROLLED, 
     162    PJ_ICE_ROLE_CONTROLLING 
     163} pj_ice_role; 
     164 
    156165/** 
    157166 * ICE structure. 
     
    165174    int                  af; 
    166175    int                  sock_type; 
    167  
     176    pj_ice_role          role; 
    168177    pj_ice_state         state; 
     178 
     179    pj_ice_cb            cb; 
     180 
     181    /* STUN credentials */ 
     182    pj_str_t             tx_uname; 
     183    pj_str_t             tx_pass; 
     184    pj_str_t             rx_uname; 
     185    pj_str_t             rx_pass; 
    169186 
    170187    /* Components */ 
     
    173190 
    174191    /* Local candidates */ 
    175     unsigned             cand_cnt; 
    176     pj_ice_cand          cand[PJ_ICE_MAX_CAND]; 
    177  
    178     /* Checklist */ 
     192    unsigned             lcand_cnt; 
     193    pj_ice_cand          lcand[PJ_ICE_MAX_CAND]; 
     194 
     195    /* Remote candidates */ 
     196    unsigned             rcand_cnt; 
     197    pj_ice_cand          rcand[PJ_ICE_MAX_CAND]; 
     198 
     199    /* Checklists */ 
    179200    pj_ice_checklist     cklist; 
     201    pj_ice_checklist     valid_list; 
    180202 
    181203    /* STUN servers */ 
     
    184206    pj_bool_t            relay_enabled; 
    185207    pj_sockaddr          stun_srv; 
     208 
     209    /* STUN sessions */ 
     210    pj_stun_session     *tx_sess; 
     211    pj_stun_session     *rx_sess; 
    186212}; 
    187213 
     
    189215PJ_DECL(pj_status_t) pj_ice_create(pj_stun_config *cfg, 
    190216                                   const char *name, 
     217                                   pj_ice_role role, 
     218                                   const pj_ice_cb *cb, 
    191219                                   int af, 
    192220                                   int sock_type, 
     
    208236                                          unsigned comp_id, 
    209237                                          pj_sock_t sock); 
    210  
     238PJ_DECL(pj_status_t) pj_ice_set_credentials(pj_ice *ice, 
     239                                            const pj_str_t *local_ufrag, 
     240                                            const pj_str_t *local_pass, 
     241                                            const pj_str_t *remote_ufrag, 
     242                                            const pj_str_t *remote_pass); 
    211243PJ_DECL(pj_status_t) pj_ice_start_gather(pj_ice *ice, 
    212244                                         unsigned flags); 
  • pjproject/trunk/pjnath/include/pjnath/stun_msg.h

    r1080 r1085  
    15131513 * @param length        Length of data, or zero if no data is to be 
    15141514 *                      copied now. 
    1515  * @param p_attr        Pointer to receive the attribute. 
    15161515 * 
    15171516 * @return              PJ_SUCCESS on success or the appropriate error code. 
     
    15231522                                                 unsigned length); 
    15241523 
     1524/** 
     1525 * Create STUN empty attribute. 
     1526 * 
     1527 * @param pool          The pool to allocate memory from. 
     1528 * @param attr_type     The attribute type, from #pj_stun_attr_type. 
     1529 * @param p_attr        Pointer to receive the attribute. 
     1530 * 
     1531 * @return              PJ_SUCCESS on success or the appropriate error code. 
     1532 */ 
     1533PJ_DECL(pj_status_t) pj_stun_empty_attr_create(pj_pool_t *pool, 
     1534                                               int attr_type, 
     1535                                               pj_stun_empty_attr **p_attr); 
     1536 
     1537/** 
     1538 * Create STUN empty attribute and add the attribute to the message. 
     1539 * 
     1540 * @param pool          The pool to allocate memory from. 
     1541 * @param msg           The STUN message. 
     1542 * @param attr_type     The attribute type, from #pj_stun_attr_type. 
     1543 * 
     1544 * @return              PJ_SUCCESS on success or the appropriate error code. 
     1545 */ 
     1546PJ_DECL(pj_status_t) pj_stun_msg_add_empty_attr(pj_pool_t *pool, 
     1547                                                pj_stun_msg *msg, 
     1548                                                int attr_type); 
    15251549 
    15261550/** 
  • pjproject/trunk/pjnath/include/pjnath/stun_session.h

    r1080 r1085  
    139139    pj_stun_msg         *msg;           /**< The STUN message.              */ 
    140140 
     141    void                *user_data;     /**< Arbitrary application data.    */ 
     142 
    141143    pj_stun_client_tsx  *client_tsx;    /**< Client STUN transaction.       */ 
    142144    pj_uint32_t          msg_magic;     /**< Message magic.                 */ 
  • pjproject/trunk/pjnath/src/pjnath/ice.c

    r1080 r1085  
    1919#include <pjnath/ice.h> 
    2020#include <pjnath/errno.h> 
     21#include <pj/addr_resolv.h> 
    2122#include <pj/assert.h> 
     23#include <pj/log.h> 
    2224#include <pj/os.h> 
    2325#include <pj/pool.h> 
    2426#include <pj/string.h> 
    2527 
     28 
     29static const char *check_state_name[] =  
     30{ 
     31    "Frozen", 
     32    "Waiting", 
     33    "In Progress", 
     34    "Succeeded", 
     35    "Failed" 
     36}; 
    2637 
    2738static void destroy_ice(pj_ice *ice, 
     
    3041                          pj_ice_state new_state); 
    3142 
     43static pj_status_t on_stun_send_msg(pj_stun_session *sess, 
     44                                    const void *pkt, 
     45                                    pj_size_t pkt_size, 
     46                                    const pj_sockaddr_t *dst_addr, 
     47                                    unsigned addr_len); 
     48static pj_status_t on_stun_rx_request(pj_stun_session *sess, 
     49                                      const pj_uint8_t *pkt, 
     50                                      unsigned pkt_len, 
     51                                      const pj_stun_msg *msg, 
     52                                      const pj_sockaddr_t *src_addr, 
     53                                      unsigned src_addr_len); 
     54static void on_stun_request_complete(pj_stun_session *sess, 
     55                                     pj_status_t status, 
     56                                     pj_stun_tx_data *tdata, 
     57                                     const pj_stun_msg *response); 
     58static pj_status_t on_stun_rx_indication(pj_stun_session *sess, 
     59                                         const pj_uint8_t *pkt, 
     60                                         unsigned pkt_len, 
     61                                         const pj_stun_msg *msg, 
     62                                         const pj_sockaddr_t *src_addr, 
     63                                         unsigned src_addr_len); 
     64 
     65static pj_status_t stun_auth_get_auth(void *user_data, 
     66                                      pj_pool_t *pool, 
     67                                      pj_str_t *realm, 
     68                                      pj_str_t *nonce); 
     69static pj_status_t stun_auth_get_password(void *user_data,  
     70                                          const pj_str_t *realm, 
     71                                          const pj_str_t *username, 
     72                                          pj_pool_t *pool, 
     73                                          int *data_type, 
     74                                          pj_str_t *data); 
     75static pj_bool_t stun_auth_verify_nonce(void *user_data, 
     76                                        const pj_str_t *realm, 
     77                                        const pj_str_t *username, 
     78                                        const pj_str_t *nonce); 
     79 
    3280 
    3381PJ_DEF(pj_status_t) pj_ice_create(pj_stun_config *cfg, 
    3482                                  const char *name, 
     83                                  pj_ice_role role, 
     84                                  const pj_ice_cb *cb, 
    3585                                  int af, 
    3686                                  int sock_type, 
     
    3989    pj_pool_t *pool; 
    4090    pj_ice *ice; 
     91    pj_stun_session_cb sess_cb; 
     92    pj_stun_auth_cred auth_cred; 
    4193    pj_status_t status; 
    4294 
    43     PJ_ASSERT_RETURN(cfg && p_ice, PJ_EINVAL); 
     95    PJ_ASSERT_RETURN(cfg && cb && p_ice, PJ_EINVAL); 
    4496    PJ_ASSERT_RETURN(sock_type==PJ_SOCK_DGRAM || sock_type==PJ_SOCK_STREAM, 
    4597                     PJ_EINVAL); 
     
    53105    ice->af = af; 
    54106    ice->sock_type = sock_type; 
     107    ice->role = role; 
    55108 
    56109    pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name), 
     
    64117    } 
    65118 
     119    pj_memcpy(&ice->cb, cb, sizeof(*cb)); 
     120 
     121    /* Init STUN callbacks */ 
     122    pj_bzero(&sess_cb, sizeof(sess_cb)); 
     123    sess_cb.on_request_complete = &on_stun_request_complete; 
     124    sess_cb.on_rx_indication = &on_stun_rx_indication; 
     125    sess_cb.on_rx_request = &on_stun_rx_request; 
     126    sess_cb.on_send_msg = &on_stun_send_msg; 
     127 
     128    /* Init STUN authentication credential */ 
     129    pj_bzero(&auth_cred, sizeof(auth_cred)); 
     130    auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 
     131    auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth; 
     132    auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 
     133    auth_cred.data.dyn_cred.verify_nonce = &stun_auth_verify_nonce; 
     134 
     135    /* Create STUN session for outgoing requests */ 
     136    status = pj_stun_session_create(cfg, ice->obj_name, &sess_cb, PJ_FALSE, 
     137                                    &ice->tx_sess); 
     138    if (status != PJ_SUCCESS) { 
     139        destroy_ice(ice, status); 
     140        return status; 
     141    } 
     142 
     143    pj_stun_session_set_user_data(ice->tx_sess, ice); 
     144    auth_cred.data.dyn_cred.user_data = ice->tx_sess; 
     145    pj_stun_session_set_credential(ice->tx_sess, &auth_cred); 
     146 
     147    /* Create STUN session for incoming requests */ 
     148    status = pj_stun_session_create(cfg, ice->obj_name, &sess_cb, PJ_FALSE, 
     149                                    &ice->rx_sess); 
     150    if (status != PJ_SUCCESS) { 
     151        destroy_ice(ice, status); 
     152        return status; 
     153    } 
     154 
     155    pj_stun_session_set_user_data(ice->rx_sess, ice); 
     156    auth_cred.data.dyn_cred.user_data = ice->rx_sess; 
     157    pj_stun_session_set_credential(ice->rx_sess, &auth_cred); 
     158 
     159    /* Done */ 
    66160    *p_ice = ice; 
     161 
     162    PJ_LOG(4,(ice->obj_name, "ICE session created")); 
    67163 
    68164    return PJ_SUCCESS; 
     
    73169                        pj_status_t reason) 
    74170{ 
     171    if (reason == PJ_SUCCESS) { 
     172        PJ_LOG(4,(ice->obj_name, "Destroying ICE session")); 
     173    } 
     174 
    75175    if (ice->resv_q) { 
    76176        pj_dns_resolver_cancel_query(ice->resv_q, PJ_FALSE); 
     
    109209{ 
    110210    pj_assert(!"Not implemented yet!"); 
     211    PJ_UNUSED_ARG(user_data); 
     212    PJ_UNUSED_ARG(status); 
     213    PJ_UNUSED_ARG(response); 
    111214} 
    112215 
     
    260363 
    261364 
     365static pj_status_t stun_auth_get_auth(void *user_data, 
     366                                      pj_pool_t *pool, 
     367                                      pj_str_t *realm, 
     368                                      pj_str_t *nonce) 
     369{ 
     370    PJ_UNUSED_ARG(user_data); 
     371    PJ_UNUSED_ARG(pool); 
     372 
     373    realm->slen = 0; 
     374    nonce->slen = 0; 
     375 
     376    return PJ_SUCCESS; 
     377} 
     378 
     379 
     380static pj_status_t stun_auth_get_password(void *user_data,  
     381                                          const pj_str_t *realm, 
     382                                          const pj_str_t *username, 
     383                                          pj_pool_t *pool, 
     384                                          int *data_type, 
     385                                          pj_str_t *data) 
     386{ 
     387    pj_stun_session *sess = (pj_stun_session *)user_data; 
     388    pj_ice *ice = (pj_ice*) pj_stun_session_get_user_data(sess); 
     389 
     390    PJ_UNUSED_ARG(realm); 
     391    PJ_UNUSED_ARG(pool); 
     392 
     393    if (sess == ice->tx_sess) { 
     394        /* Verify username */ 
     395        if (pj_strcmp(username, &ice->tx_uname) != 0) 
     396            return -1; 
     397        *data_type = 0; 
     398        *data = ice->tx_pass; 
     399    } else { 
     400        /* The agent MUST accept a credential if the username consists 
     401         * of two values separated by a colon, where the first value is 
     402         * equal to the username fragment generated by the agent in an offer 
     403         * or answer for a session in-progress, and the MESSAGE-INTEGRITY  
     404         * is the output of a hash of the password and the STUN packet's  
     405         * contents.  
     406         */ 
     407        PJ_TODO(CHECK_USERNAME_FOR_INCOMING_STUN_REQUEST); 
     408        *data_type = 0; 
     409        *data = ice->rx_pass; 
     410    } 
     411 
     412    return PJ_SUCCESS; 
     413} 
     414 
     415 
     416static pj_bool_t stun_auth_verify_nonce(void *user_data, 
     417                                        const pj_str_t *realm, 
     418                                        const pj_str_t *username, 
     419                                        const pj_str_t *nonce) 
     420{ 
     421    /* We don't use NONCE */ 
     422    PJ_UNUSED_ARG(user_data); 
     423    PJ_UNUSED_ARG(realm); 
     424    PJ_UNUSED_ARG(username); 
     425    PJ_UNUSED_ARG(nonce); 
     426    return PJ_TRUE; 
     427} 
     428 
     429 
     430PJ_DEF(pj_status_t) pj_ice_set_credentials(pj_ice *ice, 
     431                                           const pj_str_t *local_ufrag, 
     432                                           const pj_str_t *local_pass, 
     433                                           const pj_str_t *remote_ufrag, 
     434                                           const pj_str_t *remote_pass) 
     435{ 
     436    char buf[128]; 
     437    pj_str_t username; 
     438 
     439    username.ptr = buf; 
     440 
     441    PJ_ASSERT_RETURN(ice && local_ufrag && local_pass && 
     442                     remote_ufrag && remote_pass, PJ_EINVAL); 
     443    PJ_ASSERT_RETURN(local_ufrag->slen + remote_ufrag->slen < 
     444                     sizeof(buf), PJ_ENAMETOOLONG); 
     445 
     446    pj_strcpy(&username, remote_ufrag); 
     447    pj_strcat2(&username, ":"); 
     448    pj_strcat(&username, local_ufrag); 
     449 
     450    pj_strdup(ice->pool, &ice->tx_uname, &username); 
     451    pj_strdup(ice->pool, &ice->tx_pass, remote_pass); 
     452 
     453    pj_strcpy(&username, local_ufrag); 
     454    pj_strcat2(&username, ":"); 
     455    pj_strcat(&username, remote_ufrag); 
     456 
     457    pj_strdup(ice->pool, &ice->rx_uname, &username); 
     458    pj_strdup(ice->pool, &ice->rx_pass, local_pass); 
     459 
     460    return PJ_SUCCESS; 
     461} 
     462 
     463 
    262464static pj_status_t gather_host_cands(pj_ice *ice) 
    263465{ 
     
    293495static pj_status_t gather_mapped_cands(pj_ice *ice) 
    294496{ 
     497    PJ_UNUSED_ARG(ice); 
    295498    return PJ_ENOTSUP; 
    296499} 
     
    298501static pj_status_t gather_relayed_cands(pj_ice *ice) 
    299502{ 
     503    PJ_UNUSED_ARG(ice); 
    300504    return PJ_ENOTSUP; 
    301505} 
     
    305509{ 
    306510    pj_status_t status; 
     511 
     512    PJ_UNUSED_ARG(flags); 
    307513 
    308514    /* Gather host candidate */ 
     
    348554                                    unsigned *p_cand_id) 
    349555{ 
    350     pj_ice_cand *cand; 
     556    pj_ice_cand *lcand; 
    351557    pj_status_t status = PJ_SUCCESS; 
    352558 
    353559    pj_mutex_lock(ice->mutex); 
    354560 
    355     if (ice->cand_cnt >= PJ_ARRAY_SIZE(ice->cand)) { 
     561    if (ice->lcand_cnt >= PJ_ARRAY_SIZE(ice->lcand)) { 
    356562        status = PJ_ETOOMANY; 
    357563        goto on_error; 
    358564    } 
    359565 
    360     cand = &ice->cand[ice->cand_cnt]; 
    361     cand->comp_id = comp_id; 
    362     cand->type = type; 
    363     pj_strdup(ice->pool, &cand->foundation, foundation); 
    364     cand->prio = CALC_CAND_PRIO(type, local_pref, cand->comp_id); 
    365     pj_memcpy(&cand->addr, addr, addr_len); 
    366     pj_memcpy(&cand->base_addr, base_addr, addr_len); 
     566    lcand = &ice->lcand[ice->lcand_cnt]; 
     567    lcand->comp_id = comp_id; 
     568    lcand->type = type; 
     569    pj_strdup(ice->pool, &lcand->foundation, foundation); 
     570    lcand->prio = CALC_CAND_PRIO(type, local_pref, lcand->comp_id); 
     571    pj_memcpy(&lcand->addr, addr, addr_len); 
     572    pj_memcpy(&lcand->base_addr, base_addr, addr_len); 
    367573    if (srv_addr) 
    368         pj_memcpy(&cand->srv_addr, srv_addr, addr_len); 
     574        pj_memcpy(&lcand->srv_addr, srv_addr, addr_len); 
    369575    else 
    370         pj_bzero(&cand->srv_addr, sizeof(cand->srv_addr)); 
     576        pj_bzero(&lcand->srv_addr, sizeof(lcand->srv_addr)); 
    371577 
    372578    if (p_cand_id) 
    373         *p_cand_id = ice->cand_cnt; 
    374  
    375     ++ice->cand_cnt; 
     579        *p_cand_id = ice->lcand_cnt; 
     580 
     581    ++ice->lcand_cnt; 
    376582 
    377583on_error: 
     
    383589PJ_DEF(unsigned) pj_ice_get_cand_cnt(pj_ice *ice) 
    384590{ 
    385     return ice->cand_cnt; 
     591    return ice->lcand_cnt; 
    386592} 
    387593 
     
    394600    unsigned i, count; 
    395601 
     602    PJ_UNUSED_ARG(sort_by); 
     603 
    396604    pj_mutex_lock(ice->mutex); 
    397605 
    398     count = (*p_count < ice->cand_cnt) ? *p_count : ice->cand_cnt; 
     606    count = (*p_count < ice->lcand_cnt) ? *p_count : ice->lcand_cnt; 
    399607    for (i=0; i<count; ++i) 
    400608        cand_ids[i] = i; 
     
    412620{ 
    413621    PJ_ASSERT_RETURN(ice && p_cand, PJ_EINVAL); 
    414     PJ_ASSERT_RETURN(cand_id <= ice->cand_cnt, PJ_EINVAL); 
    415  
    416     *p_cand = &ice->cand[cand_id]; 
     622    PJ_ASSERT_RETURN(cand_id <= ice->lcand_cnt, PJ_EINVAL); 
     623 
     624    *p_cand = &ice->lcand[cand_id]; 
    417625 
    418626    return PJ_SUCCESS; 
     
    433641} 
    434642 
     643static const char *dump_check(char *buffer, unsigned bufsize, 
     644                              const pj_ice *ice, 
     645                              const pj_ice_check *check) 
     646{ 
     647    char local_addr[128]; 
     648    int len; 
     649 
     650    pj_ansi_strcpy(local_addr,  
     651                   pj_inet_ntoa(ice->lcand[check->cand_id].addr.ipv4.sin_addr)); 
     652 
     653    len = pj_ansi_snprintf(buffer, bufsize, 
     654              "%s:%d-->%s:%d", 
     655              local_addr, 
     656              (int)pj_ntohs(ice->lcand[check->cand_id].addr.ipv4.sin_port), 
     657              pj_inet_ntoa(check->rem_addr.ipv4.sin_addr), 
     658              (int)pj_ntohs(check->rem_addr.ipv4.sin_port)); 
     659    if (len < 0) 
     660        len = 0; 
     661    else if (len >= (int)bufsize) 
     662        len = bufsize - 1; 
     663 
     664    buffer[len] = '\0'; 
     665    return buffer; 
     666} 
     667 
     668#if PJ_LOG_MAX_LEVEL >= 4 
     669static void dump_checklist(const char *title, const pj_ice *ice,  
     670                           const pj_ice_checklist *clist) 
     671{ 
     672    unsigned i; 
     673    char buffer[128]; 
     674 
     675    PJ_LOG(4,(ice->obj_name, "%s", title)); 
     676    for (i=0; i<clist->count; ++i) { 
     677        const pj_ice_check *c = &clist->checks[i]; 
     678        PJ_LOG(4,(ice->obj_name, " %d: %s (prio=%u, state=%s)", 
     679                  i, dump_check(buffer, sizeof(buffer), ice, c), 
     680                  c->check_prio, check_state_name[c->check_state])); 
     681    } 
     682} 
     683#else 
     684#define dump_checklist(ice, clist) 
     685#endif 
     686 
     687static void sort_checklist(pj_ice_checklist *clist) 
     688{ 
     689    unsigned i; 
     690 
     691    for (i=0; i<clist->count-1; ++i) { 
     692        unsigned j, highest = i; 
     693        for (j=i+1; j<clist->count; ++j) { 
     694            if (clist->checks[j].check_prio >  
     695                clist->checks[highest].check_prio)  
     696            { 
     697                highest = j; 
     698            } 
     699        } 
     700 
     701        if (highest != i) { 
     702            pj_ice_check tmp; 
     703 
     704            pj_memcpy(&tmp, &clist->checks[i], sizeof(pj_ice_check)); 
     705            pj_memcpy(&clist->checks[i], &clist->checks[highest],  
     706                      sizeof(pj_ice_check)); 
     707            pj_memcpy(&clist->checks[highest], &tmp, sizeof(pj_ice_check)); 
     708        } 
     709    } 
     710} 
    435711 
    436712PJ_DEF(pj_status_t) pj_ice_create_check_list(pj_ice *ice, 
     
    440716{ 
    441717    pj_ice_checklist *clist; 
    442     unsigned i, j, count; 
     718    unsigned i, j; 
    443719 
    444720    PJ_ASSERT_RETURN(ice && rem_cand_cnt && rem_cand, PJ_EINVAL); 
     721    PJ_ASSERT_RETURN(rem_cand_cnt < PJ_ICE_MAX_CAND, PJ_ETOOMANY); 
    445722 
    446723    pj_mutex_lock(ice->mutex); 
    447724 
    448     /* Create checklist */ 
     725    /* Save remote candidates */ 
     726    ice->rcand_cnt = 0; 
     727    for (i=0; i<rem_cand_cnt; ++i) { 
     728        pj_ice_cand *cn = &ice->rcand[ice->rcand_cnt++]; 
     729        pj_memcpy(cn, &rem_cand[i], sizeof(pj_ice_cand)); 
     730        pj_strdup(ice->pool, &cn->foundation, &rem_cand[i].foundation); 
     731    } 
     732 
     733    /* Generate checklist */ 
    449734    clist = &ice->cklist; 
    450     clist->checks = pj_pool_calloc(ice->pool,  
    451                                    ice->cand_cnt * rem_cand_cnt, 
    452                                    sizeof(pj_ice_check)); 
    453     for (i=0, count=0; i<ice->cand_cnt; ++i) { 
     735    for (i=0; i<ice->lcand_cnt; ++i) { 
    454736        for (j=0; j<rem_cand_cnt; ++j) { 
    455737 
    456             pj_ice_check *c = &clist->checks[count++]; 
     738            pj_ice_check *c = &clist->checks[clist->count++]; 
    457739 
    458740            /* A local candidate is paired with a remote candidate if 
     
    460742             * and have the same IP address version.  
    461743             */ 
    462             if (ice->cand[i].comp_id != rem_cand[j].comp_id || 
    463                 pj_strcmp(&ice->cand[i].foundation,&rem_cand[j].foundation)==0) 
     744            if (ice->lcand[i].comp_id != rem_cand[j].comp_id || 
     745                pj_strcmp(&ice->lcand[i].foundation,&rem_cand[j].foundation)==0) 
    464746            { 
    465747                continue; 
    466748            } 
    467749 
    468             c->local_cand_id = i; 
     750            c->cand_id = i; 
     751            c->comp_id = ice->lcand[i].comp_id; 
     752            c->foundation = ice->lcand[i].foundation; 
    469753 
    470754            if (is_remote_offer) { 
    471755                c->check_prio = CALC_CHECK_PRIO(rem_cand[j].prio, 
    472                                                 ice->cand[i].prio); 
     756                                                ice->lcand[i].prio); 
    473757            } else { 
    474                 c->check_prio = CALC_CHECK_PRIO(ice->cand[i].prio,  
     758                c->check_prio = CALC_CHECK_PRIO(ice->lcand[i].prio,  
    475759                                                rem_cand[j].prio); 
    476760            } 
     
    486770    } 
    487771 
    488     clist->count = count; 
    489  
    490772    /* Sort checklist based on priority */ 
    491     for (i=0; i<clist->count-1; ++i) { 
    492         unsigned highest = i; 
    493         for (j=i+1; j<clist->count; ++j) { 
    494             if (clist->checks[j].check_prio >  
    495                 clist->checks[highest].check_prio)  
    496             { 
    497                 highest = j; 
    498             } 
    499         } 
    500  
    501         if (highest != i) { 
    502             pj_ice_check tmp; 
    503  
    504             pj_memcpy(&tmp, &clist->checks[i], sizeof(pj_ice_check)); 
    505             pj_memcpy(&clist->checks[i], &clist->checks[highest],  
    506                       sizeof(pj_ice_check)); 
    507             pj_memcpy(&clist->checks[highest], &tmp, sizeof(pj_ice_check)); 
    508         } 
    509     } 
     773    sort_checklist(clist); 
    510774 
    511775    /* Prune the checklist */ 
     
    514778    } 
    515779 
     780    /* Log checklist */ 
     781    dump_checklist("Checklist created:", ice, clist); 
     782 
    516783    pj_mutex_lock(ice->mutex); 
    517784 
     
    519786} 
    520787 
     788 
     789struct req_data 
     790{ 
     791    pj_ice              *ice; 
     792    pj_ice_checklist    *clist; 
     793    unsigned             ckid; 
     794}; 
     795 
     796/* Perform check on the specified candidate pair */ 
     797static pj_status_t perform_check(pj_ice *ice, pj_ice_checklist *clist, 
     798                                 unsigned check_id) 
     799{ 
     800    pj_stun_tx_data *tdata; 
     801    struct req_data *rd; 
     802    pj_ice_check *check; 
     803    pj_uint32_t prio; 
     804    char buffer[128]; 
     805    pj_status_t status; 
     806 
     807    check = &clist->checks[check_id]; 
     808 
     809    PJ_LOG(5,(ice->obj_name,  
     810              "Sending connectivity check for check %d: %s",  
     811              check_id, dump_check(buffer, sizeof(buffer), ice, check))); 
     812 
     813    /* Create request */ 
     814    status = pj_stun_session_create_req(ice->tx_sess,  
     815                                        PJ_STUN_BINDING_REQUEST, &tdata); 
     816    if (status != PJ_SUCCESS) 
     817        return status; 
     818 
     819    /* Attach data to be retrieved later when STUN request transaction 
     820     * completes and on_stun_request_complete() callback is called. 
     821     */ 
     822    rd = PJ_POOL_ZALLOC_T(tdata->pool, struct req_data); 
     823    rd->ice = ice; 
     824    rd->clist = clist; 
     825    rd->ckid = check_id; 
     826    tdata->user_data = (void*) rd; 
     827 
     828    /* Add PRIORITY */ 
     829    prio = CALC_CAND_PRIO(check->rem_type, 65535, check->comp_id); 
     830    pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_PRIORITY, 
     831                              prio); 
     832 
     833    /* Add USE-CANDIDATE */ 
     834    if (ice->role == PJ_ICE_ROLE_CONTROLLING) { 
     835        pj_stun_msg_add_empty_attr(tdata->pool, tdata->msg,  
     836                                   PJ_STUN_ATTR_USE_CANDIDATE); 
     837    } 
     838 
     839    /* Initiate STUN transaction to send the request */ 
     840    status = pj_stun_session_send_msg(ice->tx_sess, PJ_FALSE,  
     841                                      &check->rem_addr,  
     842                                      sizeof(pj_sockaddr_in), tdata); 
     843    if (status != PJ_SUCCESS) 
     844        return status; 
     845 
     846    check->check_state = PJ_ICE_CHECK_STATE_IN_PROGRESS; 
     847    return PJ_SUCCESS; 
     848} 
    521849 
    522850/* Start periodic check for the specified checklist */ 
    523851static pj_status_t start_periodic_check(pj_ice *ice, pj_ice_checklist *clist) 
    524852{ 
     853    unsigned i, start_count=0; 
     854    pj_status_t status; 
     855 
     856    /* Checklist state must be idle or completed */ 
     857    pj_assert(clist->state == PJ_ICE_CHECKLIST_ST_IDLE || 
     858              clist->state == PJ_ICE_CHECKLIST_ST_COMPLETED); 
     859 
     860    /* Set checklist state to Running */ 
     861    clist->state = PJ_ICE_CHECKLIST_ST_RUNNING; 
     862 
     863    PJ_LOG(4,(ice->obj_name, "Starting checklist periodic check")); 
     864 
     865    /* Send STUN Binding request for checks in Waiting list */ 
     866    for (i=0; i<clist->count; ++i) { 
     867        pj_ice_check *check = &clist->checks[i]; 
     868 
     869        if (check->check_state == PJ_ICE_CHECK_STATE_WAITING) { 
     870            status = perform_check(ice, clist, i); 
     871            if (status != PJ_SUCCESS) 
     872                return status; 
     873 
     874            ++start_count; 
     875        } 
     876    } 
     877 
     878    /* If we don't have anything in Waiting state, perform check to 
     879     * highest priority pair that is in Frozen state. 
     880     */ 
     881    if (start_count==0) { 
     882        for (i=0; i<clist->count; ++i) { 
     883            pj_ice_check *check = &clist->checks[i]; 
     884 
     885            if (check->check_state == PJ_ICE_CHECK_STATE_FROZEN) { 
     886                status = perform_check(ice, clist, i); 
     887                if (status != PJ_SUCCESS) 
     888                    return status; 
     889 
     890                ++start_count; 
     891                break; 
     892            } 
     893        } 
     894    } 
     895 
     896    /* Cannot start check because there's no suitable candidate pair. 
     897     * Set checklist state to Completed. 
     898     */ 
     899    if (start_count==0) { 
     900        clist->state = PJ_ICE_CHECKLIST_ST_COMPLETED; 
     901        PJ_LOG(4,(ice->obj_name, "Checklist completed")); 
     902    } 
     903 
     904    return PJ_SUCCESS; 
    525905} 
    526906 
     
    530910{ 
    531911    pj_ice_checklist *clist; 
    532     unsigned i, comp_id; 
    533     pj_str_t fnd; 
     912    unsigned i; 
    534913 
    535914    PJ_ASSERT_RETURN(ice, PJ_EINVAL); 
     
    547926     * states to Waiting as well. 
    548927     */ 
    549     comp_id = ice->cand[clist->checks[0].local_cand_id].comp_id; 
    550     fnd = ice->cand[clist->checks[0].local_cand_id].foundation; 
    551  
    552928    for (i=1; i<clist->count; ++i) { 
    553929        pj_ice_check *cki = &clist->checks[i]; 
    554930 
    555         if (ice->cand[cki->local_cand_id].comp_id != comp_id) 
     931        if (cki->comp_id != clist->checks[0].comp_id) 
    556932            continue; 
    557933 
    558         if (pj_strcmp(&ice->cand[cki->local_cand_id].foundation, &fnd)==0) 
     934        if (pj_strcmp(&cki->foundation, &clist->checks[0].foundation)==0) 
    559935            continue; 
    560936 
     
    565941    return start_periodic_check(ice, clist); 
    566942} 
     943 
     944 
     945////////////////////////////////////////////////////////////////////////////// 
     946 
     947static pj_status_t on_stun_send_msg(pj_stun_session *sess, 
     948                                    const void *pkt, 
     949                                    pj_size_t pkt_size, 
     950                                    const pj_sockaddr_t *dst_addr, 
     951                                    unsigned addr_len) 
     952{ 
     953    pj_ice *ice = (pj_ice*) pj_stun_session_get_user_data(sess); 
     954    return (*ice->cb.on_send_pkt)(ice, pkt, pkt_size, dst_addr, addr_len); 
     955} 
     956 
     957 
     958static pj_status_t on_stun_rx_request(pj_stun_session *sess, 
     959                                      const pj_uint8_t *pkt, 
     960                                      unsigned pkt_len, 
     961                                      const pj_stun_msg *msg, 
     962                                      const pj_sockaddr_t *src_addr, 
     963                                      unsigned src_addr_len) 
     964{ 
     965    pj_stun_tx_data *tdata; 
     966    pj_status_t status; 
     967 
     968    /* 7.2.1.2.  Learning Peer Reflexive Candidates */ 
     969    PJ_TODO(LEARN_PEER_REFLEXIVE_CANDIDATES); 
     970 
     971    /* Reject any requests except Binding request */ 
     972    if (msg->hdr.type != PJ_STUN_BINDING_REQUEST) { 
     973        status = pj_stun_session_create_response(sess, msg,  
     974                                                 PJ_STUN_SC_BAD_REQUEST, 
     975                                                 NULL, &tdata); 
     976        if (status != PJ_SUCCESS) 
     977            return status; 
     978 
     979        status = pj_stun_session_send_msg(sess, PJ_TRUE,  
     980                                          src_addr, src_addr_len, tdata); 
     981        return status; 
     982    } 
     983 
     984    status = pj_stun_session_create_response(sess, msg, 0, NULL, &tdata); 
     985    if (status != PJ_SUCCESS) 
     986        return status; 
     987 
     988    status = pj_stun_msg_add_sockaddr_attr(tdata->pool, msg,  
     989                                           PJ_STUN_ATTR_XOR_MAPPED_ADDR, 
     990                                           PJ_TRUE, src_addr, src_addr_len); 
     991 
     992    status = pj_stun_session_send_msg(sess, PJ_TRUE,  
     993                                      src_addr, src_addr_len, tdata); 
     994 
     995    /* 7.2.1.3.  Triggered Checks: 
     996     * Next, the agent constructs a pair whose local candidate is equal to 
     997     * the transport address on which the STUN request was received, and a 
     998     * remote candidate equal to the source transport address where the 
     999     * request came from (which may be peer-reflexive remote candidate that 
     1000     * was just learned).  
     1001     */ 
     1002     
     1003    return status; 
     1004} 
     1005 
     1006/* This callback is called when outgoing STUN request completed */ 
     1007static void on_stun_request_complete(pj_stun_session *sess, 
     1008                                     pj_status_t status, 
     1009                                     pj_stun_tx_data *tdata, 
     1010                                     const pj_stun_msg *response) 
     1011{ 
     1012    struct req_data *rd = (struct req_data*) tdata->user_data; 
     1013    pj_ice *ice; 
     1014    pj_ice_check *check, *valid_check; 
     1015    pj_ice_checklist *clist; 
     1016    char buffer[128]; 
     1017 
     1018    ice = rd->ice; 
     1019    check = &rd->clist->checks[rd->ckid]; 
     1020    clist = rd->clist; 
     1021 
     1022    PJ_LOG(5,(ice->obj_name,  
     1023              "Connectivity check %s for check %d: %s", 
     1024              (status==PJ_SUCCESS ? "SUCCESS" : "FAILED"), rd->ckid,  
     1025              dump_check(buffer, sizeof(buffer), ice, check))); 
     1026 
     1027    if (status != PJ_SUCCESS) { 
     1028        check->check_state = PJ_ICE_CHECK_STATE_FAILED; 
     1029        return; 
     1030    } 
     1031 
     1032    /* The agent MUST check that the source IP address and port of the 
     1033     * response equals the destination IP address and port that the Binding 
     1034     * Request was sent to, and that the destination IP address and port of 
     1035     * the response match the source IP address and port that the Binding 
     1036     * Request was sent from. 
     1037     */ 
     1038    PJ_TODO(CHECK_ICE_RESPONSE_SOURCE_ADDRESS); 
     1039 
     1040    /* Get the STUN MAPPED-ADDRESS attribute. If the 
     1041     * transport address does not match any of the local candidates that the 
     1042     * agent knows about, the mapped address represents a new candidate - a 
     1043     * peer reflexive candidate  
     1044     */ 
     1045    PJ_TODO(CHECK_ICE_RESPONSE_SOURCE_ADDRESS2); 
     1046 
     1047    /* Sets the state of the pair that generated the check to succeeded. */ 
     1048    check->check_state = PJ_ICE_CHECK_STATE_SUCCEEDED; 
     1049 
     1050    /* This is a valid pair, so add this to the valid list */ 
     1051    valid_check = &ice->valid_list.checks[ice->valid_list.count++]; 
     1052    pj_memcpy(valid_check, check, sizeof(*check)); 
     1053 
     1054    /* Sort valid_list */ 
     1055    sort_checklist(&ice->valid_list); 
     1056 
     1057 
     1058    /* If the pair had a component ID of 1, the agent MUST change the 
     1059     * states for all other Frozen pairs for the same media stream and 
     1060     * same foundation, but different component IDs, to Waiting. 
     1061     */ 
     1062    if (check->comp_id == 1) { 
     1063        unsigned i; 
     1064        for (i=0; i<clist->count; ++i)  { 
     1065            pj_ice_check *c = &clist->checks[i]; 
     1066 
     1067            if (c->check_state == PJ_ICE_CHECK_STATE_FROZEN && 
     1068                c->comp_id != check->comp_id && 
     1069                pj_strcmp(&c->foundation, &check->foundation)==0) 
     1070            { 
     1071                /* Unfreeze and start check */ 
     1072                PJ_LOG(5,(ice->obj_name, "Unfreezing check %d", i)); 
     1073                c->check_state = PJ_ICE_CHECK_STATE_WAITING; 
     1074                perform_check(ice, clist, i); 
     1075            } 
     1076        } 
     1077 
     1078    }  
     1079    /* If the pair had a component ID equal to the number of components 
     1080     * for the media stream (where this is the actual number of 
     1081     * components being used, in cases where the number of components 
     1082     * signaled in the SDP differs from offerer to answerer), the agent 
     1083     * MUST change the state for all other Frozen pairs for the first 
     1084     * component of different media streams (and thus in different check 
     1085     * lists) but the same foundation, to Waiting. 
     1086     */ 
     1087    else if (0) { 
     1088        PJ_TODO(UNFREEZE_OTHER_COMPONENT_ID); 
     1089    } 
     1090    /* If the pair has any other component ID, no other pairs can be 
     1091     * unfrozen. 
     1092     */ 
     1093    else { 
     1094        PJ_TODO(UNFREEZE_OTHER_COMPONENT_ID1); 
     1095    } 
     1096 
     1097} 
     1098 
     1099static pj_status_t on_stun_rx_indication(pj_stun_session *sess, 
     1100                                         const pj_uint8_t *pkt, 
     1101                                         unsigned pkt_len, 
     1102                                         const pj_stun_msg *msg, 
     1103                                         const pj_sockaddr_t *src_addr, 
     1104                                         unsigned src_addr_len) 
     1105{ 
     1106    PJ_TODO(SUPPORT_RX_BIND_REQUEST_AS_INDICATION); 
     1107    return PJ_ENOTSUP; 
     1108} 
     1109 
  • pjproject/trunk/pjnath/src/pjnath/stun_msg.c

    r1080 r1085  
    874874 
    875875 
     876/* 
     877 * Create STUN empty attribute and add the attribute to the message. 
     878 */ 
     879PJ_DEF(pj_status_t) pj_stun_msg_add_empty_attr( pj_pool_t *pool, 
     880                                                pj_stun_msg *msg, 
     881                                                int attr_type) 
     882{ 
     883    pj_stun_empty_attr *attr = NULL; 
     884    pj_status_t status; 
     885 
     886    status = pj_stun_empty_attr_create(pool, attr_type, &attr); 
     887    if (status != PJ_SUCCESS) 
     888        return status; 
     889 
     890    return pj_stun_msg_add_attr(msg, &attr->hdr); 
     891} 
     892 
    876893static pj_status_t decode_empty_attr(pj_pool_t *pool,  
    877894                                     const pj_uint8_t *buf,  
Note: See TracChangeset for help on using the changeset viewer.