summaryrefslogtreecommitdiff
path: root/pjnath/src/pjnath/ice_session.c
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-04-03 19:15:10 +0000
committerBenny Prijono <bennylp@teluu.com>2007-04-03 19:15:10 +0000
commit10c62612cd3b742a3cf78be53214a2906b687921 (patch)
tree919467f99844794b456eeafa029b3d24a2879e62 /pjnath/src/pjnath/ice_session.c
parent89c220218ff5245488bf78514c79dfaf86b13743 (diff)
Added ICE-CONTROLLED and ICE-CONTROLLING attribute, handle ICE 487 error, and add response source address checking
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1141 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjnath/src/pjnath/ice_session.c')
-rw-r--r--pjnath/src/pjnath/ice_session.c95
1 files changed, 85 insertions, 10 deletions
diff --git a/pjnath/src/pjnath/ice_session.c b/pjnath/src/pjnath/ice_session.c
index f3b9ce87..4cae89af 100644
--- a/pjnath/src/pjnath/ice_session.c
+++ b/pjnath/src/pjnath/ice_session.c
@@ -115,7 +115,9 @@ static pj_status_t on_stun_rx_request(pj_stun_session *sess,
static void on_stun_request_complete(pj_stun_session *stun_sess,
pj_status_t status,
pj_stun_tx_data *tdata,
- const pj_stun_msg *response);
+ const pj_stun_msg *response,
+ const pj_sockaddr_t *src_addr,
+ unsigned src_addr_len);
static pj_status_t on_stun_rx_indication(pj_stun_session *sess,
const pj_uint8_t *pkt,
unsigned pkt_len,
@@ -1206,13 +1208,25 @@ static pj_status_t perform_check(pj_ice_sess *ice,
pj_stun_msg_add_uint_attr(check->tdata->pool, check->tdata->msg,
PJ_STUN_ATTR_PRIORITY, prio);
- /* Add USE-CANDIDATE and set this check to nominated */
+ /* Add USE-CANDIDATE and set this check to nominated.
+ * Also add ICE-CONTROLLING or ICE-CONTROLLED
+ */
if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLING) {
pj_stun_msg_add_empty_attr(check->tdata->pool, check->tdata->msg,
PJ_STUN_ATTR_USE_CANDIDATE);
check->nominated = PJ_TRUE;
+
+ pj_stun_msg_add_uint64_attr(check->tdata->pool, check->tdata->msg,
+ PJ_STUN_ATTR_ICE_CONTROLLING,
+ &ice->tie_breaker);
+
+ } else {
+ pj_stun_msg_add_uint64_attr(check->tdata->pool, check->tdata->msg,
+ PJ_STUN_ATTR_ICE_CONTROLLED,
+ &ice->tie_breaker);
}
+
/* Note that USERNAME and MESSAGE-INTEGRITY will be added by the
* STUN session.
*/
@@ -1428,7 +1442,9 @@ static pj_status_t on_stun_send_msg(pj_stun_session *sess,
static void on_stun_request_complete(pj_stun_session *stun_sess,
pj_status_t status,
pj_stun_tx_data *tdata,
- const pj_stun_msg *response)
+ const pj_stun_msg *response,
+ const pj_sockaddr_t *src_addr,
+ unsigned src_addr_len)
{
struct req_data *rd = (struct req_data*) tdata->user_data;
pj_ice_sess *ice;
@@ -1440,6 +1456,7 @@ static void on_stun_request_complete(pj_stun_session *stun_sess,
unsigned i;
PJ_UNUSED_ARG(stun_sess);
+ PJ_UNUSED_ARG(src_addr_len);
ice = rd->ice;
check = &rd->clist->checks[rd->ckid];
@@ -1456,26 +1473,84 @@ static void on_stun_request_complete(pj_stun_session *stun_sess,
*/
lcand = NULL;
- LOG4((ice->obj_name,
- "Check %s%s: connectivity check %s",
- dump_check(buffer, sizeof(buffer), &ice->clist, check),
- (check->nominated ? " (nominated)" : " (not nominated)"),
- (status==PJ_SUCCESS ? "SUCCESS" : "FAILED")));
-
if (status != PJ_SUCCESS) {
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ if (status==PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_ROLE_CONFLICT)) {
+ /* Role conclict response.
+ * 7.1.2.1. Failure Cases:
+ * If the request had contained the ICE-CONTROLLED attribute,
+ * the agent MUST switch to the controlling role if it has not
+ * already done so. If the request had contained the
+ * ICE-CONTROLLING attribute, the agent MUST switch to the
+ * controlled role if it has not already done so. Once it has
+ * switched, the agent MUST immediately retry the request with
+ * the ICE-CONTROLLING or ICE-CONTROLLED attribute reflecting
+ * its new role.
+ */
+ pj_ice_sess_role new_role = PJ_ICE_SESS_ROLE_UNKNOWN;
+ pj_stun_msg *req = tdata->msg;
+
+ if (pj_stun_msg_find_attr(req, PJ_STUN_ATTR_ICE_CONTROLLING, 0)) {
+ new_role = PJ_ICE_SESS_ROLE_CONTROLLED;
+ } else if (pj_stun_msg_find_attr(req, PJ_STUN_ATTR_ICE_CONTROLLED,
+ 0)) {
+ new_role = PJ_ICE_SESS_ROLE_CONTROLLING;
+ } else {
+ pj_assert(!"We should have put CONTROLLING/CONTROLLED attr!");
+ new_role = PJ_ICE_SESS_ROLE_CONTROLLED;
+ }
+
+ if (new_role != ice->role) {
+ LOG4((ice->obj_name,
+ "Changing role because of role conflict"));
+ pj_ice_sess_change_role(ice, new_role);
+ }
+
+ /* Resend request */
+ LOG4((ice->obj_name, "Resending check because of role conflict"));
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_WAITING, 0);
+ perform_check(ice, clist, rd->ckid);
+ pj_mutex_unlock(ice->mutex);
+ return;
+ }
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ LOG4((ice->obj_name,
+ "Check %s%s: connectivity check FAILED: %s",
+ dump_check(buffer, sizeof(buffer), &ice->clist, check),
+ (check->nominated ? " (nominated)" : " (not nominated)"),
+ errmsg));
+
check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, status);
on_check_complete(ice, check);
pj_mutex_unlock(ice->mutex);
return;
}
+
/* The agent MUST check that the source IP address and port of the
* response equals the destination IP address and port that the Binding
* Request was sent to, and that the destination IP address and port of
* the response match the source IP address and port that the Binding
* Request was sent from.
*/
- PJ_TODO(ICE_CHECK_RESPONSE_SOURCE_ADDRESS);
+ if (sockaddr_cmp(&check->rcand->addr, src_addr) != 0) {
+ status = PJNATH_EICEINSRCADDR;
+ LOG4((ice->obj_name,
+ "Check %s%s: connectivity check FAILED: source address mismatch",
+ dump_check(buffer, sizeof(buffer), &ice->clist, check),
+ (check->nominated ? " (nominated)" : " (not nominated)")));
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, status);
+ on_check_complete(ice, check);
+ pj_mutex_unlock(ice->mutex);
+ return;
+ }
+
+ LOG4((ice->obj_name,
+ "Check %s%s: connectivity check SUCCESS",
+ dump_check(buffer, sizeof(buffer), &ice->clist, check),
+ (check->nominated ? " (nominated)" : " (not nominated)")));
/* Get the STUN XOR-MAPPED-ADDRESS attribute. */
xaddr = (pj_stun_xor_mapped_addr_attr*)