From bd086483084600546e8336cbd5d24fa9561847fe Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Thu, 5 Apr 2007 22:28:01 +0000 Subject: Respond to early check with proper credential git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1154 74dad513-b988-da41-8d7b-12977e46ad98 --- pjnath/src/pjnath/errno.c | 1 + pjnath/src/pjnath/ice_session.c | 105 +++++++++++++++++++++++++++++++-------- pjnath/src/pjnath/ice_strans.c | 7 ++- pjnath/src/pjnath/stun_session.c | 2 +- 4 files changed, 91 insertions(+), 24 deletions(-) (limited to 'pjnath/src') diff --git a/pjnath/src/pjnath/errno.c b/pjnath/src/pjnath/errno.c index d555336b..21a42d4e 100644 --- a/pjnath/src/pjnath/errno.c +++ b/pjnath/src/pjnath/errno.c @@ -59,6 +59,7 @@ static const struct PJ_BUILD_ERR( PJNATH_EICEINSRCADDR, "Source address mismatch"), PJ_BUILD_ERR( PJNATH_EICEMISSINGSDP, "Missing ICE SDP attribute"), PJ_BUILD_ERR( PJNATH_EICEINCANDSDP, "Invalid SDP \"candidate\" attribute"), + PJ_BUILD_ERR( PJNATH_EICENOHOSTCAND, "No host candidate associated with srflx"), }; #endif /* PJ_HAS_ERROR_STRING */ diff --git a/pjnath/src/pjnath/ice_session.c b/pjnath/src/pjnath/ice_session.c index 502eb360..0bfbe5f6 100644 --- a/pjnath/src/pjnath/ice_session.c +++ b/pjnath/src/pjnath/ice_session.c @@ -60,6 +60,7 @@ static const char *clist_state_name[] = static const char *role_names[] = { + "Unknown", "Controlled", "Controlling" }; @@ -850,7 +851,8 @@ static int sockaddr_cmp(const pj_sockaddr *a1, const pj_sockaddr *a2) /* Prune checklist, this must have been done after the checklist * is sorted. */ -static void prune_checklist(pj_ice_sess *ice, pj_ice_sess_checklist *clist) +static pj_status_t prune_checklist(pj_ice_sess *ice, + pj_ice_sess_checklist *clist) { unsigned i; @@ -864,30 +866,52 @@ static void prune_checklist(pj_ice_sess *ice, pj_ice_sess_checklist *clist) * higher up on the priority list. The result is a sequence of ordered * candidate pairs, called the check list for that media stream. */ + /* First replace SRFLX candidates with their base */ + for (i=0; icount; ++i) { + pj_ice_sess_cand *srflx = clist->checks[i].lcand; + + if (clist->checks[i].lcand->type == PJ_ICE_CAND_TYPE_SRFLX) { + /* Find the base for this candidate */ + unsigned j; + for (j=0; jlcand_cnt; ++j) { + pj_ice_sess_cand *host = &ice->lcand[j]; + + if (host->type != PJ_ICE_CAND_TYPE_HOST) + continue; + + if (sockaddr_cmp(&srflx->base_addr, &host->addr) == 0) { + /* Replace this SRFLX with its BASE */ + clist->checks[i].lcand = host; + break; + } + } + + if (j==ice->lcand_cnt) { + /* Host candidate not found this this srflx! */ + LOG4((ice->obj_name, + "Base candidate %s:%d not found for srflx candidate %d", + pj_inet_ntoa(srflx->base_addr.ipv4.sin_addr), + pj_ntohs(srflx->base_addr.ipv4.sin_port), + GET_LCAND_ID(clist->checks[i].lcand))); + return PJNATH_EICENOHOSTCAND; + } + } + } + + /* Next remove a pair if its local and remote candidates are identical + * to the local and remote candidates of a pair higher up on the priority + * list + */ for (i=0; icount; ++i) { pj_ice_sess_cand *licand = clist->checks[i].lcand; pj_ice_sess_cand *ricand = clist->checks[i].rcand; - const pj_sockaddr *liaddr; unsigned j; - if (licand->type == PJ_ICE_CAND_TYPE_SRFLX) - liaddr = &licand->base_addr; - else - liaddr = &licand->addr; - for (j=i+1; jcount;) { pj_ice_sess_cand *ljcand = clist->checks[j].lcand; pj_ice_sess_cand *rjcand = clist->checks[j].rcand; - const pj_sockaddr *ljaddr; - - if (ljcand->type == PJ_ICE_CAND_TYPE_SRFLX) - ljaddr = &ljcand->base_addr; - else - ljaddr = &ljcand->addr; - if (ricand == rjcand && - sockaddr_cmp(liaddr, ljaddr) == SOCKADDR_EQUAL) - { + if ((licand == ljcand) && (ricand == rjcand)) { /* Found duplicate, remove it */ char buf[CHECK_NAME_LEN]; @@ -904,6 +928,8 @@ static void prune_checklist(pj_ice_sess *ice, pj_ice_sess_checklist *clist) } } } + + return PJ_SUCCESS; } /* This function is called when ICE processing completes */ @@ -1124,6 +1150,7 @@ pj_ice_sess_create_check_list(pj_ice_sess *ice, pj_str_t username; timer_data *td; unsigned i, j; + pj_status_t status; PJ_ASSERT_RETURN(ice && rem_ufrag && rem_passwd && rcand_cnt && rcand, PJ_EINVAL); @@ -1174,7 +1201,7 @@ pj_ice_sess_create_check_list(pj_ice_sess *ice, pj_ice_sess_cand *rcand = &ice->rcand[j]; pj_ice_sess_check *chk = &clist->checks[clist->count]; - if (clist->count > PJ_ICE_MAX_CHECKS) { + if (clist->count >= PJ_ICE_MAX_CHECKS) { pj_mutex_unlock(ice->mutex); return PJ_ETOOMANY; } @@ -1183,8 +1210,8 @@ pj_ice_sess_create_check_list(pj_ice_sess *ice, * and only if the two candidates have the same component ID * and have the same IP address version. */ - if (lcand->comp_id != rcand->comp_id || - lcand->addr.addr.sa_family != rcand->addr.addr.sa_family) + if ((lcand->comp_id != rcand->comp_id) || + (lcand->addr.addr.sa_family != rcand->addr.addr.sa_family)) { continue; } @@ -1204,7 +1231,11 @@ pj_ice_sess_create_check_list(pj_ice_sess *ice, sort_checklist(clist); /* Prune the checklist */ - prune_checklist(ice, clist); + status = prune_checklist(ice, clist); + if (status != PJ_SUCCESS) { + pj_mutex_unlock(ice->mutex); + return status; + } /* Init timer entry in the checklist. Initially the timer ID is FALSE * because timer is not running. @@ -1465,7 +1496,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_start_check(pj_ice_sess *ice) /* Pickup the first pair for component 1. */ for (i=0; icount; ++i) { - if (clist->checks[0].lcand->comp_id == 1) + if (clist->checks[i].lcand->comp_id == 1) break; } if (i == clist->count) { @@ -1886,6 +1917,18 @@ static pj_status_t on_stun_rx_request(pj_stun_session *sess, } } + /* Handle the case when request comes before answer is received. + * We need to put credential in the response, and since we haven't + * got the response, copy the username from the request. + */ + if (ice->rcand_cnt == 0) { + pj_stun_string_attr *uname_attr; + + uname_attr = (pj_stun_string_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USERNAME, 0); + pj_assert(uname_attr != NULL); + pj_strdup(ice->pool, &ice->rx_uname, &uname_attr->value); + } /* * First send response to this request @@ -2089,6 +2132,20 @@ static void handle_incoming_check(pj_ice_sess *ice, * Note this may end ICE process. */ pj_bool_t complete; + unsigned j; + + /* If this check is nominated, scan the valid_list for the + * same check and update the nominated flag. A controlled + * agent might have finished the check earlier. + */ + if (rcheck->use_candidate) { + for (j=0; jvalid_list.count; ++j) { + pj_ice_sess_check *vc = &ice->valid_list.checks[j]; + if (vc->lcand == c->lcand && vc->rcand == c->rcand) { + vc->nominated = PJ_TRUE; + } + } + } LOG5((ice->obj_name, "Triggered check for check %d not performed " "because it's completed", i)); @@ -2207,6 +2264,12 @@ PJ_DEF(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice, status = pj_stun_session_on_rx_pkt(comp->stun_sess, pkt, pkt_size, PJ_STUN_IS_DATAGRAM, NULL, src_addr, src_addr_len); + if (status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; + pj_strerror(status, errmsg, sizeof(errmsg)); + LOG4((ice->obj_name, "Error processing incoming message: %s", + errmsg)); + } } else { (*ice->cb.on_rx_data)(ice, comp_id, pkt, pkt_size, src_addr, src_addr_len); diff --git a/pjnath/src/pjnath/ice_strans.c b/pjnath/src/pjnath/ice_strans.c index 5f7d59b6..d3ba78f4 100644 --- a/pjnath/src/pjnath/ice_strans.c +++ b/pjnath/src/pjnath/ice_strans.c @@ -461,14 +461,15 @@ static void on_read_complete(pj_ioqueue_key_t *key, if (status == PJ_SUCCESS) { if (ice_st->ice==NULL || - pj_memcmp(comp->pkt+8, comp->ka_tsx_id, 12) == 0) + (comp->stun_sess && + pj_memcmp(comp->pkt+8, comp->ka_tsx_id, 12) == 0)) { status = pj_stun_session_on_rx_pkt(comp->stun_sess, comp->pkt, bytes_read, PJ_STUN_IS_DATAGRAM, NULL, &comp->src_addr, comp->src_addr_len); - } else { + } else if (ice_st->ice) { PJ_TODO(DISTINGUISH_BETWEEN_LOCAL_AND_RELAY); TRACE_PKT((comp->ice_st->obj_name, @@ -481,6 +482,8 @@ static void on_read_complete(pj_ioqueue_key_t *key, comp->pkt, bytes_read, &comp->src_addr, comp->src_addr_len); + } else { + /* This must have been a very late STUN reponse */ } } else { (*ice_st->cb.on_rx_data)(ice_st, comp->comp_id, diff --git a/pjnath/src/pjnath/stun_session.c b/pjnath/src/pjnath/stun_session.c index f2dab459..8d9f6852 100644 --- a/pjnath/src/pjnath/stun_session.c +++ b/pjnath/src/pjnath/stun_session.c @@ -811,7 +811,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; } -- cgit v1.2.3