Index: pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_srtp.c
===================================================================
--- pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_srtp.c	(revision 1712)
+++ pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_srtp.c	(revision 1713)
@@ -181,43 +181,41 @@
 
 
-pj_str_t srtp_transport_getliberrstr(int err)
-{
-    pj_str_t msg = {NULL, 0};
-
+const char* get_libsrtp_errstr(int err)
+{
 #if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0)
     static char *liberr[] = {
-	"nothing to report                       ", /* err_status_ok           = 0,   */
-	"unspecified failure                     ", /* err_status_fail         = 1,   */
-	"unsupported parameter                   ", /* err_status_bad_param    = 2,   */
-	"couldn't allocate memory                ", /* err_status_alloc_fail   = 3,   */
-	"couldn't deallocate properly            ", /* err_status_dealloc_fail = 4,   */
-	"couldn't initialize                     ", /* err_status_init_fail    = 5,   */
-	"can't process as much data as requested ", /* err_status_terminus     = 6,   */
-	"authentication failure                  ", /* err_status_auth_fail    = 7,   */
-	"cipher failure                          ", /* err_status_cipher_fail  = 8,   */
-	"replay check failed (bad index)         ", /* err_status_replay_fail  = 9,   */
-	"replay check failed (index too old)     ", /* err_status_replay_old   = 10,  */
-	"algorithm failed test routine           ", /* err_status_algo_fail    = 11,  */
-	"unsupported operation                   ", /* err_status_no_such_op   = 12,  */
-	"no appropriate context found            ", /* err_status_no_ctx       = 13,  */
-	"unable to perform desired validation    ", /* err_status_cant_check   = 14,  */
-	"can't use key any more                  ", /* err_status_key_expired  = 15,  */
-	"error in use of socket                  ", /* err_status_socket_err   = 16,  */
-	"error in use POSIX signals              ", /* err_status_signal_err   = 17,  */
-	"nonce check failed                      ", /* err_status_nonce_bad    = 18,  */
-	"couldn't read data                      ", /* err_status_read_fail    = 19,  */
-	"couldn't write data                     ", /* err_status_write_fail   = 20,  */
-	"error pasring data                      ", /* err_status_parse_err    = 21,  */
-	"error encoding data                     ", /* err_status_encode_err   = 22,  */
-	"error while using semaphores            ", /* err_status_semaphore_err = 23,  */
-	"error while using pfkey                 " /* err_status_pfkey_err    = 24,   */
+	"ok",				    /* err_status_ok            = 0  */
+	"unspecified failure",		    /* err_status_fail          = 1  */
+	"unsupported parameter",	    /* err_status_bad_param     = 2  */
+	"couldn't allocate memory",	    /* err_status_alloc_fail    = 3  */
+	"couldn't deallocate properly",	    /* err_status_dealloc_fail  = 4  */
+	"couldn't initialize",		    /* err_status_init_fail     = 5  */
+	"can't process as much data as requested", 
+					    /* err_status_terminus      = 6  */
+	"authentication failure",	    /* err_status_auth_fail     = 7  */
+	"cipher failure",		    /* err_status_cipher_fail   = 8  */
+	"replay check failed (bad index)",  /* err_status_replay_fail   = 9  */
+	"replay check failed (index too old)", 
+					    /* err_status_replay_old    = 10 */
+	"algorithm failed test routine",    /* err_status_algo_fail     = 11 */
+	"unsupported operation",	    /* err_status_no_such_op    = 12 */
+	"no appropriate context found",	    /* err_status_no_ctx        = 13 */
+	"unable to perform desired validation", 
+					    /* err_status_cant_check    = 14 */
+	"can't use key any more",	    /* err_status_key_expired   = 15 */
+	"error in use of socket",	    /* err_status_socket_err    = 16 */
+	"error in use POSIX signals",	    /* err_status_signal_err    = 17 */
+	"nonce check failed",		    /* err_status_nonce_bad     = 18 */
+	"couldn't read data",		    /* err_status_read_fail     = 19 */
+	"couldn't write data",		    /* err_status_write_fail    = 20 */
+	"error pasring data",		    /* err_status_parse_err     = 21 */
+	"error encoding data",		    /* err_status_encode_err    = 22 */
+	"error while using semaphores",	    /* err_status_semaphore_err = 23 */
+	"error while using pfkey"	    /* err_status_pfkey_err     = 24 */
     };
-    if (err >= 0 && err <= 24) {
-	msg.ptr = liberr[err];
-	msg.slen = 40;
-    }
+    return liberr[err];
+#else
+    return NULL;
 #endif
-
-    return msg;
 }
 
@@ -235,6 +233,4 @@
 
 	initialized = PJ_TRUE;
-
-	PJ_TODO(REGISTER_LIBSRTP_ERROR_CODES_AND_MESSAGES);
     }
     
@@ -247,4 +243,7 @@
     int cs_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);
     
+    if (crypto_name->slen == 0)
+	return 0;
+
     for (i=0; i<cs_cnt; ++i) {
 	if (!pj_stricmp2(crypto_name, crypto_suites[i].name))
@@ -284,4 +283,25 @@
     PJ_ASSERT_RETURN(endpt && p_tp, PJ_EINVAL);
 
+    /* Check crypto availability */
+    if (opt->crypto_count == 0 && 
+	opt->use == PJMEDIA_SRTP_MANDATORY)
+	return PJMEDIA_SRTP_ESDPREQCRYPTO;
+
+    /* Check crypto */
+    if (opt->use != PJMEDIA_SRTP_DISABLED) {
+	for (i=0; i < opt->crypto_count; ++i) {
+	    int cs_idx = get_crypto_idx(&opt->crypto[i].name);
+
+	    /* check crypto name */
+	    if (cs_idx == -1)
+		return PJMEDIA_SRTP_ENOTSUPCRYPTO;
+
+	    /* check key length */
+	    if (opt->crypto[i].key.slen && 
+		opt->crypto[i].key.slen < crypto_suites[cs_idx].cipher_key_len)
+		return PJMEDIA_SRTP_EINKEYLEN;
+	}
+    }
+
     /* Init libsrtp. */
     status = pjmedia_srtp_init_lib();
@@ -294,23 +314,24 @@
     srtp->pool = pool;
     srtp->session_inited = PJ_FALSE;
-    srtp->bypass_srtp = PJ_TRUE;
+    srtp->bypass_srtp = PJ_FALSE;
 
     if (opt) {
 	srtp->setting = *opt;
-	for (i=0; i < opt->crypto_count; ++i) {
+	if (opt->use == PJMEDIA_SRTP_DISABLED)
+	    srtp->setting.crypto_count = 0;
+
+	for (i=0; i < srtp->setting.crypto_count; ++i) {
 	    int cs_idx = get_crypto_idx(&opt->crypto[i].name);
-	    if (cs_idx == -1)
-		return PJMEDIA_SRTP_ENOTSUPCRYPTO;
-
+	    pj_str_t tmp_key = opt->crypto[i].key;
+
+	    /* re-set crypto */
 	    srtp->setting.crypto[i].name = pj_str(crypto_suites[cs_idx].name);
-	    pj_strdup(pool, &srtp->setting.crypto[i].key, &opt->crypto[i].key);
+	    /* cut key length */
+	    tmp_key.slen = crypto_suites[cs_idx].cipher_key_len;
+	    pj_strdup(pool, &srtp->setting.crypto[i].key, &tmp_key);
 	}
     } else {
 	pjmedia_srtp_setting_default(&srtp->setting);
     }
-
-    if (srtp->setting.crypto_count==0 && 
-	srtp->setting.use == PJMEDIA_SRTP_MANDATORY)
-	return PJMEDIA_SRTP_ESDPREQCRYPTO;
 
     status = pj_lock_create_null_mutex(pool, pool->obj_name, &srtp->mutex);
@@ -376,4 +397,9 @@
     if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 || au_rx_idx == -1)
 	return PJMEDIA_SRTP_ENOTSUPCRYPTO;
+
+    if (cr_tx_idx == 0 && cr_rx_idx == 0 && au_tx_idx == 0 && au_rx_idx == 0) {
+	srtp->bypass_srtp = PJ_TRUE;
+	return PJ_SUCCESS;
+    }
 
     /* Init transmit direction */
@@ -429,5 +455,4 @@
     /* Declare SRTP session initialized */
     srtp->session_inited = PJ_TRUE;
-    srtp->bypass_srtp = PJ_FALSE;
 
     PJ_LOG(5, (THIS_FILE, "TX: %s key=%s", srtp->tx_policy.name.ptr,
@@ -545,5 +570,5 @@
 
     if (srtp->bypass_srtp)
-	return pjmedia_transport_send_rtp(srtp->real_tp, srtp->tx_buffer, len);
+	return pjmedia_transport_send_rtp(srtp->real_tp, pkt, size);
 
     if (!srtp->session_inited)
@@ -578,5 +603,5 @@
 
     if (srtp->bypass_srtp)
-	return pjmedia_transport_send_rtp(srtp->real_tp, srtp->tx_buffer, len);
+	return pjmedia_transport_send_rtp(srtp->real_tp, pkt, size);
 
     if (!srtp->session_inited)
@@ -642,5 +667,5 @@
 
     if (srtp->bypass_srtp) {
-	srtp->rtp_cb(srtp->user_data, srtp->rx_buffer, len);
+	srtp->rtp_cb(srtp->user_data, pkt, size);
 	return;
     }
@@ -674,5 +699,5 @@
 
     if (srtp->bypass_srtp) {
-	srtp->rtcp_cb(srtp->user_data, srtp->rx_buffer, len);
+	srtp->rtcp_cb(srtp->user_data, pkt, size);
 	return;
     }
@@ -746,5 +771,5 @@
     }
 
-    if ((unsigned)crypto->key.slen != crypto_suites[cs_idx].cipher_key_len)
+    if (crypto->key.slen != (int)crypto_suites[cs_idx].cipher_key_len)
 	return PJMEDIA_SRTP_EINKEYLEN;
 
@@ -759,5 +784,5 @@
     b64_key[b64_key_len] = '\0';
     
-    PJ_ASSERT_RETURN((unsigned)*buffer_len >= (crypto->name.slen + \
+    PJ_ASSERT_RETURN(*buffer_len >= (crypto->name.slen + \
 		     b64_key_len + 16), PJ_ETOOSMALL);
 
@@ -959,4 +984,10 @@
 				   &srtp->setting.crypto[j].name) == 0)
 		    {
+			int cs_idx = get_crypto_idx(&tmp_rx_crypto.name);
+
+			if (tmp_rx_crypto.key.slen != 
+			    (int)crypto_suites[cs_idx].cipher_key_len)
+			    return PJMEDIA_SRTP_EINKEYLEN;
+
 			srtp->tx_policy = srtp->setting.crypto[j];
 			srtp->rx_policy = tmp_rx_crypto;
@@ -1036,6 +1067,9 @@
     /* bypass if media transport is not RTP/AVP or RTP/SAVP */
     if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP)  != 0 && 
-	pj_stricmp(&m_loc->desc.transport, &ID_RTP_SAVP) != 0)
+	pj_stricmp(&m_loc->desc.transport, &ID_RTP_SAVP) != 0) 
+    {
+	srtp->bypass_srtp = PJ_TRUE;
 	goto PROPAGATE_MEDIA_START;
+    }
 
     /* If the media is inactive, do nothing. */
@@ -1043,4 +1077,5 @@
 	(m_rem && pjmedia_sdp_media_find_attr(m_rem, &ID_INACTIVE, NULL)))
     {
+	srtp->bypass_srtp = PJ_TRUE;
 	goto PROPAGATE_MEDIA_START;
     }
@@ -1057,5 +1092,6 @@
 		return PJMEDIA_SRTP_ESDPINCRYPTO;
 	    }
-	    goto PROPAGATE_MEDIA_START;;
+	    srtp->bypass_srtp = PJ_TRUE;
+	    goto PROPAGATE_MEDIA_START;
 	} else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) {
 	    if (pj_stricmp(&m_rem->desc.transport, &m_loc->desc.transport)) {
@@ -1073,4 +1109,5 @@
     if (srtp->offerer_side) {
 	/* find supported crypto-suite, get the tag, and assign policy_local */
+	pjmedia_srtp_crypto tmp_tx_crypto;
 	pj_bool_t has_crypto_attr = PJ_FALSE;
 	int rem_tag;
@@ -1089,5 +1126,5 @@
 
 	    status = parse_attr_crypto(pool, m_rem->attr[i], 
-				       &srtp->rx_policy, &rem_tag);
+				       &tmp_tx_crypto, &rem_tag);
 	    if (status != PJ_SUCCESS)
 		return status;
@@ -1095,5 +1132,5 @@
 
 	    /* our offer tag is always ordered by setting */
-	    if (rem_tag<1 || rem_tag>srtp->setting.crypto_count) {
+	    if (rem_tag < 1 || rem_tag > srtp->setting.crypto_count) {
 		DEACTIVATE_MEDIA(pool, m_loc);
 		return PJMEDIA_SRTP_ESDPINCRYPTOTAG;
@@ -1109,12 +1146,16 @@
 
 	    srtp->tx_policy = srtp->setting.crypto[rem_tag-1];
+	    srtp->rx_policy = tmp_tx_crypto;
 	}
 
 	if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) {
 	    /* should never reach here */
+	    srtp->bypass_srtp = PJ_TRUE;
 	    goto PROPAGATE_MEDIA_START;
 	} else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) {
-	    if (!has_crypto_attr)
+	    if (!has_crypto_attr) {
+		srtp->bypass_srtp = PJ_TRUE;
 		goto PROPAGATE_MEDIA_START;
+	    }
 	} else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) {
 	    if (!has_crypto_attr) {
@@ -1145,8 +1186,10 @@
     pj_status_t status;
 
-    status = pjmedia_transport_srtp_stop(tp);
-    if (status != PJ_SUCCESS)
-	PJ_LOG(4, (THIS_FILE, "Failed deinit session."));
-
-    return pjmedia_transport_media_stop(srtp->real_tp);
-}
+    if (srtp->setting.close_member_tp) {
+	status = pjmedia_transport_media_stop(srtp->real_tp);
+	if (status != PJ_SUCCESS)
+	    PJ_LOG(4, (THIS_FILE, "Failed deinit session."));
+    }
+
+    return pjmedia_transport_srtp_stop(tp);
+}
