} switch_core_media_params_t;
-typedef struct xpayload_map_s {
- uint32_t pt;
- uint32_t send_pt;
- uint32_t rate;
- uint32_t ptime;
- switch_media_type_t type;
- uint8_t negotiated;
- char *name;
- switch_sdp_type_t sdp_type;
- unsigned long hash;
- struct xpayload_map_s *next;
-} xpayload_map_t;
-
typedef struct payload_map_s {
switch_media_type_t type;
switch_sdp_type_t sdp_type;
uint32_t rate;
uint8_t allocated;
uint8_t negotiated;
+ uint8_t current;
unsigned long hash;
char *rm_encoding;
int ret = 0;
char *rsa;
+ rsa = switch_mprintf("%s%s%s.pem", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, prefix);
- rsa = switch_mprintf("%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, prefix);
+ if (switch_file_exists(rsa, NULL) != SWITCH_STATUS_SUCCESS) {
+ free(rsa);
+ rsa = switch_mprintf("%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, prefix);
+ }
if (!(bio = BIO_new(BIO_s_file()))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FP BIO ERR!\n");
static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days);
-static int add_ext(X509 *cert, int nid, char *value);
SWITCH_DECLARE(int) switch_core_gen_certs(const char *prefix)
{
//bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
- mkcert(&x509, &pkey, 2048, 0, 365);
+ mkcert(&x509, &pkey, 1024, 0, 36500);
//RSA_print_fp(stdout, pkey->pkey.rsa, 0);
//X509_print_fp(stdout, x509);
return(0);
}
+#if 0
static void callback(int p, int n, void *arg)
{
char c='B';
if (p == 3) c='\n';
fputc(c, stderr);
}
+#endif
static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days)
{
RSA *rsa;
X509_NAME *name=NULL;
- if ((pkeyp == NULL) || (*pkeyp == NULL))
- {
- if ((pk=EVP_PKEY_new()) == NULL)
- {
- abort();
- }
- }
- else
- pk= *pkeyp;
-
- if ((x509p == NULL) || (*x509p == NULL))
- {
- if ((x=X509_new()) == NULL)
- goto err;
+ if ((pkeyp == NULL) || (*pkeyp == NULL)) {
+ if ((pk = EVP_PKEY_new()) == NULL) {
+ abort();
}
- else
- x= *x509p;
+ } else {
+ pk = *pkeyp;
+ }
- rsa=RSA_generate_key(bits, RSA_F4, callback, NULL);
- if (!EVP_PKEY_assign_RSA(pk, rsa))
- {
- abort();
+ if ((x509p == NULL) || (*x509p == NULL)) {
+ if ((x = X509_new()) == NULL) {
goto err;
}
- rsa=NULL;
+ } else {
+ x = *x509p;
+ }
+
+ rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
+
+ if (!EVP_PKEY_assign_RSA(pk, rsa)) {
+ abort();
+ goto err;
+ }
+
+ rsa = NULL;
- X509_set_version(x, 2);
+ X509_set_version(x, 0);
ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
- X509_gmtime_adj(X509_get_notBefore(x), 0);
+ X509_gmtime_adj(X509_get_notBefore(x), -(long)60*60*24*7);
X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
X509_set_pubkey(x, pk);
- name=X509_get_subject_name(x);
+ name = X509_get_subject_name(x);
/* This function creates and adds the entry, working out the
* correct string type and performing checks on its length.
* Normally we'd check the return value for errors...
*/
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0);
-
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"FreeSWITCH", -1, -1, 0);
*/
X509_set_issuer_name(x, name);
- /* Add various extensions: standard extensions */
- add_ext(x, NID_basic_constraints, "critical, CA:TRUE");
- add_ext(x, NID_key_usage, "critical, keyCertSign, cRLSign");
-
- add_ext(x, NID_subject_key_identifier, "hash");
-
- /* Some Netscape specific extensions */
- add_ext(x, NID_netscape_cert_type, "sslCA");
-
- add_ext(x, NID_netscape_comment, "Self-Signed CERT for DTLS");
-
-
if (!X509_sign(x, pk, EVP_sha1()))
goto err;
- *x509p=x;
- *pkeyp=pk;
+ *x509p = x;
+ *pkeyp = pk;
return(1);
err:
return(0);
}
-/* Add extension using V3 code: we can set the config file as NULL
- * because we wont reference any other sections.
- */
-
-static int add_ext(X509 *cert, int nid, char *value)
-{
- X509_EXTENSION *ex;
- X509V3_CTX ctx;
- /* This sets the 'context' of the extensions. */
- /* No configuration database */
- X509V3_set_ctx_nodb(&ctx);
- /* Issuer and subject certs: both the target since it is self signed,
- * no request and no CRL
- */
- X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);
- ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
- if (!ex)
- return 0;
-
- X509_add_ext(cert, ex, -1);
- X509_EXTENSION_free(ex);
- return 1;
-}
-
session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].payload_map = switch_core_alloc(session->pool, sizeof(payload_map_t));
session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].cur_payload_map = session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].payload_map;
+ session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].cur_payload_map->current = 1;
session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].payload_map = switch_core_alloc(session->pool, sizeof(payload_map_t));
session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].cur_payload_map = session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].payload_map;
-
+ session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].cur_payload_map->current = 1;
switch_channel_set_flag(session->channel, CF_DTLS_OK);
for (pmap = engine->payload_map; pmap; pmap = pmap->next) {
if (engine->read_frame.payload == pmap->recv_pt && pmap->negotiated) {
engine->cur_payload_map = pmap;
-
+ engine->cur_payload_map->current = 1;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Changing current codec to %s (payload type %d).\n",
pmap->iananame, pmap->pt);
for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
pmap->negotiated = 0;
+ pmap->current = 0;
}
}
if (j == 0) {
a_engine->cur_payload_map = pmap;
+ a_engine->cur_payload_map->current = 1;
+ if (a_engine->rtp_session) {
+ switch_rtp_set_default_payload(a_engine->rtp_session, pmap->pt);
+ }
}
pmap->rm_encoding = switch_core_session_strdup(session, (char *) mmap->rm_encoding);
SWITCH_TRUE);
if (j == 0) {
v_engine->cur_payload_map = pmap;
+ v_engine->cur_payload_map->current = 1;
+ if (v_engine->rtp_session) {
+ switch_rtp_set_default_payload(v_engine->rtp_session, pmap->pt);
+ }
}
mimp = matches[j].imp;
SWITCH_DECLARE(void) switch_core_media_init(void)
{
- switch_core_gen_certs(DTLS_SRTP_FNAME);
+ switch_core_gen_certs(DTLS_SRTP_FNAME ".pem");
}
SWITCH_DECLARE(void) switch_core_media_deinit(void)
char *rsa;
char *pvt;
char *ca;
+ char *pem;
struct switch_rtp *rtp_session;
} switch_dtls_t;
static int dtls_state_handshake(switch_rtp_t *rtp_session, switch_dtls_t *dtls);
static int dtls_state_ready(switch_rtp_t *rtp_session, switch_dtls_t *dtls);
static int dtls_state_setup(switch_rtp_t *rtp_session, switch_dtls_t *dtls);
-static int dtls_state_dummy(switch_rtp_t *rtp_session, switch_dtls_t *dtls);
+static int dtls_state_fail(switch_rtp_t *rtp_session, switch_dtls_t *dtls);
-dtls_state_handler_t dtls_states[DS_INVALID] = {dtls_state_handshake, dtls_state_setup, dtls_state_ready, dtls_state_dummy};
+dtls_state_handler_t dtls_states[DS_INVALID] = {dtls_state_handshake, dtls_state_setup, dtls_state_ready, dtls_state_fail};
typedef struct ts_normalize_s {
uint32_t last_ssrc;
remote_ip = switch_get_addr(ipbuf, sizeof(ipbuf), from_addr);
switch_stun_packet_attribute_add_xor_binded_address(rpacket, (char *) remote_ip, switch_sockaddr_get_port(from_addr));
-
if (!switch_cmp_addr(from_addr, ice->addr)) {
host = switch_get_addr(buf, sizeof(buf), from_addr);
port = switch_sockaddr_get_port(from_addr);
#define dtls_set_state(_dtls, _state) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Changing %s DTLS state from %s to %s\n", rtp_type(rtp_session), dtls_state_names(_dtls->state), dtls_state_names(_state)); _dtls->new_state = 1; _dtls->last_state = _dtls->state; _dtls->state = _state
-static int dtls_state_dummy(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
-{
- return -1;
-}
-
#define cr_keylen 16
#define cr_saltlen 14
#define cr_kslen 30
return 0;
}
+static int dtls_state_fail(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
+{
+ if (rtp_session->session) {
+ switch_channel_t *channel = switch_core_session_get_channel(rtp_session->session);
+ switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ }
+
+ return -1;
+}
+
+
static int dtls_state_handshake(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
{
int ret;
static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
{
int r = 0, ret = 0, len;
- void *data;
switch_size_t bytes;
+ unsigned char buf[4096] = "";
+ int ready = rtp_session->ice.ice_user ? (rtp_session->ice.rready && rtp_session->ice.ready) : 1;
+
- if (dtls->bytes) {
-
- //if (dtls->state == DS_READY) {
- //
- //}
-
- if ((ret = BIO_write(dtls->read_bio, dtls->data, (int)dtls->bytes)) != (int)dtls->bytes) {
- ret = SSL_get_error(dtls->ssl, ret);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS packet read err %d\n", rtp_type(rtp_session), ret);
- dtls_set_state(dtls, DS_FAIL);
- return -1;
- }
+ if (!dtls->bytes && !ready) {
+ printf("SKIP\n");
+ return 0;
}
- if (SSL_read(dtls->ssl, dtls->data, (int)dtls->bytes) == (int)dtls->bytes) {
- if (BIO_reset(dtls->read_bio));
+ if ((ret = BIO_write(dtls->read_bio, dtls->data, (int)dtls->bytes)) != (int)dtls->bytes && dtls->bytes > 0) {
+ ret = SSL_get_error(dtls->ssl, ret);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS packet read err %d\n", rtp_type(rtp_session), ret);
}
r = dtls_states[dtls->state](rtp_session, dtls);
-
- if ((len = BIO_get_mem_data(dtls->write_bio, &data)) && data) {
+ if ((len = BIO_read(dtls->write_bio, buf, sizeof(buf))) > 0) {
bytes = len;
- if (switch_socket_sendto(dtls->sock_output, dtls->remote_addr, 0, data, &bytes ) != SWITCH_STATUS_SUCCESS) {
+ if (switch_socket_sendto(dtls->sock_output, dtls->remote_addr, 0, (void *)buf, &bytes ) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS packet not written\n", rtp_type(rtp_session));
- } else {
- if (BIO_reset(dtls->write_bio));
}
}
+
+
return r;
}
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->pem = switch_core_sprintf(rtp_session->pool, "%s%s%s.pem", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME);
+
+ if (switch_file_exists(dtls->pem, rtp_session->pool) == SWITCH_STATUS_SUCCESS) {
+ dtls->pvt = dtls->rsa = dtls->pem;
+ } else {
+ 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());
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_set_verify(dtls->ssl, SSL_VERIFY_NONE, NULL);
SSL_set_app_data(dtls->ssl, dtls);
+ BIO_ctrl(dtls->read_bio, BIO_CTRL_DGRAM_SET_MTU, 1400, NULL);
+ BIO_ctrl(dtls->write_bio, BIO_CTRL_DGRAM_SET_MTU, 1400, NULL);
+ SSL_set_mtu(dtls->ssl, 1400);
+ BIO_ctrl(dtls->write_bio, BIO_C_SET_BUFF_SIZE, 1400, NULL);
+ BIO_ctrl(dtls->read_bio, BIO_C_SET_BUFF_SIZE, 1400, NULL);
+
+
+
dtls->local_fp = local_fp;
dtls->remote_fp = remote_fp;
dtls->rtp_session = rtp_session;
ok = 0;
switch_mutex_lock(rtp_session->flag_mutex);
+
for (pmap = *rtp_session->pmaps; pmap && pmap->allocated; pmap = pmap->next) {
if (!pmap->negotiated) {
continue;
}
} else {
payload = rtp_session->payload;
+#if 0
+ if (rtp_session->pmaps && *rtp_session->pmaps) {
+ payload_map_t *pmap;
+ for (pmap = *rtp_session->pmaps; pmap; pmap = pmap->next) {
+ if (pmap->current) {
+ payload = pmap->pt;
+ }
+ }
+ }
+#endif
}
if (switch_test_flag(frame, SFF_RTP_HEADER)) {