Index: pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_srtp.c
===================================================================
--- pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_srtp.c	(revision 1721)
+++ pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_srtp.c	(revision 1722)
@@ -42,4 +42,5 @@
 static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 };
 static const pj_str_t ID_INACTIVE = { "inactive", 8 };
+static const pj_str_t ID_CRYPTO   = { "crypto", 6 };
 
 typedef struct crypto_suite
@@ -243,4 +244,5 @@
     int cs_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);
     
+    /* treat unspecified crypto_name as crypto 'NULL' */
     if (crypto_name->slen == 0)
 	return 0;
@@ -301,5 +303,6 @@
 	    /* check key length */
 	    if (opt->crypto[i].key.slen && 
-		opt->crypto[i].key.slen < crypto_suites[cs_idx].cipher_key_len)
+		opt->crypto[i].key.slen < 
+		(pj_ssize_t)crypto_suites[cs_idx].cipher_key_len)
 		return PJMEDIA_SRTP_EINKEYLEN;
 	}
@@ -384,5 +387,5 @@
     crypto_suites_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);
 
-    /* Check whether the crypto-suite requested is supported */
+    /* Get encryption and authentication method */
     cr_tx_idx = au_tx_idx = get_crypto_idx(&tx->name);
     if (tx->flags && PJMEDIA_SRTP_NO_ENCRYPTION)
@@ -391,5 +394,4 @@
 	au_tx_idx = 0;
 
-    /* Check whether the crypto-suite requested is supported */
     cr_rx_idx = au_rx_idx = get_crypto_idx(&rx->name);
     if (rx->flags && PJMEDIA_SRTP_NO_ENCRYPTION)
@@ -398,7 +400,10 @@
 	au_rx_idx = 0;
 
-    if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 || au_rx_idx == -1)
+    /* Check whether the crypto-suite requested is supported */
+    if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 || 
+	au_rx_idx == -1)
 	return PJMEDIA_SRTP_ENOTSUPCRYPTO;
 
+    /* If all options points to 'NULL' method, just bypass SRTP */
     if (cr_tx_idx == 0 && cr_rx_idx == 0 && au_tx_idx == 0 && au_rx_idx == 0) {
 	srtp->bypass_srtp = PJ_TRUE;
@@ -406,11 +411,23 @@
     }
 
+    /* Check key length */
+    if (tx->key.slen != (pj_ssize_t)crypto_suites[cr_tx_idx].cipher_key_len ||
+        rx->key.slen != (pj_ssize_t)crypto_suites[cr_rx_idx].cipher_key_len)
+	return PJMEDIA_SRTP_EINKEYLEN;
+
     /* Init transmit direction */
     pj_bzero(&tx_, sizeof(srtp_policy_t));
     pj_memmove(srtp->tx_key, tx->key.ptr, tx->key.slen);
+    if (cr_tx_idx && au_tx_idx)
+	tx_.rtp.sec_serv    = sec_serv_conf_and_auth;
+    else if (cr_tx_idx)
+	tx_.rtp.sec_serv    = sec_serv_conf;
+    else if (au_tx_idx)
+	tx_.rtp.sec_serv    = sec_serv_auth;
+    else
+	tx_.rtp.sec_serv    = sec_serv_none;
     tx_.key		    = (uint8_t*)srtp->tx_key;
     tx_.ssrc.type	    = ssrc_any_outbound;
     tx_.ssrc.value	    = 0;
-    tx_.rtp.sec_serv	    = crypto_suites[cr_tx_idx].service;
     tx_.rtp.cipher_type	    = crypto_suites[cr_tx_idx].cipher_type;
     tx_.rtp.cipher_key_len  = crypto_suites[cr_tx_idx].cipher_key_len;
@@ -434,4 +451,12 @@
     pj_bzero(&rx_, sizeof(srtp_policy_t));
     pj_memmove(srtp->rx_key, rx->key.ptr, rx->key.slen);
+    if (cr_rx_idx && au_rx_idx)
+	rx_.rtp.sec_serv    = sec_serv_conf_and_auth;
+    else if (cr_rx_idx)
+	rx_.rtp.sec_serv    = sec_serv_conf;
+    else if (au_rx_idx)
+	rx_.rtp.sec_serv    = sec_serv_auth;
+    else
+	rx_.rtp.sec_serv    = sec_serv_none;
     rx_.key		    = (uint8_t*)srtp->rx_key;
     rx_.ssrc.type	    = ssrc_any_inbound;
@@ -774,5 +799,5 @@
     }
 
-    if (crypto->key.slen != (int)crypto_suites[cs_idx].cipher_key_len)
+    if (crypto->key.slen != (pj_ssize_t)crypto_suites[cs_idx].cipher_key_len)
 	return PJMEDIA_SRTP_EINKEYLEN;
 
@@ -817,5 +842,5 @@
     token = strtok(input.ptr, " ");
     if (!token) {
-	PJ_LOG(5,(THIS_FILE, "Expecting tag"));
+	PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting tag"));
 	return PJMEDIA_SDP_EINATTR;
     }
@@ -827,5 +852,5 @@
     token = strtok(NULL, " ");
     if (!token) {
-	PJ_LOG(5,(THIS_FILE, "Expecting crypto suite"));
+	PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting crypto suite"));
 	return PJMEDIA_SDP_EINATTR;
     }
@@ -835,9 +860,10 @@
     token = strtok(NULL, ":");
     if (!token) {
-	PJ_LOG(5,(THIS_FILE, "Expecting key method"));
+	PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key method"));
 	return PJMEDIA_SDP_EINATTR;
     }
     if (pj_ansi_stricmp(token, "inline")) {
-	PJ_LOG(5,(THIS_FILE, "Key method %s not supported!", token));
+	PJ_LOG(4,(THIS_FILE, "Attribute crypto key method '%s' not supported!",
+	          token));
 	return PJMEDIA_SDP_EINATTR;
     }
@@ -846,5 +872,5 @@
     token = strtok(NULL, "| ");
     if (!token) {
-	PJ_LOG(5,(THIS_FILE, "Expecting key"));
+	PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key"));
 	return PJMEDIA_SDP_EINATTR;
     }
@@ -857,5 +883,5 @@
 			      &itmp);
     if (status != PJ_SUCCESS) {
-	PJ_LOG(5,(THIS_FILE, "Failed decoding key from base64"));
+	PJ_LOG(4,(THIS_FILE, "Failed decoding crypto key from base64"));
 	return status;
     }
@@ -927,4 +953,5 @@
 		return PJMEDIA_SRTP_ESDPINTRANSPORT;
 	    }
+	    m_loc->desc.transport = ID_RTP_SAVP;
 	}
     }
@@ -944,5 +971,6 @@
 	    if (buffer_len) {
 		pj_strset(&attr_value, buffer, buffer_len);
-		attr = pjmedia_sdp_attr_create(pool, "crypto", &attr_value);
+		attr = pjmedia_sdp_attr_create(pool, ID_CRYPTO.ptr, 
+					       &attr_value);
 		m_loc->attr[m_loc->attr_count++] = attr;
 	    }
@@ -954,13 +982,14 @@
 	pj_bool_t has_match = PJ_FALSE;
 	int chosen_tag = 0;
-	int tags[8];
-	int cr_count = 0;
+	int tags[64]; /* assume no more than 64 crypto attrs in a media */
+	int cr_attr_count = 0;
 	int k;
 
 	for (i=0; i<m_rem->attr_count; ++i) {
-	    if (pj_stricmp2(&m_rem->attr[i]->name, "crypto") != 0)
+	    if (pj_stricmp(&m_rem->attr[i]->name, &ID_CRYPTO) != 0)
 		continue;
 
 	    /* SRTP is disabled but there is crypto attr in remote media */
+	    /* Put the checking here to save a bit memory for parsing */
 	    if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) {
 		DEACTIVATE_MEDIA(pool, m_loc);
@@ -971,11 +1000,11 @@
 
 	    status = parse_attr_crypto(pool, m_rem->attr[i], 
-				       &tmp_rx_crypto, &tags[cr_count]);
+				       &tmp_rx_crypto, &tags[cr_attr_count]);
 	    if (status != PJ_SUCCESS)
 		return status;
 	 
 	    /* Check duplicated tag */
-	    for (k=0; k<cr_count; ++k) {
-		if (tags[k] == tags[cr_count]) {
+	    for (k=0; k<cr_attr_count; ++k) {
+		if (tags[k] == tags[cr_attr_count]) {
 		    DEACTIVATE_MEDIA(pool, m_loc);
 		    return PJMEDIA_SRTP_ESDPDUPCRYPTOTAG;
@@ -997,10 +1026,10 @@
 			srtp->tx_policy = srtp->setting.crypto[j];
 			srtp->rx_policy = tmp_rx_crypto;
-			chosen_tag = tags[cr_count];
+			chosen_tag = tags[cr_attr_count];
 			has_match = PJ_TRUE;
     			break;
 		    }
 	    }
-	    cr_count++;
+	    cr_attr_count++;
 	}
 
@@ -1018,11 +1047,14 @@
 		goto BYPASS_SRTP;
 	} else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) {
-	    if (!has_crypto_attr) {
-		DEACTIVATE_MEDIA(pool, m_loc);
-		return PJMEDIA_SRTP_ESDPREQCRYPTO;
-	    }
-	}
-
-	/* No crypto match? */
+	    /* do nothing, this is intended */
+	}
+
+	/* No crypto attr */
+	if (!has_crypto_attr) {
+	    DEACTIVATE_MEDIA(pool, m_loc);
+	    return PJMEDIA_SRTP_ESDPREQCRYPTO;
+	}
+
+	/* No crypto match */
 	if (!has_match) {
 	    DEACTIVATE_MEDIA(pool, m_loc);
@@ -1044,5 +1076,5 @@
 	if (buffer_len) {
 	    pj_strset(&attr_value, buffer, buffer_len);
-	    attr = pjmedia_sdp_attr_create(pool, "crypto", &attr_value);
+	    attr = pjmedia_sdp_attr_create(pool, ID_CRYPTO.ptr, &attr_value);
 	    m_loc->attr[m_loc->attr_count++] = attr;
 	}
@@ -1091,5 +1123,5 @@
     if (srtp->offerer_side) {
 	if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) {
-	    if (pjmedia_sdp_media_find_attr2(m_rem, "crypto", NULL)) {
+	    if (pjmedia_sdp_media_find_attr(m_rem, &ID_CRYPTO, NULL)) {
 		DEACTIVATE_MEDIA(pool, m_loc);
 		return PJMEDIA_SRTP_ESDPINCRYPTO;
@@ -1116,5 +1148,5 @@
 
 	for (i=0; i<m_rem->attr_count; ++i) {
-	    if (pj_stricmp2(&m_rem->attr[i]->name, "crypto") != 0)
+	    if (pj_stricmp(&m_rem->attr[i]->name, &ID_CRYPTO) != 0)
 		continue;
 
