From 1d1908a032b3d078210ca41d3d1c17d1bf90cfdd Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Mon, 2 Apr 2007 11:30:14 +0000 Subject: ICE: work in progress git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1126 74dad513-b988-da41-8d7b-12977e46ad98 --- pjnath/include/pjnath/config.h | 15 +++ pjnath/include/pjnath/ice_session.h | 41 ++++--- pjnath/include/pjnath/stun_auth.h | 2 + pjnath/include/pjnath/stun_msg.h | 4 + pjnath/include/pjnath/types.h | 19 +++- pjnath/src/pjnath/errno.c | 28 +++++ pjnath/src/pjnath/ice_session.c | 201 +++++++++++++++++++++++------------ pjnath/src/pjnath/ice_strans.c | 33 +++--- pjnath/src/pjnath/stun_auth.c | 6 +- pjnath/src/pjnath/stun_msg.c | 17 +-- pjnath/src/pjnath/stun_msg_dump.c | 7 +- pjnath/src/pjnath/stun_session.c | 18 +--- pjnath/src/pjnath/stun_transaction.c | 14 +-- 13 files changed, 264 insertions(+), 141 deletions(-) (limited to 'pjnath') diff --git a/pjnath/include/pjnath/config.h b/pjnath/include/pjnath/config.h index 3bc5afaf..dec268f8 100644 --- a/pjnath/include/pjnath/config.h +++ b/pjnath/include/pjnath/config.h @@ -31,6 +31,21 @@ * @{ */ + +/* ************************************************************************** + * GENERAL + */ + +/** + * The log level for PJNATH error display. + * + * default 1 + */ +#ifndef PJNATH_ERROR_LEVEL +# define PJNATH_ERROR_LEVEL 1 +#endif + + /* ************************************************************************** * STUN CLIENT CONFIGURATION */ diff --git a/pjnath/include/pjnath/ice_session.h b/pjnath/include/pjnath/ice_session.h index 929a4e82..36ad1b27 100644 --- a/pjnath/include/pjnath/ice_session.h +++ b/pjnath/include/pjnath/ice_session.h @@ -97,18 +97,6 @@ typedef enum pj_ice_cand_type } pj_ice_cand_type; -/** - * This enumeration describes the default preference for the ICE - * candidate types as described by ICE standard. - */ -enum pj_ice_type_pref -{ - PJ_ICE_HOST_PREF = 126, /**< Preference value for host. */ - PJ_ICE_SRFLX_PREF = 100, /**< Preference value for SRFLX. */ - PJ_ICE_PRFLX_PREF = 110, /**< Preference value for PRFLX */ - PJ_ICE_RELAYED_PREF = 0 /**< Preference value for relay */ -}; - /** Forward declaration for pj_ice_sess */ typedef struct pj_ice_sess pj_ice_sess; @@ -273,7 +261,7 @@ struct pj_ice_sess_check /** * Check priority. */ - pj_uint64_t prio; + pj_timestamp prio; /** * Connectivity check state. @@ -445,6 +433,7 @@ struct pj_ice_sess pj_mutex_t *mutex; /**< Mutex. */ pj_ice_sess_role role; /**< ICE role. */ pj_timestamp tie_breaker; /**< Tie breaker value */ + pj_uint8_t *prefs; /**< Type preference. */ pj_bool_t is_complete; /**< Complete? */ pj_status_t ice_status; /**< Error status. */ pj_ice_sess_cb cb; /**< Callback. */ @@ -565,6 +554,28 @@ PJ_DECL(pj_status_t) pj_ice_sess_change_role(pj_ice_sess *ice, pj_ice_sess_role new_role); +/** + * Assign a custom preference values for ICE candidate types. By assigning + * custom preference value, application can control the order of candidates + * to be checked first. The default preference settings is to use 126 for + * host candidates, 100 for server reflexive candidates, 110 for peer + * reflexive candidates, an 0 for relayed candidates. + * + * Note that this function must be called before any candidates are added + * to the ICE session. + * + * @param ice The ICE session. + * @param prefs Array of candidate preference value. The values are + * put in the array indexed by the candidate type as + * specified in pj_ice_cand_type. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice, + const pj_uint8_t prefs[4]); + + + /** * Add a candidate to this ICE session. Application must add candidates for * each components ID before it can start pairing the candidates and @@ -595,6 +606,9 @@ PJ_DECL(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, int addr_len, unsigned *p_cand_id); +#if 0 +/* Temporarily disabled to reduce size, since we don't need this yet */ + /** * Find default candidate for the specified component ID, using this * rule: @@ -612,6 +626,7 @@ PJ_DECL(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, PJ_DECL(pj_status_t) pj_ice_sess_find_default_cand(pj_ice_sess *ice, unsigned comp_id, int *p_cand_id); +#endif /** * Pair the local and remote candidates to create check list. Application diff --git a/pjnath/include/pjnath/stun_auth.h b/pjnath/include/pjnath/stun_auth.h index 6914036d..539c8867 100644 --- a/pjnath/include/pjnath/stun_auth.h +++ b/pjnath/include/pjnath/stun_auth.h @@ -225,6 +225,8 @@ typedef struct pj_stun_auth_cred * in the message can be accepted. If this callback returns * PJ_FALSE, 438 (Stale Nonce) response will be created. * + * This callback is optional. + * * @param msg The STUN message where the nonce was received. * @param user_data The user data as specified in the credential. * @param realm The realm as specified in the message. diff --git a/pjnath/include/pjnath/stun_msg.h b/pjnath/include/pjnath/stun_msg.h index 6c716a0c..f1544de3 100644 --- a/pjnath/include/pjnath/stun_msg.h +++ b/pjnath/include/pjnath/stun_msg.h @@ -1228,10 +1228,14 @@ PJ_DECL(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, * * @return The message string output. */ +#if PJ_LOG_MAX_LEVEL > 0 PJ_DECL(char*) pj_stun_msg_dump(const pj_stun_msg *msg, char *buffer, unsigned length, unsigned *printed_len); +#else +# define pj_stun_msg_dump(msg, buf, length, printed_len) "" +#endif /** diff --git a/pjnath/include/pjnath/types.h b/pjnath/include/pjnath/types.h index 72c326af..10544d22 100644 --- a/pjnath/include/pjnath/types.h +++ b/pjnath/include/pjnath/types.h @@ -37,11 +37,27 @@ PJ_BEGIN_DECL /** * Initialize pjnath library. * - * @return Initialization status. + * @return Initialization status. */ PJ_DECL(pj_status_t) pjnath_init(void); +/** + * Display error to the log. + * + * @param sender The sender name. + * @param title Title message. + * @param status The error status. + */ +#if PJNATH_ERROR_LEVEL <= PJ_LOG_MAX_LEVEL +PJ_DECL(void) pjnath_perror(const char *sender, const char *title, + pj_status_t status); +#else +# define pjnath_perror(sender, title, status) +#endif + + + PJ_END_DECL /** @@ -147,6 +163,7 @@ PJ_END_DECL * for different types of application, including but not limited to * the usage of ICE in SIP/SDP offer/answer. * + * * \subsection PJNATH_ICE_ARCH ICE Library Organization * * \image html ice-arch.jpg "ICE Architecture" diff --git a/pjnath/src/pjnath/errno.c b/pjnath/src/pjnath/errno.c index 7ac88922..ed1f658f 100644 --- a/pjnath/src/pjnath/errno.c +++ b/pjnath/src/pjnath/errno.c @@ -18,6 +18,7 @@ */ #include #include +#include #include @@ -165,3 +166,30 @@ PJ_DEF(pj_status_t) pjnath_init(void) return status; } + +#if PJNATH_ERROR_LEVEL <= PJ_LOG_MAX_LEVEL + +PJ_DEF(void) pjnath_perror(const char *sender, const char *title, + pj_status_t status) +{ + char errmsg[PJ_ERR_MSG_SIZE]; + + pj_strerror(status, errmsg, sizeof(errmsg)); + +#if PJNATH_ERROR_LEVEL==1 + PJ_LOG(1,(sender, "%s: %s", title, errmsg)); +#elif PJNATH_ERROR_LEVEL==2 + PJ_LOG(2,(sender, "%s: %s", title, errmsg)); +#elif PJNATH_ERROR_LEVEL==3 + PJ_LOG(3,(sender, "%s: %s", title, errmsg)); +#elif PJNATH_ERROR_LEVEL==4 + PJ_LOG(4,(sender, "%s: %s", title, errmsg)); +#elif PJNATH_ERROR_LEVEL==5 + PJ_LOG(5,(sender, "%s: %s", title, errmsg)); +#else +# error Invalid PJNATH_ERROR_LEVEL value +#endif +} + +#endif /* PJNATH_ERROR_LEVEL <= PJ_LOG_MAX_LEVEL */ + diff --git a/pjnath/src/pjnath/ice_session.c b/pjnath/src/pjnath/ice_session.c index 09617965..50c593bd 100644 --- a/pjnath/src/pjnath/ice_session.c +++ b/pjnath/src/pjnath/ice_session.c @@ -40,6 +40,7 @@ static const char *cand_type_names[] = }; /* String names for pj_ice_sess_check_state */ +#if PJ_LOG_MAX_LEVEL >= 4 static const char *check_state_name[] = { "Frozen", @@ -55,6 +56,7 @@ static const char *clist_state_name[] = "Running", "Completed" }; +#endif /* PJ_LOG_MAX_LEVEL >= 4 */ static const char *role_names[] = { @@ -62,6 +64,15 @@ static const char *role_names[] = "Controlling" }; +/* Default ICE session preferences, according to draft-ice */ +static pj_uint8_t cand_type_prefs[4] = +{ + 126, /**< PJ_ICE_HOST_PREF */ + 100, /**< PJ_ICE_SRFLX_PREF. */ + 110, /**< PJ_ICE_PRFLX_PREF */ + 0 /**< PJ_ICE_RELAYED_PREF */ +}; + #define CHECK_NAME_LEN 128 #define LOG4(expr) PJ_LOG(4,expr) #define LOG5(expr) PJ_LOG(4,expr) @@ -71,15 +82,14 @@ static const char *role_names[] = typedef struct stun_data { - pj_ice_sess *ice; - unsigned lcand_id; + pj_ice_sess *ice; pj_ice_sess_cand *lcand; } stun_data; typedef struct timer_data { - pj_ice_sess *ice; - pj_ice_sess_checklist *clist; + pj_ice_sess *ice; + pj_ice_sess_checklist *clist; } timer_data; @@ -131,11 +141,6 @@ static pj_status_t stun_auth_get_password(const pj_stun_msg *msg, pj_pool_t *pool, int *data_type, pj_str_t *data); -static pj_bool_t stun_auth_verify_nonce(const pj_stun_msg *msg, - void *user_data, - const pj_str_t *realm, - const pj_str_t *username, - const pj_str_t *nonce); PJ_DEF(const char*) pj_ice_get_cand_type_name(pj_ice_cand_type type) @@ -188,8 +193,6 @@ PJ_DEF(pj_status_t) pj_ice_sess_create(pj_stun_config *stun_cfg, { pj_pool_t *pool; pj_ice_sess *ice; - char tmp[64]; - pj_str_t s; unsigned i; pj_status_t status; @@ -204,6 +207,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_create(pj_stun_config *stun_cfg, ice->role = role; ice->tie_breaker.u32.hi = pj_rand(); ice->tie_breaker.u32.lo = pj_rand(); + ice->prefs = cand_type_prefs; pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name), name, ice); @@ -226,18 +230,18 @@ PJ_DEF(pj_status_t) pj_ice_sess_create(pj_stun_config *stun_cfg, } if (local_ufrag == NULL) { - pj_ansi_snprintf(tmp, sizeof(tmp), "%x%x", pj_rand(), pj_rand()); - s = pj_str(tmp); - local_ufrag = &s; + ice->rx_ufrag.ptr = pj_pool_alloc(ice->pool, 16); + pj_create_random_string(ice->rx_ufrag.ptr, 16); + } else { + pj_strdup(ice->pool, &ice->rx_ufrag, local_ufrag); } - pj_strdup(ice->pool, &ice->rx_ufrag, local_ufrag); if (local_passwd == NULL) { - pj_ansi_snprintf(tmp, sizeof(tmp), "%x%x", pj_rand(), pj_rand()); - s = pj_str(tmp); - local_passwd = &s; + ice->rx_pass.ptr = pj_pool_alloc(ice->pool, 16); + pj_create_random_string(ice->rx_pass.ptr, 16); + } else { + pj_strdup(ice->pool, &ice->rx_pass, local_passwd); } - pj_strdup(ice->pool, &ice->rx_pass, local_passwd); /* Done */ @@ -316,6 +320,20 @@ PJ_DEF(pj_status_t) pj_ice_sess_change_role(pj_ice_sess *ice, } +/* + * Change type preference + */ +PJ_DEF(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice, + const pj_uint8_t prefs[4]) +{ + PJ_ASSERT_RETURN(ice && prefs, PJ_EINVAL); + ice->prefs = pj_pool_calloc(ice->pool, PJ_ARRAY_SIZE(prefs), + sizeof(pj_uint8_t)); + pj_memcpy(ice->prefs, prefs, sizeof(prefs)); + return PJ_SUCCESS; +} + + /* Find component by ID */ static pj_ice_sess_comp *find_comp(const pj_ice_sess *ice, unsigned comp_id) { @@ -421,35 +439,12 @@ static pj_status_t stun_auth_get_password(const pj_stun_msg *msg, } -static pj_bool_t stun_auth_verify_nonce(const pj_stun_msg *msg, - void *user_data, - const pj_str_t *realm, - const pj_str_t *username, - const pj_str_t *nonce) -{ - /* We don't use NONCE */ - PJ_UNUSED_ARG(msg); - PJ_UNUSED_ARG(user_data); - PJ_UNUSED_ARG(realm); - PJ_UNUSED_ARG(username); - PJ_UNUSED_ARG(nonce); - return PJ_TRUE; -} - - -static pj_uint32_t CALC_CAND_PRIO(pj_ice_cand_type type, +static pj_uint32_t CALC_CAND_PRIO(pj_ice_sess *ice, + pj_ice_cand_type type, pj_uint32_t local_pref, pj_uint32_t comp_id) { - pj_uint32_t type_pref[] = - { - PJ_ICE_HOST_PREF, - PJ_ICE_SRFLX_PREF, - PJ_ICE_PRFLX_PREF, - PJ_ICE_RELAYED_PREF - }; - - return ((type_pref[type] & 0xFF) << 24) + + return ((ice->prefs[type] & 0xFF) << 24) + ((local_pref & 0xFFFF) << 8) + (((256 - comp_id) & 0xFF) << 0); } @@ -492,7 +487,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, lcand->comp_id = comp_id; lcand->type = type; pj_strdup(ice->pool, &lcand->foundation, foundation); - lcand->prio = CALC_CAND_PRIO(type, local_pref, lcand->comp_id); + lcand->prio = CALC_CAND_PRIO(ice, type, local_pref, lcand->comp_id); pj_memcpy(&lcand->addr, addr, addr_len); pj_memcpy(&lcand->base_addr, base_addr, addr_len); if (rel_addr) @@ -520,7 +515,6 @@ PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, /* Associate data with this STUN session */ sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data); sd->ice = ice; - sd->lcand_id = GET_LCAND_ID(lcand); sd->lcand = lcand; pj_stun_session_set_user_data(lcand->stun_sess, sd); @@ -530,7 +524,6 @@ PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth; auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred; auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; - auth_cred.data.dyn_cred.verify_nonce = &stun_auth_verify_nonce; auth_cred.data.dyn_cred.user_data = lcand->stun_sess; pj_stun_session_set_credential(lcand->stun_sess, &auth_cred); @@ -562,6 +555,7 @@ on_error: /* Find default candidate ID for the component */ +#if 0 PJ_DEF(pj_status_t) pj_ice_sess_find_default_cand(pj_ice_sess *ice, unsigned comp_id, int *cand_id) @@ -629,6 +623,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_find_default_cand(pj_ice_sess *ice, pj_assert(!"Should have a candidate by now"); return PJ_EBUG; } +#endif /* if 0 */ #ifndef MIN @@ -639,11 +634,16 @@ PJ_DEF(pj_status_t) pj_ice_sess_find_default_cand(pj_ice_sess *ice, # define MAX(a,b) (a > b ? a : b) #endif -static pj_uint64_t CALC_CHECK_PRIO(const pj_ice_sess *ice, - const pj_ice_sess_cand *lcand, - const pj_ice_sess_cand *rcand) +static pj_timestamp CALC_CHECK_PRIO(const pj_ice_sess *ice, + const pj_ice_sess_cand *lcand, + const pj_ice_sess_cand *rcand) { pj_uint32_t O, A; + pj_timestamp prio; + + /* Original formula: + * pair priority = 2^32*MIN(O,A) + 2*MAX(O,A) + (O>A?1:0) + */ if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLING) { O = lcand->prio; @@ -653,10 +653,26 @@ static pj_uint64_t CALC_CHECK_PRIO(const pj_ice_sess *ice, A = lcand->prio; } + /* return ((pj_uint64_t)1 << 32) * MIN(O, A) + (pj_uint64_t)2 * MAX(O, A) + (O>A ? 1 : 0); + */ + + prio.u32.hi = MIN(O,A); + prio.u32.lo = (MAX(O, A) << 1) + (O>A ? 1 : 0); + + return prio; } + +PJ_INLINE(int) CMP_CHECK_PRIO(const pj_ice_sess_check *c1, + const pj_ice_sess_check *c2) +{ + return pj_cmp_timestamp(&c1->prio, &c2->prio); +} + + +#if PJ_LOG_MAX_LEVEL >= 4 static const char *dump_check(char *buffer, unsigned bufsize, const pj_ice_sess_checklist *clist, const pj_ice_sess_check *check) @@ -690,7 +706,6 @@ static const char *dump_check(char *buffer, unsigned bufsize, return buffer; } -#if PJ_LOG_MAX_LEVEL >= 4 static void dump_checklist(const char *title, const pj_ice_sess *ice, const pj_ice_sess_checklist *clist) { @@ -746,7 +761,7 @@ static void sort_checklist(pj_ice_sess_checklist *clist) for (i=0; icount-1; ++i) { unsigned j, highest = i; for (j=i+1; jcount; ++j) { - if (clist->checks[j].prio > clist->checks[highest].prio) { + if (CMP_CHECK_PRIO(&clist->checks[j], &clist->checks[highest]) > 0) { highest = j; } } @@ -827,15 +842,15 @@ static void prune_checklist(pj_ice_sess *ice, pj_ice_sess_checklist *clist) else ljaddr = &ljcand->addr; - if (sockaddr_cmp(liaddr, ljaddr) == SOCKADDR_EQUAL && - sockaddr_cmp(&ricand->addr, &rjcand->addr) == SOCKADDR_EQUAL) + if (ricand == rjcand && + sockaddr_cmp(liaddr, ljaddr) == SOCKADDR_EQUAL) { /* Found duplicate, remove it */ char buf[CHECK_NAME_LEN]; LOG5((ice->obj_name, "Check %s pruned", - dump_check(buf, sizeof(buf), &ice->clist, - &clist->checks[j]))); + dump_check(buf, sizeof(buf), &ice->clist, + &clist->checks[j]))); pj_array_erase(clist->checks, sizeof(clist->checks[0]), clist->count, j); @@ -928,7 +943,7 @@ static pj_bool_t on_check_complete(pj_ice_sess *ice, if (comp->valid_check == NULL) { comp->valid_check = check; } else { - if (comp->valid_check->prio < check->prio) + if (CMP_CHECK_PRIO(comp->valid_check, check) < 0) comp->valid_check = check; } } @@ -1154,8 +1169,10 @@ static pj_status_t perform_check(pj_ice_sess *ice, status = pj_stun_session_create_req(lcand->stun_sess, PJ_STUN_BINDING_REQUEST, &check->tdata); - if (status != PJ_SUCCESS) + if (status != PJ_SUCCESS) { + pjnath_perror(ice->obj_name, "Error creating STUN request", status); return status; + } /* Attach data to be retrieved later when STUN request transaction * completes and on_stun_request_complete() callback is called. @@ -1167,7 +1184,7 @@ static pj_status_t perform_check(pj_ice_sess *ice, check->tdata->user_data = (void*) rd; /* Add PRIORITY */ - prio = CALC_CAND_PRIO(PJ_ICE_CAND_TYPE_PRFLX, 65535, + prio = CALC_CAND_PRIO(ice, PJ_ICE_CAND_TYPE_PRFLX, 65535, lcand->comp_id); pj_stun_msg_add_uint_attr(check->tdata->pool, check->tdata->msg, PJ_STUN_ATTR_PRIORITY, prio); @@ -1189,6 +1206,7 @@ static pj_status_t perform_check(pj_ice_sess *ice, sizeof(pj_sockaddr_in), check->tdata); if (status != PJ_SUCCESS) { check->tdata = NULL; + pjnath_perror(ice->obj_name, "Error sending STUN request", status); return status; } @@ -1289,38 +1307,79 @@ static void periodic_timer(pj_timer_heap_t *th, start_periodic_check(th, te); } + +/* Utility: find string in string array */ +const pj_str_t *find_str(const pj_str_t *strlist[], unsigned count, + const pj_str_t *str) +{ + unsigned i; + for (i=0; iclist.count > 0, PJ_EINVALIDOP); LOG4((ice->obj_name, "Starting ICE check..")); + /* The agent examines the check list for the first media stream (a + * media stream is the first media stream when it is described by + * the first m-line in the SDP offer and answer). For that media + * stream, it: + * + * - Groups together all of the pairs with the same foundation, + * + * - For each group, sets the state of the pair with the lowest + * component ID to Waiting. If there is more than one such pair, + * the one with the highest priority is used. + */ + clist = &ice->clist; - /* Pickup the first pair and set the state to Waiting */ - clist->checks[0].state = PJ_ICE_SESS_CHECK_STATE_WAITING; - cand0 = clist->checks[0].lcand; + /* Pickup the first pair for component 1. */ + for (i=0; icount; ++i) { + if (clist->checks[0].lcand->comp_id == 1) + break; + } + if (i == clist->count) { + pj_assert(!"Unable to find checklist for component 1"); + return PJNATH_EICEINCOMPID; + } + + /* Set this check to WAITING */ + check_set_state(ice, &clist->checks[i], + PJ_ICE_SESS_CHECK_STATE_WAITING, PJ_SUCCESS); + cand0 = clist->checks[i].lcand; + flist[flist_cnt++] = &clist->checks[i].lcand->foundation; /* Find all of the other pairs in that check list with the same * component ID, but different foundations, and sets all of their * states to Waiting as well. */ - for (i=1; icount; ++i) { + for (++i; icount; ++i) { const pj_ice_sess_cand *cand1; cand1 = clist->checks[i].lcand; - if (cand0->comp_id == cand1->comp_id && - pj_strcmp(&cand0->foundation, &cand1->foundation)!=0) + if (cand1->comp_id==cand0->comp_id && + find_str(flist, flist_cnt, &cand1->foundation)==NULL) { - clist->checks[i].state = PJ_ICE_SESS_CHECK_STATE_WAITING; + check_set_state(ice, &clist->checks[i], + PJ_ICE_SESS_CHECK_STATE_WAITING, PJ_SUCCESS); + flist[flist_cnt++] = &cand1->foundation; } } @@ -1341,7 +1400,9 @@ static pj_status_t on_stun_send_msg(pj_stun_session *sess, unsigned addr_len) { stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess); - return (*sd->ice->cb.on_tx_pkt)(sd->ice, sd->lcand->comp_id, sd->lcand_id, + pj_ice_sess *ice = sd->ice; + return (*sd->ice->cb.on_tx_pkt)(sd->ice, sd->lcand->comp_id, + GET_LCAND_ID(sd->lcand), pkt, pkt_size, dst_addr, addr_len); } diff --git a/pjnath/src/pjnath/ice_strans.c b/pjnath/src/pjnath/ice_strans.c index 378d13a4..082d310a 100644 --- a/pjnath/src/pjnath/ice_strans.c +++ b/pjnath/src/pjnath/ice_strans.c @@ -65,19 +65,7 @@ static void start_ka_timer(pj_ice_strans *ice_st); static void stop_ka_timer(pj_ice_strans *ice_st); /* Utility: print error */ -#if PJ_LOG_MAX_LEVEL >= 3 -static void ice_st_perror(pj_ice_strans *ice_st, const char *title, - pj_status_t status) -{ - char errmsg[PJ_ERR_MSG_SIZE]; - - pj_strerror(status, errmsg, sizeof(errmsg)); - PJ_LOG(3,(ice_st->obj_name, "%s: %s", title, errmsg)); -} -#else -# define ice_st_perror(ice_st, title, status) -#endif - +#define ice_st_perror(ice_st,msg,rc) pjnath_perror(ice_st->obj_name,msg,rc) /* * Create ICE stream transport @@ -344,6 +332,7 @@ static pj_status_t create_component(pj_ice_strans *ice_st, for (i=0; i> 24)==127) @@ -358,14 +347,15 @@ static pj_status_t create_component(pj_ice_strans *ice_st, */ if (ifs[i].s_addr == comp->local_addr.ipv4.sin_addr.s_addr) { set_default = PJ_TRUE; + local_pref = 65535; } else { set_default = PJ_FALSE; + local_pref = 0; } status = add_cand(ice_st, comp, comp_id, PJ_ICE_CAND_TYPE_HOST, - (pj_uint16_t)(65535-i), &cand_addr, - set_default); + local_pref, &cand_addr, set_default); if (status != PJ_SUCCESS) goto on_error; } @@ -759,6 +749,7 @@ PJ_DEF(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st, pj_status_t status; unsigned i; pj_ice_sess_cb ice_cb; + const pj_uint8_t srflx_prio[4] = { 100, 126, 110, 0 }; /* Check arguments */ PJ_ASSERT_RETURN(ice_st, PJ_EINVAL); @@ -783,6 +774,18 @@ PJ_DEF(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st, /* Associate user data */ ice_st->ice->user_data = (void*)ice_st; + /* If default candidate for components are SRFLX one, upload a custom + * type priority to ICE session so that SRFLX candidates will get + * checked first. + */ + if (ice_st->comp[0]->default_cand >= 0 && + ice_st->comp[0]->cand_list[ice_st->comp[0]->default_cand].type + == PJ_ICE_CAND_TYPE_SRFLX) + { + pj_ice_sess_set_prefs(ice_st->ice, srflx_prio); + } + + /* Add candidates */ for (i=0; icomp_cnt; ++i) { unsigned j; diff --git a/pjnath/src/pjnath/stun_auth.c b/pjnath/src/pjnath/stun_auth.c index 15f226dc..3f5a77a5 100644 --- a/pjnath/src/pjnath/stun_auth.c +++ b/pjnath/src/pjnath/stun_auth.c @@ -269,12 +269,16 @@ PJ_DEF(pj_status_t) pj_stun_verify_credential( const pj_uint8_t *pkt, if (anonce) { pj_bool_t ok; - if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { + if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC && + cred->data.dyn_cred.verify_nonce != NULL) + { ok=cred->data.dyn_cred.verify_nonce(msg, cred->data.dyn_cred.user_data, (arealm?&arealm->value:NULL), &auser->value, &anonce->value); + } else if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { + ok = PJ_TRUE; } else { if (nonce.slen) { ok = !pj_strcmp(&anonce->value, &nonce); diff --git a/pjnath/src/pjnath/stun_msg.c b/pjnath/src/pjnath/stun_msg.c index 072a7a1b..5b54ff38 100644 --- a/pjnath/src/pjnath/stun_msg.c +++ b/pjnath/src/pjnath/stun_msg.c @@ -139,7 +139,7 @@ static pj_status_t encode_empty_attr(const void *a, pj_uint8_t *buf, unsigned len, unsigned *printed); -struct attr_desc mandatory_attr_desc[] = +static struct attr_desc mandatory_attr_desc[] = { { /* type zero */ @@ -437,13 +437,13 @@ static struct attr_desc extended_attr_desc[] = }, { /* PJ_STUN_ATTR_ICE_CONTROLLED, */ - "ICE-CCONTROLLED", + "ICE-CONTROLLED", &decode_uint64_attr, &encode_uint64_attr }, { /* PJ_STUN_ATTR_ICE_CONTROLLING, */ - "ICE-CCONTROLLING", + "ICE-CONTROLLING", &decode_uint64_attr, &encode_uint64_attr } @@ -1870,8 +1870,6 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, if (has_msg_int) { /* Already has MESSAGE-INTEGRITY */ if (p_response) { - pj_str_t e; - e = pj_str("MESSAGE-INTEGRITY already present"); pj_stun_msg_create_response(pool, msg, PJ_STUN_SC_BAD_REQUEST, NULL, p_response); @@ -1884,8 +1882,6 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, if (has_fingerprint) { /* Already has FINGERPRINT */ if (p_response) { - pj_str_t e; - e = pj_str("FINGERPRINT already present"); pj_stun_msg_create_response(pool, msg, PJ_STUN_SC_BAD_REQUEST, NULL, p_response); @@ -1898,8 +1894,6 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, /* Another attribute is found which is not FINGERPRINT * after FINGERPRINT or MESSAGE-INTEGRITY */ if (p_response) { - pj_str_t e; - e = pj_str("Invalid attribute order"); pj_stun_msg_create_response(pool, msg, PJ_STUN_SC_BAD_REQUEST, NULL, p_response); @@ -1912,12 +1906,9 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, /* Make sure we have rooms for the new attribute */ if (msg->attr_count >= PJ_STUN_MAX_ATTR) { if (p_response) { - pj_str_t e; - - e = pj_str("Too many attributes"); pj_stun_msg_create_response(pool, msg, PJ_STUN_SC_BAD_REQUEST, - &e, p_response); + NULL, p_response); } return PJNATH_ESTUNTOOMANYATTR; } diff --git a/pjnath/src/pjnath/stun_msg_dump.c b/pjnath/src/pjnath/stun_msg_dump.c index e888e91e..0da2cc21 100644 --- a/pjnath/src/pjnath/stun_msg_dump.c +++ b/pjnath/src/pjnath/stun_msg_dump.c @@ -22,6 +22,9 @@ #include +#if PJ_LOG_MAX_LEVEL > 0 + + #define APPLY() if (len < 1 || len >= (end-p)) \ goto on_return; \ p += len @@ -244,7 +247,9 @@ on_return: *printed_len = (p-buffer); return buffer; +#undef APPLY } -#undef APPLY +#endif /* PJ_LOG_MAX_LEVEL > 0 */ + diff --git a/pjnath/src/pjnath/stun_session.c b/pjnath/src/pjnath/stun_session.c index 2694d5ac..5f308fcd 100644 --- a/pjnath/src/pjnath/stun_session.c +++ b/pjnath/src/pjnath/stun_session.c @@ -43,21 +43,7 @@ struct pj_stun_session # define TRACE_(expr) #endif -#if PJ_LOG_MAX_LEVEL >= 4 -# define LOG_ERR_(sess, title, rc) stun_perror(sess, title, rc) -static void stun_perror(pj_stun_session *sess, const char *title, - pj_status_t status) -{ - char errmsg[PJ_ERR_MSG_SIZE]; - - pj_strerror(status, errmsg, sizeof(errmsg)); - - PJ_LOG(4,(SNAME(sess), "%s: %s", title, errmsg)); -} - -#else -# define LOG_ERR_(sess, title, rc) -#endif +#define LOG_ERR_(sess,title,rc) pjnath_perror(sess->pool->obj_name,title,rc) #define TDATA_POOL_SIZE 1024 #define TDATA_POOL_INC 1024 @@ -779,7 +765,7 @@ static pj_status_t on_incoming_response(pj_stun_session *sess, /* Lookup pending client transaction */ tdata = tsx_lookup(sess, msg); if (tdata == NULL) { - PJ_LOG(4,(SNAME(sess), + PJ_LOG(5,(SNAME(sess), "Transaction not found, response silently discarded")); return PJ_SUCCESS; } diff --git a/pjnath/src/pjnath/stun_transaction.c b/pjnath/src/pjnath/stun_transaction.c index 69829919..5d6f80f6 100644 --- a/pjnath/src/pjnath/stun_transaction.c +++ b/pjnath/src/pjnath/stun_transaction.c @@ -50,15 +50,7 @@ struct pj_stun_client_tsx static void retransmit_timer_callback(pj_timer_heap_t *timer_heap, pj_timer_entry *timer); -static void stun_perror(pj_stun_client_tsx *tsx, const char *title, - pj_status_t status) -{ - char errmsg[PJ_ERR_MSG_SIZE]; - - pj_strerror(status, errmsg, sizeof(errmsg)); - PJ_LOG(4,(tsx->obj_name, "%s: %s", title, errmsg)); -} - +#define stun_perror(tsx,msg,rc) pjnath_perror(tsx->obj_name, msg, rc) /* * Create a STUN client transaction. @@ -84,7 +76,7 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_create(pj_stun_config *cfg, *p_tsx = tsx; - PJ_LOG(4,(tsx->obj_name, "STUN client transaction created")); + PJ_LOG(5,(tsx->obj_name, "STUN client transaction created")); return PJ_SUCCESS; } @@ -191,7 +183,7 @@ static pj_status_t tsx_transmit_msg(pj_stun_client_tsx *tsx) tsx->transmit_count++; - PJ_LOG(4,(tsx->obj_name, "STUN sending message (transmit count=%d)", + PJ_LOG(5,(tsx->obj_name, "STUN sending message (transmit count=%d)", tsx->transmit_count)); return status; } -- cgit v1.2.3