cleanup debug and memory and add stupid code for using sep dtls session when rtcp is not mux

This commit is contained in:
Anthony Minessale 2013-02-02 23:57:27 -06:00
parent eae2e6aeca
commit 16fa338b49
5 changed files with 288 additions and 185 deletions

View File

@ -53,6 +53,8 @@ SWITCH_BEGIN_EXTERN_C
typedef enum {
SWITCH_RTP_CRYPTO_SEND,
SWITCH_RTP_CRYPTO_RECV,
SWITCH_RTP_CRYPTO_SEND_RTCP,
SWITCH_RTP_CRYPTO_RECV_RTCP,
SWITCH_RTP_CRYPTO_MAX
} switch_rtp_crypto_direction_t;
@ -99,7 +101,7 @@ typedef struct ice_s {
icand_t cands[MAX_CAND][2];
int cand_idx;
int chosen;
int chosen[2];
char *ufrag;
char *pwd;
char *options;

View File

@ -1706,8 +1706,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
abort();
}
printf("SOFIA nh[%p] pvt[%p] call_id %s key %s\n", (void*) nh, (void *) sofia_private, call_id, key);
memset(sofia_private, 0, sizeof(*sofia_private));
sofia_private->call_id = su_strdup(nh->nh_home, call_id);
sofia_private->network_ip = su_strdup(nh->nh_home, network_ip);

View File

@ -133,6 +133,10 @@ SWITCH_DECLARE(int) switch_core_cert_gen_fingerprint(const char *prefix, dtls_fi
BIO_free_all(bio);
}
if (x509) {
X509_free(x509);
}
free(rsa);
return ret;

View File

@ -140,6 +140,13 @@ typedef struct switch_rtp_engine_s {
dtls_fingerprint_t local_dtls_fingerprint;
dtls_fingerprint_t remote_dtls_fingerprint;
char *remote_rtp_ice_addr;
switch_port_t remote_rtp_ice_port;
char *remote_rtcp_ice_addr;
switch_port_t remote_rtcp_ice_port;
} switch_rtp_engine_t;
@ -1793,15 +1800,11 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
switch_rtp_engine_t *engine = &smh->engines[type];
sdp_attribute_t *attr;
int i = 0, got_rtcp_mux = 0;
char tmp[80] = "";
engine->ice_in.chosen = 0;
engine->ice_in.chosen[0] = 0;
engine->ice_in.chosen[1] = 0;
engine->ice_in.cand_idx = 0;
for (attr = m->m_attributes; attr; attr = attr->a_next) {
}
for (attr = m->m_attributes; attr; attr = attr->a_next) {
char *data;
@ -1842,8 +1845,8 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
#ifdef RTCP_MUX
} else if (!strcasecmp(attr->a_name, "rtcp-mux")) {
engine->remote_rtcp_port = engine->codec_params.remote_sdp_port;
engine->rtcp_mux = SWITCH_TRUE;
engine->remote_rtcp_port = engine->codec_params.remote_sdp_port;
got_rtcp_mux++;
#endif
} else if (!strcasecmp(attr->a_name, "candidate")) {
@ -1876,23 +1879,23 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG,
"Checking Candidate cid: %d proto: %s type: %s addr: %s\n", cid+1, fields[2], fields[7], fields[4]);
"Checking Candidate cid: %d proto: %s type: %s addr: %s:%s\n", cid+1, fields[2], fields[7], fields[4], fields[5]);
engine->ice_in.cand_idx++;
for (i = 0; i < engine->cand_acl_count; i++) {
if (!engine->ice_in.chosen && switch_check_network_list_ip(fields[4], engine->cand_acl[i])) {
engine->ice_in.chosen = engine->ice_in.cand_idx;
if (!engine->ice_in.chosen[cid] && switch_check_network_list_ip(fields[4], engine->cand_acl[i])) {
engine->ice_in.chosen[cid] = engine->ice_in.cand_idx;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"Choose %s Candidate cid: %d proto: %s type: %s addr: %s\n",
"Choose %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n",
type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
cid+1, fields[2], fields[7], fields[4]);
cid+1, fields[2], fields[7], fields[4], fields[5]);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"Save %s Candidate cid: %d proto: %s type: %s addr: %s\n",
"Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n",
type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
cid+1, fields[2], fields[7], fields[4]);
cid+1, fields[2], fields[7], fields[4], fields[5]);
}
engine->ice_in.cands[engine->ice_in.cand_idx][cid].foundation = switch_core_session_strdup(smh->session, fields[0]);
@ -1918,8 +1921,8 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
j += 2;
}
if (engine->ice_in.chosen) {
engine->ice_in.cands[engine->ice_in.chosen][cid].ready++;
if (engine->ice_in.chosen[cid]) {
engine->ice_in.cands[engine->ice_in.chosen[cid]][cid].ready++;
}
break;
@ -1929,31 +1932,41 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
}
for (i = 0; i < 2; i++) {
if (engine->ice_in.cands[engine->ice_in.chosen][i].ready) {
if (engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready) {
if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) {
engine->ice_in.cands[engine->ice_in.chosen][i].ready = 0;
engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready = 0;
}
}
}
if (engine->ice_in.cands[engine->ice_in.chosen][0].con_addr && engine->ice_in.cands[engine->ice_in.chosen][0].con_port) {
engine->codec_params.remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen][0].con_addr);
engine->codec_params.remote_sdp_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen][0].con_port;
if (engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr && engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port) {
char tmp[80] = "";
engine->codec_params.remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"setting remote %s addr to %s:%d based on candidate\n", type2str(type),
engine->ice_in.cands[engine->ice_in.chosen][0].con_addr, engine->ice_in.cands[engine->ice_in.chosen][0].con_port);
"setting remote %s ice addr to %s:%d based on candidate\n", type2str(type),
engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port);
engine->remote_rtp_ice_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
engine->remote_rtp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
engine->codec_params.remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
engine->codec_params.remote_sdp_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
switch_snprintf(tmp, sizeof(tmp), "%d", engine->codec_params.remote_sdp_port);
switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, engine->codec_params.remote_sdp_ip);
switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
}
if (engine->ice_in.cands[engine->ice_in.chosen][1].con_port) {
if (engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"setting remote rtcp %s addr to %s:%d based on candidate\n", type2str(type),
engine->ice_in.cands[engine->ice_in.chosen][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen][1].con_port);
engine->remote_rtcp_port = engine->ice_in.cands[engine->ice_in.chosen][1].con_port;
engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port);
engine->remote_rtcp_ice_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port;
engine->remote_rtcp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr);
engine->remote_rtcp_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port;
}
@ -3706,16 +3719,22 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
if (!zstr(a_engine->local_dtls_fingerprint.str)) {
dtls_type_t dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
dtls_type_t xtype, dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
dtype |= DTLS_TYPE_RTP;
if (a_engine->rtcp_mux > 0) dtype |= DTLS_TYPE_RTCP;
xtype = DTLS_TYPE_RTP;
if (a_engine->rtcp_mux > 0) xtype |= DTLS_TYPE_RTCP;
switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype);
switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype);
if (a_engine->rtcp_mux < 1) {
xtype = DTLS_TYPE_RTCP;
switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype);
}
}
if (a_engine->ice_in.cands[a_engine->ice_in.chosen][0].ready) {
if (a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].ready) {
gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
@ -3766,7 +3785,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
}
if (a_engine->ice_in.cands[a_engine->ice_in.chosen][1].ready && a_engine->rtcp_mux < 1) {
if (a_engine->ice_in.cands[a_engine->ice_in.chosen[1]][1].ready) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP ICE\n");
switch_rtp_activate_ice(a_engine->rtp_session,
@ -4096,16 +4115,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
switch_rtp_set_ssrc(v_engine->rtp_session, v_engine->ssrc);
}
if (!zstr(v_engine->local_dtls_fingerprint.str)) {
dtls_type_t dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
dtype |= DTLS_TYPE_RTP;
if (v_engine->rtcp_mux > 0) dtype |= DTLS_TYPE_RTCP;
switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype);
}
if (v_engine->ice_in.cands[v_engine->ice_in.chosen][0].ready) {
if (v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready) {
gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
@ -4150,7 +4161,24 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
}
if (v_engine->ice_in.cands[v_engine->ice_in.chosen][1].ready && v_engine->rtcp_mux < 1) {
if (!zstr(v_engine->local_dtls_fingerprint.str)) {
dtls_type_t xtype,
dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
printf("FUCK FP XXXXX %d\n", v_engine->rtcp_mux);
xtype = DTLS_TYPE_RTP;
if (v_engine->rtcp_mux > 0) xtype |= DTLS_TYPE_RTCP;
switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype);
if (v_engine->rtcp_mux < 1) {
xtype = DTLS_TYPE_RTCP;
printf("FUCKER\n");
switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype);
}
}
if (v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].ready) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP ICE\n");
switch_rtp_activate_ice(v_engine->rtp_session,
v_engine->ice_in.ufrag,

View File

@ -240,12 +240,18 @@ struct switch_rtp {
uint32_t autoadj_window;
uint32_t autoadj_tally;
srtp_ctx_t *send_ctx;
srtp_ctx_t *recv_ctx;
srtp_policy_t send_policy;
srtp_policy_t recv_policy;
uint32_t srtp_errs;
uint32_t srctp_errs;
srtp_ctx_t *send_ctx[2];
srtp_ctx_t *recv_ctx[2];
srtp_policy_t send_policy[2];
srtp_policy_t recv_policy[2];
uint32_t srtp_errs[2];
uint32_t srctp_errs[2];
int srtp_idx_rtp;
int srtp_idx_rtcp;
switch_dtls_t *dtls;
switch_dtls_t *rtcp_dtls;
@ -720,7 +726,7 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
if ((ice->type & ICE_VANILLA)) {
char sw[128] = "";
switch_stun_packet_attribute_add_priority(packet, ice->ice_params->cands[ice->ice_params->chosen][ice->proto].priority);
switch_stun_packet_attribute_add_priority(packet, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].priority);
switch_snprintf(sw, sizeof(sw), "FreeSWITCH (%s)", SWITCH_VERSION_REVISION_HUMAN);
switch_stun_packet_attribute_add_software(packet, sw, strlen(sw));
@ -792,7 +798,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
memcpy(buf, data, cpylen);
packet = switch_stun_packet_parse(buf, cpylen);
if (!packet) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Invalid STUN/ICE packet received\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Invalid STUN/ICE packet received %ld %d\n", cpylen, *(uint8_t *) data);
goto end;
}
@ -829,7 +835,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
case SWITCH_STUN_ATTR_PRIORITY:
{
pri = (uint32_t *) attr->value;
ok = *pri == ice->ice_params->cands[ice->ice_params->chosen][ice->proto].priority;
ok = *pri == ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].priority;
}
break;
}
@ -846,7 +852,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
if (ice->type == ICE_VANILLA) {
if (!ok && ice == &rtp_session->ice && pri &&
*pri == rtp_session->rtcp_ice.ice_params->cands[rtp_session->rtcp_ice.ice_params->chosen][1].priority) {
*pri == rtp_session->rtcp_ice.ice_params->cands[rtp_session->rtcp_ice.ice_params->chosen[1]][1].priority) {
ice = &rtp_session->rtcp_ice;
ok = 1;
}
@ -874,7 +880,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
for (i = 0; i < icep[j]->ice_params->cand_idx; i++) {
if (icep[j]->ice_params->cands[i][icep[j]->proto].priority == *pri) {
if (j == IPR_RTP) {
icep[j]->ice_params->chosen = i;
icep[j]->ice_params->chosen[j] = i;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Change candidate index to %d\n", i);
}
@ -1320,7 +1326,7 @@ static int check_srtp_and_ice(switch_rtp_t *rtp_session)
#ifdef ENABLE_SRTP
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND]) {
int sbytes = (int) rtcp_bytes;
int stat = srtp_protect_rtcp(rtp_session->send_ctx, &rtp_session->rtcp_send_msg.header, &sbytes);
int stat = srtp_protect_rtcp(rtp_session->send_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_send_msg.header, &sbytes);
if (stat) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP RTCP protection failed with code %d\n", stat);
@ -1999,8 +2005,13 @@ static int dtls_state_setup(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
memcpy(remote_key_buf, remote_key, cr_keylen);
memcpy(remote_key_buf + cr_keylen, remote_salt, cr_saltlen);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_SEND, 0, AES_CM_128_HMAC_SHA1_80, local_key_buf, cr_kslen);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_RECV, 0, AES_CM_128_HMAC_SHA1_80, remote_key_buf, cr_kslen);
if (dtls == rtp_session->rtcp_dtls && rtp_session->rtcp_dtls != rtp_session->dtls) {
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_SEND_RTCP, 0, AES_CM_128_HMAC_SHA1_80, local_key_buf, cr_kslen);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_RECV_RTCP, 0, AES_CM_128_HMAC_SHA1_80, remote_key_buf, cr_kslen);
} else {
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_SEND, 0, AES_CM_128_HMAC_SHA1_80, local_key_buf, cr_kslen);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_RECV, 0, AES_CM_128_HMAC_SHA1_80, remote_key_buf, cr_kslen);
}
}
dtls_set_state(dtls, DS_READY);
@ -2050,6 +2061,10 @@ static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
dtls_set_state(dtls, DS_FAIL);
return -1;
}
if (dtls->state == DS_READY) {
dtls_set_state(dtls, DS_HANDSHAKE);
}
}
if (SSL_read(dtls->ssl, dtls->data, dtls->bytes) == dtls->bytes) {
@ -2117,102 +2132,105 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO,
"Activate %s DTLS %s\n", rtp_type(rtp_session), (type & DTLS_TYPE_SERVER) ? "server" : "cleint");
if (!(dtls = rtp_session->dtls)) {
dtls = switch_core_alloc(rtp_session->pool, sizeof(*dtls));
dtls->pvt = switch_core_sprintf(rtp_session->pool, "%s%s%s.key", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME);
dtls->rsa = switch_core_sprintf(rtp_session->pool, "%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME);
//dtls->ca = switch_core_sprintf(rtp_session->pool, "%s%sca-bundle.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR);
dtls->ssl_ctx = SSL_CTX_new(DTLSv1_method());
switch_assert(dtls->ssl_ctx);
SSL_CTX_set_mode(dtls->ssl_ctx, SSL_MODE_AUTO_RETRY);
//SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_NONE, NULL);
SSL_CTX_set_cipher_list(dtls->ssl_ctx, "ALL");
//SSL_CTX_set_tlsext_use_srtp(dtls->ssl_ctx, "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32");
SSL_CTX_set_tlsext_use_srtp(dtls->ssl_ctx, "SRTP_AES128_CM_SHA1_80");
dtls->type = type;
dtls->read_bio = BIO_new(BIO_s_mem());
switch_assert(dtls->read_bio);
dtls->write_bio = BIO_new(BIO_s_mem());
switch_assert(dtls->write_bio);
BIO_set_mem_eof_return(dtls->read_bio, -1);
BIO_set_mem_eof_return(dtls->write_bio, -1);
if ((ret=SSL_CTX_use_certificate_file(dtls->ssl_ctx, dtls->rsa, SSL_FILETYPE_PEM)) != 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS cert err [%d]\n", rtp_type(rtp_session), SSL_get_error(dtls->ssl, ret));
return SWITCH_STATUS_FALSE;
}
if ((ret=SSL_CTX_use_PrivateKey_file(dtls->ssl_ctx, dtls->pvt, SSL_FILETYPE_PEM)) != 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS key err [%d]\n", rtp_type(rtp_session), SSL_get_error(dtls->ssl, ret));
return SWITCH_STATUS_FALSE;
}
if (SSL_CTX_check_private_key(dtls->ssl_ctx) == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS check key failed\n", rtp_type(rtp_session));
return SWITCH_STATUS_FALSE;
}
if (!zstr(dtls->ca) && (ret=SSL_CTX_load_verify_locations(dtls->ssl_ctx, dtls->ca, NULL)) != 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS check chain cert failed [%d]\n",
rtp_type(rtp_session) ,
SSL_get_error(dtls->ssl, ret));
return SWITCH_STATUS_FALSE;
}
dtls->ssl = SSL_new(dtls->ssl_ctx);
SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->write_bio);
SSL_set_mode(dtls->ssl, SSL_MODE_AUTO_RETRY);
SSL_set_read_ahead(dtls->ssl, 1);
//SSL_set_verify(dtls->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), cb_verify_peer);
SSL_set_verify(dtls->ssl, SSL_VERIFY_NONE, NULL);
SSL_set_app_data(dtls->ssl, dtls);
dtls->local_fp = local_fp;
dtls->remote_fp = remote_fp;
dtls->rtp_session = rtp_session;
switch_core_cert_expand_fingerprint(remote_fp, remote_fp->str);
if ((type & DTLS_TYPE_RTP)) {
rtp_session->dtls = dtls;
dtls->sock_output = rtp_session->sock_output;
dtls->remote_addr = rtp_session->remote_addr;
}
if ((type & DTLS_TYPE_RTCP)) {
rtp_session->rtcp_dtls = dtls;
if (!(type & DTLS_TYPE_RTP)) {
dtls->sock_output = rtp_session->rtcp_sock_output;
dtls->remote_addr = rtp_session->rtcp_remote_addr;
}
}
if ((type & DTLS_TYPE_SERVER)) {
SSL_set_accept_state(dtls->ssl);
} else {
SSL_set_connect_state(dtls->ssl);
}
return SWITCH_STATUS_SUCCESS;
if (((type & DTLS_TYPE_RTP) && rtp_session->dtls) || ((type & DTLS_TYPE_RTCP) && rtp_session->rtcp_dtls)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "DTLS ALREADY INIT\n");
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_FALSE;
dtls = switch_core_alloc(rtp_session->pool, sizeof(*dtls));
dtls->pvt = switch_core_sprintf(rtp_session->pool, "%s%s%s.key", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME);
dtls->rsa = switch_core_sprintf(rtp_session->pool, "%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME);
//dtls->ca = switch_core_sprintf(rtp_session->pool, "%s%sca-bundle.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR);
dtls->ssl_ctx = SSL_CTX_new(DTLSv1_method());
switch_assert(dtls->ssl_ctx);
SSL_CTX_set_mode(dtls->ssl_ctx, SSL_MODE_AUTO_RETRY);
//SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_NONE, NULL);
SSL_CTX_set_cipher_list(dtls->ssl_ctx, "ALL");
//SSL_CTX_set_tlsext_use_srtp(dtls->ssl_ctx, "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32");
SSL_CTX_set_tlsext_use_srtp(dtls->ssl_ctx, "SRTP_AES128_CM_SHA1_80");
dtls->type = type;
dtls->read_bio = BIO_new(BIO_s_mem());
switch_assert(dtls->read_bio);
dtls->write_bio = BIO_new(BIO_s_mem());
switch_assert(dtls->write_bio);
BIO_set_mem_eof_return(dtls->read_bio, -1);
BIO_set_mem_eof_return(dtls->write_bio, -1);
if ((ret=SSL_CTX_use_certificate_file(dtls->ssl_ctx, dtls->rsa, SSL_FILETYPE_PEM)) != 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS cert err [%d]\n", rtp_type(rtp_session), SSL_get_error(dtls->ssl, ret));
return SWITCH_STATUS_FALSE;
}
if ((ret=SSL_CTX_use_PrivateKey_file(dtls->ssl_ctx, dtls->pvt, SSL_FILETYPE_PEM)) != 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS key err [%d]\n", rtp_type(rtp_session), SSL_get_error(dtls->ssl, ret));
return SWITCH_STATUS_FALSE;
}
if (SSL_CTX_check_private_key(dtls->ssl_ctx) == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS check key failed\n", rtp_type(rtp_session));
return SWITCH_STATUS_FALSE;
}
if (!zstr(dtls->ca) && (ret=SSL_CTX_load_verify_locations(dtls->ssl_ctx, dtls->ca, NULL)) != 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS check chain cert failed [%d]\n",
rtp_type(rtp_session) ,
SSL_get_error(dtls->ssl, ret));
return SWITCH_STATUS_FALSE;
}
dtls->ssl = SSL_new(dtls->ssl_ctx);
SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->write_bio);
SSL_set_mode(dtls->ssl, SSL_MODE_AUTO_RETRY);
SSL_set_read_ahead(dtls->ssl, 1);
//SSL_set_verify(dtls->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), cb_verify_peer);
SSL_set_verify(dtls->ssl, SSL_VERIFY_NONE, NULL);
SSL_set_app_data(dtls->ssl, dtls);
dtls->local_fp = local_fp;
dtls->remote_fp = remote_fp;
dtls->rtp_session = rtp_session;
switch_core_cert_expand_fingerprint(remote_fp, remote_fp->str);
if ((type & DTLS_TYPE_RTP)) {
rtp_session->dtls = dtls;
dtls->sock_output = rtp_session->sock_output;
dtls->remote_addr = rtp_session->remote_addr;
}
if ((type & DTLS_TYPE_RTCP)) {
rtp_session->rtcp_dtls = dtls;
if (!(type & DTLS_TYPE_RTP)) {
dtls->sock_output = rtp_session->rtcp_sock_output;
dtls->remote_addr = rtp_session->rtcp_remote_addr;
}
}
if ((type & DTLS_TYPE_SERVER)) {
SSL_set_accept_state(dtls->ssl);
} else {
SSL_set_connect_state(dtls->ssl);
}
return SWITCH_STATUS_SUCCESS;
}
@ -2232,6 +2250,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
switch_channel_t *channel = switch_core_session_get_channel(rtp_session->session);
switch_event_t *fsevent = NULL;
int idx = 0;
if (direction >= SWITCH_RTP_CRYPTO_MAX || keylen > SWITCH_RTP_MAX_CRYPTO_LEN) {
return SWITCH_STATUS_FALSE;
@ -2239,10 +2258,18 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
crypto_key = switch_core_alloc(rtp_session->pool, sizeof(*crypto_key));
if (direction == SWITCH_RTP_CRYPTO_RECV_RTCP) {
direction = SWITCH_RTP_CRYPTO_RECV;
rtp_session->srtp_idx_rtcp = idx = 1;
} else if (direction == SWITCH_RTP_CRYPTO_SEND_RTCP) {
direction = SWITCH_RTP_CRYPTO_SEND;
rtp_session->srtp_idx_rtcp = idx = 1;
}
if (direction == SWITCH_RTP_CRYPTO_RECV) {
policy = &rtp_session->recv_policy;
policy = &rtp_session->recv_policy[idx];
} else {
policy = &rtp_session->send_policy;
policy = &rtp_session->send_policy[idx];
}
crypto_key->type = type;
@ -2305,10 +2332,10 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
case SWITCH_RTP_CRYPTO_RECV:
policy->ssrc.type = ssrc_any_inbound;
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV]) {
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] && idx == 0) {
rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV_RESET] = 1;
} else {
if ((stat = srtp_create(&rtp_session->recv_ctx, policy))) {
if ((stat = srtp_create(&rtp_session->recv_ctx[idx], policy))) {
status = SWITCH_STATUS_FALSE;
}
@ -2327,10 +2354,10 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
//policy->ssrc.type = ssrc_specific;
//policy->ssrc.value = rtp_session->ssrc;
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND]) {
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND] && idx == 0) {
rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_RESET] = 1;
} else {
if ((stat = srtp_create(&rtp_session->send_ctx, policy))) {
if ((stat = srtp_create(&rtp_session->send_ctx[idx], policy))) {
status = SWITCH_STATUS_FALSE;
}
@ -3027,10 +3054,32 @@ SWITCH_DECLARE(uint8_t) switch_rtp_ready(switch_rtp_t *rtp_session)
return ret;
}
static void free_dtls(switch_dtls_t **dtlsp)
{
switch_dtls_t *dtls;
if (!dtlsp) {
return;
}
dtls = *dtlsp;
*dtlsp = NULL;
if (dtls->ssl) {
SSL_free(dtls->ssl);
}
if (dtls->ssl_ctx) {
SSL_CTX_free(dtls->ssl_ctx);
}
}
SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
{
void *pop;
switch_socket_t *sock;
int x;
if (!rtp_session || !*rtp_session || !(*rtp_session)->ready) {
return;
@ -3062,6 +3111,19 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
stfu_n_destroy(&(*rtp_session)->jb);
}
if ((*rtp_session)->dtls && (*rtp_session)->dtls == (*rtp_session)->rtcp_dtls) {
(*rtp_session)->rtcp_dtls = NULL;
}
if ((*rtp_session)->dtls) {
free_dtls(&(*rtp_session)->dtls);
}
if ((*rtp_session)->rtcp_dtls) {
free_dtls(&(*rtp_session)->rtcp_dtls);
}
sock = (*rtp_session)->sock_input;
(*rtp_session)->sock_input = NULL;
switch_socket_close(sock);
@ -3090,14 +3152,22 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
#ifdef ENABLE_SRTP
if ((*rtp_session)->flags[SWITCH_RTP_FLAG_SECURE_SEND]) {
srtp_dealloc((*rtp_session)->send_ctx);
(*rtp_session)->send_ctx = NULL;
for(x = 0; x < 2; x++) {
if ((*rtp_session)->send_ctx[x]) {
srtp_dealloc((*rtp_session)->send_ctx[x]);
(*rtp_session)->send_ctx[x] = NULL;
}
}
(*rtp_session)->flags[SWITCH_RTP_FLAG_SECURE_SEND] = 0;
}
if ((*rtp_session)->flags[SWITCH_RTP_FLAG_SECURE_RECV]) {
srtp_dealloc((*rtp_session)->recv_ctx);
(*rtp_session)->recv_ctx = NULL;
for (x = 0; x < 2; x++) {
if ((*rtp_session)->recv_ctx[x]) {
srtp_dealloc((*rtp_session)->recv_ctx[x]);
(*rtp_session)->recv_ctx[x] = NULL;
}
}
(*rtp_session)->flags[SWITCH_RTP_FLAG_SECURE_RECV] = 0;
}
#endif
@ -3525,6 +3595,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
char *b = (char *) &rtp_session->recv_msg;
//printf("RECV %d %ld\n", *b, *bytes);
if ((*b >= 20) && (*b <= 64)) {
rtp_session->dtls->bytes = *bytes;
@ -3533,7 +3604,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
rtp_session->dtls->bytes = 0;
rtp_session->dtls->data = NULL;
if (*b != 0 && *b != 1 && rtp_session->dtls->state != DS_READY) {
if (0 && *b != 0 && *b != 1 && rtp_session->dtls->state != DS_READY) {
*bytes = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Drop %s packet %ld bytes (dtls not ready!)\n", rtp_type(rtp_session), *bytes);
}
@ -3681,25 +3752,25 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV_RESET]) {
switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV_RESET);
srtp_dealloc(rtp_session->recv_ctx);
rtp_session->recv_ctx = NULL;
if ((stat = srtp_create(&rtp_session->recv_ctx, &rtp_session->recv_policy))) {
srtp_dealloc(rtp_session->recv_ctx[rtp_session->srtp_idx_rtp]);
rtp_session->recv_ctx[rtp_session->srtp_idx_rtp] = NULL;
if ((stat = srtp_create(&rtp_session->recv_ctx[rtp_session->srtp_idx_rtp], &rtp_session->recv_policy[rtp_session->srtp_idx_rtp]))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error! RE-Activating Secure RTP RECV\n");
return SWITCH_STATUS_FALSE;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "RE-Activating Secure RTP RECV\n");
rtp_session->srtp_errs = 0;
rtp_session->srtp_errs[rtp_session->srtp_idx_rtp] = 0;
}
}
if (!(*flags & SFF_PLC)) {
stat = srtp_unprotect(rtp_session->recv_ctx, &rtp_session->recv_msg.header, &sbytes);
stat = srtp_unprotect(rtp_session->recv_ctx[rtp_session->srtp_idx_rtp], &rtp_session->recv_msg.header, &sbytes);
}
if (stat && rtp_session->recv_msg.header.pt != rtp_session->recv_te && rtp_session->recv_msg.header.pt != rtp_session->cng_pt) {
if (++rtp_session->srtp_errs >= MAX_SRTP_ERRS) {
if (++rtp_session->srtp_errs[rtp_session->srtp_idx_rtp] >= MAX_SRTP_ERRS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR,
"Error: SRTP %s unprotect failed with code %d%s %ld\n", rtp_type(rtp_session), stat,
@ -3710,7 +3781,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
sbytes = 0;
}
} else {
rtp_session->srtp_errs = 0;
rtp_session->srtp_errs[rtp_session->srtp_idx_rtp] = 0;
}
*bytes = sbytes;
@ -3855,7 +3926,7 @@ static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t
if (rtp_session->rtcp_dtls) {
char *b = (char *) &rtp_session->rtcp_recv_msg;
//printf("RECV %d %ld\n", *b, *bytes);
//printf("RECV2 %d %ld\n", *b, *bytes);
if ((*b >= 20) && (*b <= 64)) {
rtp_session->rtcp_dtls->bytes = *bytes;
@ -3881,11 +3952,11 @@ static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t
err_status_t stat = 0;
if ((stat = srtp_unprotect_rtcp(rtp_session->recv_ctx, &rtp_session->rtcp_recv_msg_p->header, &sbytes))) {
//++rtp_session->srtp_errs++;
if ((stat = srtp_unprotect_rtcp(rtp_session->recv_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_recv_msg_p->header, &sbytes))) {
//++rtp_session->srtp_errs[rtp_session->srtp_idx_rtp]++;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "RTCP UNPROTECT ERR\n");
} else {
//rtp_session->srtp_errs = 0;
//rtp_session->srtp_errs[rtp_session->srtp_idx_rtp] = 0;
}
*bytes = sbytes;
@ -4202,7 +4273,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
#ifdef ENABLE_SRTP
if (switch_rtp_test_flag(other_rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) {
int sbytes = (int) rtcp_bytes;
int stat = srtp_protect_rtcp(other_rtp_session->send_ctx, &other_rtp_session->rtcp_send_msg.header, &sbytes);
int stat = srtp_protect_rtcp(other_rtp_session->send_ctx[rtp_session->srtp_idx_rtcp], &other_rtp_session->rtcp_send_msg.header, &sbytes);
if (stat) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP RTCP protection failed with code %d\n", stat);
}
@ -5080,7 +5151,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
if (rtp_session->ice.ice_user && !(rtp_session->ice.rready)) {
send = 0;
//printf("XXX skip no stun love %d/%d\n", rtp_session->ice.ready, rtp_session->ice.rready);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Skip sending %s packet %ld bytes (ice not ready!)\n", rtp_type(rtp_session), bytes);
}
if (rtp_session->dtls && rtp_session->dtls->state != DS_READY) {
@ -5104,9 +5175,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_RESET]) {
switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND_RESET);
srtp_dealloc(rtp_session->send_ctx);
rtp_session->send_ctx = NULL;
if ((stat = srtp_create(&rtp_session->send_ctx, &rtp_session->send_policy))) {
srtp_dealloc(rtp_session->send_ctx[rtp_session->srtp_idx_rtp]);
rtp_session->send_ctx[rtp_session->srtp_idx_rtp] = NULL;
if ((stat = srtp_create(&rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &rtp_session->send_policy[rtp_session->srtp_idx_rtp]))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error! RE-Activating Secure RTP SEND\n");
ret = -1;
goto end;
@ -5116,7 +5187,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
}
stat = srtp_protect(rtp_session->send_ctx, &send_msg->header, &sbytes);
stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &send_msg->header, &sbytes);
if (stat) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP protection failed with code %d\n", stat);
@ -5506,9 +5577,9 @@ SWITCH_DECLARE(int) switch_rtp_write_manual(switch_rtp_t *rtp_session,
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_RESET]) {
switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND_RESET);
srtp_dealloc(rtp_session->send_ctx);
rtp_session->send_ctx = NULL;
if ((stat = srtp_create(&rtp_session->send_ctx, &rtp_session->send_policy))) {
srtp_dealloc(rtp_session->send_ctx[rtp_session->srtp_idx_rtp]);
rtp_session->send_ctx[rtp_session->srtp_idx_rtp] = NULL;
if ((stat = srtp_create(&rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &rtp_session->send_policy[rtp_session->srtp_idx_rtp]))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error! RE-Activating Secure RTP SEND\n");
ret = -1;
goto end;
@ -5517,7 +5588,7 @@ SWITCH_DECLARE(int) switch_rtp_write_manual(switch_rtp_t *rtp_session,
}
}
stat = srtp_protect(rtp_session->send_ctx, &rtp_session->write_msg.header, &sbytes);
stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &rtp_session->write_msg.header, &sbytes);
if (stat) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP protection failed with code %d\n", stat);
}