diff --git a/acinclude.m4 b/acinclude.m4 index aeba17b5c3..58b5500a80 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -6,6 +6,7 @@ m4_include([build/config/ac_gcc_archflag.m4]) m4_include([build/config/ac_gcc_x86_cpuid.m4]) m4_include([build/config/ax_lib_mysql.m4]) m4_include([build/config/ax_check_java.m4]) +m4_include([build/config/uuid.m4]) m4_include([build/config/erlang.m4]) m4_include([build/config/odbc.m4]) m4_include([build/config/sched_setaffinity.m4]) diff --git a/build/config/uuid.m4 b/build/config/uuid.m4 new file mode 100644 index 0000000000..7f37c23c66 --- /dev/null +++ b/build/config/uuid.m4 @@ -0,0 +1,17 @@ +AC_DEFUN([CHECK_LIBUUID], + [ + PKG_CHECK_MODULES([LIBUUID], [uuid >= 1.41.2], + [LIBUUID_FOUND=yes], [LIBUUID_FOUND=no]) + if test "$LIBUUID_FOUND" = "no" ; then + PKG_CHECK_MODULES([LIBUUID], [uuid], + [LIBUUID_FOUND=yes], [LIBUUID_FOUND=no]) + if test "$LIBUUID_FOUND" = "no" ; then + AC_MSG_WARN([libuuid development package highly recommended!]) + else + LIBUUID_INCLUDEDIR=$(pkg-config --variable=includedir uuid) + LIBUUID_CFLAGS+=" -I$LIBUUID_INCLUDEDIR/uuid " + fi + fi + AC_SUBST([LIBUUID_CFLAGS]) + AC_SUBST([LIBUUID_LIBS]) + ]) diff --git a/conf/rayo/autoload_configs/rayo.conf.xml b/conf/rayo/autoload_configs/rayo.conf.xml index c8171569af..82adf96faa 100644 --- a/conf/rayo/autoload_configs/rayo.conf.xml +++ b/conf/rayo/autoload_configs/rayo.conf.xml @@ -17,10 +17,10 @@ - + - - + + @@ -49,8 +49,9 @@ - - + + + diff --git a/configure.in b/configure.in index 9307c958c9..d186eebc94 100644 --- a/configure.in +++ b/configure.in @@ -412,6 +412,10 @@ if test "x$enable_core_odbc_support" != "xno"; then AC_CHECK_LIB([odbc], [SQLDisconnect],, AC_MSG_ERROR([no usable libodbc; please install unixodbc devel package or equivalent])) fi +CHECK_LIBUUID +SWITCH_AM_LDFLAGS="$LIBUUID_LIBS $SWITCH_AM_LDFLAGS" +SWITCH_AM_CFLAGS="$LIBUUID_CFLAGS $SWITCH_AM_CFLAGS" + AC_ARG_ENABLE(core-pgsql-support, [AS_HELP_STRING([--enable-core-pgsql-support], [Compile with PGSQL Support])],,[enable_core_pgsql_support="no"]) AC_ARG_ENABLE(core-pgsql-pkgconfig, diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index b9776f14ac..03953b36c0 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -36,6 +36,7 @@ avoid_mods=( xml_int/mod_xml_radius ) avoid_mods_sid=( + languages/mod_java ) avoid_mods_jessie=( ) diff --git a/libs/curl/lib/strequal.h b/libs/curl/lib/strequal.h index 6ec88d82d7..ce83d48aef 100644 --- a/libs/curl/lib/strequal.h +++ b/libs/curl/lib/strequal.h @@ -38,6 +38,6 @@ char *Curl_strcasestr(const char *haystack, const char *needle); #ifndef HAVE_STRLCAT #define strlcat(x,y,z) Curl_strlcat(x,y,z) #endif -size_t strlcat(char *dst, const char *src, size_t siz); +//size_t strlcat(char *dst, const char *src, size_t siz); #endif diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index d186665413..ede0675df0 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -1513,6 +1513,10 @@ ESL_DECLARE(esl_status_t) esl_send_recv_timed(esl_handle_t *handle, const char * } recv: + + esl_event_safe_destroy(&handle->last_sr_event); + + *handle->last_sr_reply = '\0'; status = esl_recv_event_timed(handle, ms, 0, &handle->last_sr_event); diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c index fdeb67f4b9..8a537bb5e6 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c +++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c @@ -656,9 +656,6 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj) if (ftdmchan->state == FTDM_CHANNEL_STATE_UP) { cas_bits = 0; ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CAS_BITS, &cas_bits); - if (!(state_counter % 5000)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "CAS bits: 0x%X\n", cas_bits); - } if (cas_bits == 0x0) { cas_hangup += interval; if (cas_hangup >= cas_hangup_ms) { diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h index 5c083101a9..cfbe9921eb 100644 --- a/src/include/switch_core_media.h +++ b/src/include/switch_core_media.h @@ -292,7 +292,7 @@ SWITCH_DECLARE(stfu_instance_t *) switch_core_media_get_jb(switch_core_session_t SWITCH_DECLARE(switch_rtp_stats_t *) switch_core_media_get_stats(switch_core_session_t *session, switch_media_type_t type, switch_memory_pool_t *pool); -SWITCH_DECLARE(void) switch_core_media_set_sdp_codec_string(switch_core_session_t *session, const char *r_sdp); +SWITCH_DECLARE(void) switch_core_media_set_sdp_codec_string(switch_core_session_t *session, const char *r_sdp, switch_sdp_type_t sdp_type); SWITCH_DECLARE(void) switch_core_media_reset_autofix(switch_core_session_t *session, switch_media_type_t type); SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_t *session, switch_core_session_t *o_session); SWITCH_DECLARE(switch_status_t) switch_core_media_codec_chosen(switch_core_session_t *session, switch_media_type_t media); @@ -305,6 +305,13 @@ SWITCH_DECLARE(void) switch_core_media_deinit(void); SWITCH_DECLARE(void) switch_core_media_set_stats(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_session_clear_crypto(switch_core_session_t *session); + +SWITCH_DECLARE(switch_status_t) switch_core_session_get_payload_code(switch_core_session_t *session, + switch_media_type_t type, + const char *iananame, + switch_payload_t *ptP, + switch_payload_t *recv_ptP); + SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_session_t *session, switch_media_type_t type, const char *name, diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 55e681aa09..dd3d6bb4bb 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -6179,7 +6179,7 @@ static switch_status_t conf_api_sub_file_seek(conference_obj_t *conference, swit step = 1000; } - samps = step * (conference->rate / 1000); + samps = step * (conference->fnode->fh.native_rate / 1000); target = (int32_t)conference->fnode->fh.pos + samps; if (target < 0) { @@ -6190,7 +6190,7 @@ static switch_status_t conf_api_sub_file_seek(conference_obj_t *conference, swit switch_core_file_seek(&conference->fnode->fh, &pos, target, SEEK_SET); } else { - samps = switch_atoui(argv[2]) * (conference->rate / 1000); + samps = switch_atoui(argv[2]) * (conference->fnode->fh.native_rate / 1000); stream->write_function(stream, "+OK seek to position %d\n", samps); switch_core_file_seek(&conference->fnode->fh, &pos, samps, SEEK_SET); } diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 527de9b8fb..cd566c22bd 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5118,8 +5118,12 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status } tech_pvt->mparams.last_sdp_str = NULL; - if (!sofia_use_soa(tech_pvt) && sip->sip_payload && sip->sip_payload->pl_data) { - tech_pvt->mparams.last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data); + if (sip->sip_payload && sip->sip_payload->pl_data) { + switch_core_media_set_sdp_codec_string(session, sip->sip_payload->pl_data, SDP_TYPE_RESPONSE); + + if (!sofia_use_soa(tech_pvt)) { + tech_pvt->mparams.last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data); + } } @@ -5867,9 +5871,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote SDP:\n%s\n", r_sdp); tech_pvt->mparams.remote_sdp_str = switch_core_session_strdup(session, r_sdp); - if ((sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) { - switch_core_media_set_sdp_codec_string(session, r_sdp); - } + //if ((sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) { + // switch_core_media_set_sdp_codec_string(session, r_sdp, status < 200 ? SDP_TYPE_REQUEST : SDP_TYPE_RESPONSE); + //} sofia_glue_pass_sdp(tech_pvt, (char *) r_sdp); sofia_set_flag(tech_pvt, TFLAG_NEW_SDP); @@ -7882,8 +7886,13 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia const char *from_tag = ""; char *sql = NULL; char *acl_context = NULL; + const char *r_sdp = NULL; + profile->ib_calls++; + if (sip->sip_payload && sip->sip_payload->pl_data) { + r_sdp = sip->sip_payload->pl_data; + } if (!session || (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING))) { nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"), TAG_END()); @@ -7910,6 +7919,12 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia is_nat = "websockets"; } + + if (r_sdp) { + switch_core_media_set_sdp_codec_string(session, r_sdp, SDP_TYPE_REQUEST); + } + + if (sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION)) { if (sip && sip->sip_via) { const char *port = sip->sip_via->v_port; diff --git a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml index 3fdc772daf..dc90b519df 100644 --- a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml +++ b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml @@ -49,8 +49,9 @@ - - + + + diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index 88eb44b417..7dcd6738dc 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -135,11 +135,13 @@ struct rayo_call { /** ID of joined party TODO this will be many mixers / calls */ const char *joined_id; /** set if response needs to be sent to IQ request */ - const char *dial_id; + const char *dial_request_id; /** channel destroy event */ switch_event_t *end_event; /** True if ringing event sent to client */ int ringing_sent; + /** True if request to create this call failed */ + int dial_request_failed; }; /** @@ -877,9 +879,9 @@ static void rayo_call_cleanup(struct rayo_actor *actor) iks *revent; iks *end; - if (!event) { + if (!event || call->dial_request_failed) { /* destroyed before FS session was created (in originate, for example) */ - return; + goto done; } revent = iks_new_presence("end", RAYO_NS, @@ -941,6 +943,10 @@ static void rayo_call_cleanup(struct rayo_actor *actor) RAYO_SEND_MESSAGE_DUP(actor, rayo_call_get_dcp_jid(call), revent); } + iks_delete(revent); + +done: + /* lost the race: pending join failed... send IQ result to client now. */ if (call->pending_join_request) { iks *request = call->pending_join_request; @@ -950,8 +956,9 @@ static void rayo_call_cleanup(struct rayo_actor *actor) iks_delete(call->pending_join_request); } - iks_delete(revent); - switch_event_destroy(&event); + if (event) { + switch_event_destroy(&event); + } switch_core_hash_destroy(&call->pcps); } @@ -1102,6 +1109,9 @@ static struct rayo_call *rayo_call_init(struct rayo_call *call, switch_memory_po call->joined_id = NULL; call->ringing_sent = 0; call->pending_join_request = NULL; + call->dial_request_id = NULL; + call->end_event = NULL; + call->dial_request_failed = 0; switch_core_hash_init(&call->pcps, pool); switch_safe_free(call_jid); @@ -2141,7 +2151,7 @@ static void *SWITCH_THREAD_FUNC rayo_dial_thread(switch_thread_t *thread, void * /* create call and link to DCP */ call = rayo_call_create(NULL); call->dcp_jid = switch_core_strdup(RAYO_POOL(call), dcp_jid); - call->dial_id = iks_find_attrib(iq, "id"); + call->dial_request_id = iks_find_attrib(iq, "id"); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s has control of call\n", dcp_jid); uuid = switch_core_strdup(dtdata->pool, rayo_call_get_uuid(call)); @@ -2245,27 +2255,63 @@ static void *SWITCH_THREAD_FUNC rayo_dial_thread(switch_thread_t *thread, void * if (switch_api_execute("originate", stream.data, NULL, &api_stream) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Got originate result: %s\n", (char *)api_stream.data); + switch_mutex_lock(RAYO_ACTOR(call)->mutex); /* check for failure */ if (strncmp("+OK", api_stream.data, strlen("+OK"))) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_INFO, "Failed to originate call\n"); - if (call->dial_id) { + if (call->dial_request_id) { + call->dial_request_failed = 1; + call->dial_request_id = NULL; + /* map failure reason to iq error */ if (!strncmp("-ERR DESTINATION_OUT_OF_ORDER", api_stream.data, strlen("-ERR DESTINATION_OUT_OF_ORDER"))) { - /* this -ERR is received when out of sessions */ - response = iks_new_error(iq, STANZA_ERROR_RESOURCE_CONSTRAINT); + /* out of sessions, typically */ + response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, (char *)api_stream.data); + } else if (!strncmp("-ERR USER_NOT_REGISTERED", api_stream.data, strlen("-ERR USER_NOT_REGISTERED"))) { + response = iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, (char *)api_stream.data); + } else if (!strncmp("-ERR EXCHANGE_ROUTING_ERROR", api_stream.data, strlen("-ERR EXCHANGE_ROUTING_ERROR"))) { + /* max forwards */ + response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, (char *)api_stream.data); + } else if (!strncmp("-ERR CHAN_NOT_IMPLEMENTED", api_stream.data, strlen("-ERR CHAN_NOT_IMPLEMENTED"))) { + /* unsupported endpoint type */ + response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, (char *)api_stream.data); + } else if (!strncmp("-ERR INVALID_URL", api_stream.data, strlen("-ERR INVALID_URL"))) { + response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, (char *)api_stream.data); + } else if (!strncmp("-ERR INVALID_GATEWAY", api_stream.data, strlen("-ERR INVALID_GATEWAY"))) { + response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, (char *)api_stream.data); + } else if (!strncmp("-ERR INVALID_PROFILE", api_stream.data, strlen("-ERR INVALID_PROFILE"))) { + response = iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, (char *)api_stream.data); + } else if (!strncmp("-ERR SYSTEM_SHUTDOWN", api_stream.data, strlen("-ERR SYSTEM_SHUTDOWN"))) { + response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, (char *)api_stream.data); + } else if (!strncmp("-ERR GATEWAY_DOWN", api_stream.data, strlen("-ERR GATEWAY_DOWN"))) { + response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, (char *)api_stream.data); + } else if (!strncmp("-ERR INVALID_NUMBER_FORMAT", api_stream.data, strlen("-ERR INVALID_NUMBER_FORMAT"))) { + response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, (char *)api_stream.data); + } else { + /* other unspecified error */ + response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, (char *)api_stream.data); } } } - } else if (call->dial_id) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Failed to exec originate API\n"); - response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "Failed to execute originate API"); + switch_mutex_unlock(RAYO_ACTOR(call)->mutex); + } else { + switch_mutex_lock(RAYO_ACTOR(call)->mutex); + if (call->dial_request_id) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Failed to exec originate API\n"); + call->dial_request_failed = 1; + call->dial_request_id = NULL; + response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "Failed to execute originate API"); + } + switch_mutex_unlock(RAYO_ACTOR(call)->mutex); } switch_safe_free(api_stream.data); } else { /* will only happen if misconfigured */ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_CRIT, "No dial gateway found for %s!\n", dial_to); + call->dial_request_failed = 1; + call->dial_request_id = NULL; response = iks_new_error_detailed_printf(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "No dial gateway found for %s!\n", dial_to); goto done; } @@ -2719,21 +2765,27 @@ static void on_call_originate_event(struct rayo_client *rclient, switch_event_t if (call && (session = switch_core_session_locate(uuid))) { iks *response, *ref; - switch_channel_set_private(switch_core_session_get_channel(session), "rayo_call_private", call); + switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Got originate event\n"); + + switch_mutex_lock(RAYO_ACTOR(call)->mutex); + if (call->dial_request_id) { + switch_channel_set_private(switch_core_session_get_channel(session), "rayo_call_private", call); + + /* send response to DCP */ + response = iks_new("iq"); + iks_insert_attrib(response, "from", RAYO_JID(globals.server)); + iks_insert_attrib(response, "to", rayo_call_get_dcp_jid(call)); + iks_insert_attrib(response, "id", call->dial_request_id); + iks_insert_attrib(response, "type", "result"); + ref = iks_insert(response, "ref"); + iks_insert_attrib(ref, "xmlns", RAYO_NS); + + iks_insert_attrib_printf(ref, "uri", "xmpp:%s", RAYO_JID(call)); + RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), response); + call->dial_request_id = NULL; + } + switch_mutex_unlock(RAYO_ACTOR(call)->mutex); switch_core_session_rwunlock(session); - - /* send response to DCP */ - response = iks_new("iq"); - iks_insert_attrib(response, "from", RAYO_JID(globals.server)); - iks_insert_attrib(response, "to", rayo_call_get_dcp_jid(call)); - iks_insert_attrib(response, "id", call->dial_id); - iks_insert_attrib(response, "type", "result"); - ref = iks_insert(response, "ref"); - iks_insert_attrib(ref, "xmlns", RAYO_NS); - - iks_insert_attrib_printf(ref, "uri", "xmpp:%s", RAYO_JID(call)); - RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), response); - call->dial_id = NULL; } RAYO_UNLOCK(call); } @@ -2754,9 +2806,15 @@ static void on_call_end_event(switch_event_t *event) switch_safe_free(event_str); } #endif - switch_event_dup(&call->end_event, event); - RAYO_UNLOCK(call); /* decrement ref from creation */ - RAYO_DESTROY(call); + switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Got channel destroy event\n"); + + switch_mutex_lock(RAYO_ACTOR(call)->mutex); + if (!call->dial_request_id && !call->dial_request_failed) { + switch_event_dup(&call->end_event, event); + RAYO_DESTROY(call); + RAYO_UNLOCK(call); /* decrement ref from creation */ + } + switch_mutex_unlock(RAYO_ACTOR(call)->mutex); RAYO_UNLOCK(call); /* decrement this ref */ } } @@ -2796,9 +2854,9 @@ static void on_call_ringing_event(struct rayo_client *rclient, switch_event_t *e switch_event_get_header(event, "variable_rayo_dcp_jid")); call->ringing_sent = 1; RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent); - RAYO_UNLOCK(call); } switch_mutex_unlock(RAYO_ACTOR(call)->mutex); + RAYO_UNLOCK(call); } } } diff --git a/src/switch_caller.c b/src/switch_caller.c index fdd41a4dd7..f7a9e5d40a 100644 --- a/src/switch_caller.c +++ b/src/switch_caller.c @@ -313,6 +313,10 @@ SWITCH_DECLARE(void) switch_caller_profile_event_set_data(switch_caller_profile_ switch_snprintf(header_name, sizeof(header_name), "%s-Direction", prefix); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->direction == SWITCH_CALL_DIRECTION_INBOUND ? "inbound" : "outbound"); + + switch_snprintf(header_name, sizeof(header_name), "%s-Logical-Direction", prefix); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->logical_direction == SWITCH_CALL_DIRECTION_INBOUND ? + "inbound" : "outbound"); if (!zstr(caller_profile->username)) { switch_snprintf(header_name, sizeof(header_name), "%s-Username", prefix); diff --git a/src/switch_core_media.c b/src/switch_core_media.c index bbef0b79bd..eee0affc86 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -40,9 +40,9 @@ #include #include -SWITCH_DECLARE(switch_t38_options_t *) switch_core_media_process_udptl(switch_core_session_t *session, sdp_session_t *sdp, sdp_media_t *m); -SWITCH_DECLARE(void) switch_core_media_find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp); -SWITCH_DECLARE(void) switch_core_media_set_r_sdp_codec_string(switch_core_session_t *session, const char *codec_string, sdp_session_t *sdp); +static switch_t38_options_t * switch_core_media_process_udptl(switch_core_session_t *session, sdp_session_t *sdp, sdp_media_t *m); +static void switch_core_media_find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp); +static void switch_core_media_set_r_sdp_codec_string(switch_core_session_t *session, const char *codec_string, sdp_session_t *sdp, switch_sdp_type_t sdp_type); //#define GOOGLE_ICE #define RTCP_MUX @@ -162,6 +162,7 @@ struct switch_media_handle_s { char *origin; switch_mutex_t *mutex; + switch_mutex_t *sdp_mutex; const switch_codec_implementation_t *negotiated_codecs[SWITCH_MAX_CODECS]; int num_negotiated_codecs; @@ -262,7 +263,7 @@ SWITCH_DECLARE(const char *) switch_core_media_get_zrtp_hash(switch_core_session } -SWITCH_DECLARE(void) switch_core_media_find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp) +static void switch_core_media_find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_rtp_engine_t *audio_engine; @@ -306,7 +307,7 @@ SWITCH_DECLARE(void) switch_core_media_find_zrtp_hash(switch_core_session_t *ses } -SWITCH_DECLARE(switch_t38_options_t *) switch_core_media_process_udptl(switch_core_session_t *session, sdp_session_t *sdp, sdp_media_t *m) +static switch_t38_options_t * switch_core_media_process_udptl(switch_core_session_t *session, sdp_session_t *sdp, sdp_media_t *m) { switch_t38_options_t *t38_options = switch_channel_get_private(session->channel, "t38_options"); sdp_attribute_t *attr; @@ -459,6 +460,53 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_process_t38_passthru(switch_co } +SWITCH_DECLARE(switch_status_t) switch_core_session_get_payload_code(switch_core_session_t *session, + switch_media_type_t type, + const char *iananame, + switch_payload_t *ptP, + switch_payload_t *recv_ptP) +{ + payload_map_t *pmap; + switch_media_handle_t *smh; + switch_rtp_engine_t *engine; + switch_payload_t pt = 0, recv_pt = 0; + int found = 0; + + switch_assert(session); + + if (!(smh = session->media_handle)) { + return SWITCH_STATUS_FALSE; + } + + engine = &smh->engines[type]; + + switch_mutex_lock(smh->sdp_mutex); + for (pmap = engine->payload_map; pmap ; pmap = pmap->next) { + + if (!pmap->allocated) continue; + + if (!strcasecmp(pmap->iananame, iananame)) { + pt = pmap->pt; + recv_pt = pmap->recv_pt; + found++; + } + } + switch_mutex_unlock(smh->sdp_mutex); + + if (found) { + if (ptP) { + *ptP = pt; + } + if (recv_ptP) { + *recv_ptP = recv_pt; + } + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; + +} + SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_session_t *session, switch_media_type_t type, @@ -482,11 +530,11 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se engine = &smh->engines[type]; - switch_mutex_lock(smh->mutex); + switch_mutex_lock(smh->sdp_mutex); for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) { - exists = (!strcasecmp(name, pmap->iananame) && rate == pmap->rate && pmap->ptime == ptime); + exists = (!strcasecmp(name, pmap->iananame) && (!pmap->rate || rate == pmap->rate) && (pmap->ptime || pmap->ptime == ptime)); if (exists) { break; @@ -495,17 +543,27 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se if (!exists) { + switch_ssize_t hlen = -1; + if (engine->payload_map && !engine->payload_map->allocated) { pmap = engine->payload_map; } else { pmap = switch_core_alloc(session->pool, sizeof(*pmap)); } - pmap->sdp_type = sdp_type; pmap->type = type; pmap->iananame = switch_core_strdup(session->pool, name); pmap->rm_encoding = pmap->iananame; + pmap->hash = switch_ci_hashfunc_default(pmap->iananame, &hlen); + } + + pmap->sdp_type = sdp_type; + + if (ptime) { pmap->ptime = ptime; + } + + if (rate) { pmap->rate = rate; } @@ -531,7 +589,7 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se } } - switch_mutex_unlock(smh->mutex); + switch_mutex_unlock(smh->sdp_mutex); return pmap; } @@ -1141,6 +1199,7 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t switch_mutex_init(&session->media_handle->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); + switch_mutex_init(&session->media_handle->sdp_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssrc = (uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO] + (uint32_t) time(NULL)); @@ -1635,7 +1694,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session /* search for payload type */ - switch_mutex_lock(smh->mutex); + switch_mutex_lock(smh->sdp_mutex); for (pmap = engine->cur_payload_map; pmap; pmap = pmap->next) { if (engine->read_frame.payload == pmap->recv_pt) { engine->cur_payload_map = pmap; @@ -1649,7 +1708,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session break; } } - switch_mutex_unlock(smh->mutex); + switch_mutex_unlock(smh->sdp_mutex); if (!engine->reset_codec) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, @@ -5606,10 +5665,10 @@ SWITCH_DECLARE(void)switch_core_media_set_local_sdp(switch_core_session_t *sessi return; } - if (smh->mutex) switch_mutex_lock(smh->mutex); + if (smh->sdp_mutex) switch_mutex_lock(smh->sdp_mutex); smh->mparams->local_sdp_str = dup ? switch_core_session_strdup(session, sdp_str) : (char *) sdp_str; switch_channel_set_variable(session->channel, "rtp_local_sdp_str", smh->mparams->local_sdp_str); - if (smh->mutex) switch_mutex_unlock(smh->mutex); + if (smh->sdp_mutex) switch_mutex_unlock(smh->sdp_mutex); } @@ -5643,6 +5702,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess switch_media_handle_t *smh; ice_t *ice_out; int vp8 = 0; + int red = 0; payload_map_t *pmap; switch_assert(session); @@ -5701,16 +5761,24 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess smh->mparams->cng_pt = 0; } + + if (!smh->payload_space) { int i; + smh->payload_space = 98; if (sdp_type == SDP_TYPE_REQUEST) { + switch_core_session_t *orig_session = NULL; + + switch_core_session_get_partner(session, &orig_session); + for (i = 0; i < smh->mparams->num_codecs; i++) { const switch_codec_implementation_t *imp = smh->codecs[i]; - + switch_payload_t orig_pt = 0; + smh->ianacodes[i] = imp->ianacode; if (smh->ianacodes[i] > 64) { @@ -5721,7 +5789,15 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess smh->mparams->cng_pt && use_cng && smh->mparams->cng_pt == smh->payload_space) { smh->payload_space++; } - smh->ianacodes[i] = (switch_payload_t)smh->payload_space++; + + if (orig_session && + switch_core_session_get_payload_code(orig_session, + imp->codec_type == SWITCH_CODEC_TYPE_AUDIO ? SWITCH_MEDIA_TYPE_AUDIO : SWITCH_MEDIA_TYPE_VIDEO, + imp->iananame, &orig_pt, NULL) == SWITCH_STATUS_SUCCESS) { + smh->ianacodes[i] = orig_pt; + } else { + smh->ianacodes[i] = (switch_payload_t)smh->payload_space++; + } } @@ -5735,6 +5811,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess SWITCH_FALSE); } + + if (orig_session) { + switch_core_session_rwunlock(orig_session); + } } } @@ -5846,13 +5926,13 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess if (switch_media_handle_test_media_flag(smh, SCMF_MULTI_ANSWER_AUDIO)) { - switch_mutex_lock(smh->mutex); + switch_mutex_lock(smh->sdp_mutex); for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) { if (pmap->pt != a_engine->cur_payload_map->pt) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt); } } - switch_mutex_unlock(smh->mutex); + switch_mutex_unlock(smh->sdp_mutex); } if ((smh->mparams->dtmf_type == DTMF_2833 || switch_media_handle_test_media_flag(smh, SCMF_LIBERAL_DTMF) || @@ -5886,7 +5966,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } if (switch_media_handle_test_media_flag(smh, SCMF_MULTI_ANSWER_AUDIO)) { - switch_mutex_lock(smh->mutex); + switch_mutex_lock(smh->sdp_mutex); for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) { if (pmap->pt != a_engine->cur_payload_map->pt) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n", @@ -5894,7 +5974,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess pmap->rate); } } - switch_mutex_unlock(smh->mutex); + switch_mutex_unlock(smh->sdp_mutex); } @@ -6165,13 +6245,13 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", v_engine->cur_payload_map->agreed_pt); if (switch_media_handle_test_media_flag(smh, SCMF_MULTI_ANSWER_VIDEO)) { - switch_mutex_lock(smh->mutex); + switch_mutex_lock(smh->sdp_mutex); for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) { if (pmap->pt != v_engine->cur_payload_map->pt) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt); } } - switch_mutex_unlock(smh->mutex); + switch_mutex_unlock(smh->sdp_mutex); } } else if (smh->mparams->num_codecs) { @@ -6216,6 +6296,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess vp8 = v_engine->cur_payload_map->pt; } + if (!strcasecmp(v_engine->cur_payload_map->rm_encoding, "red")) { + red = v_engine->cur_payload_map->pt; + } + rate = v_engine->cur_payload_map->rm_rate; switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n", v_engine->cur_payload_map->pt, v_engine->cur_payload_map->rm_encoding, @@ -6247,7 +6331,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess if (switch_media_handle_test_media_flag(smh, SCMF_MULTI_ANSWER_VIDEO)) { - switch_mutex_lock(smh->mutex); + switch_mutex_lock(smh->sdp_mutex); for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) { if (pmap->pt != v_engine->cur_payload_map->pt) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n", @@ -6255,7 +6339,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } } - switch_mutex_unlock(smh->mutex); + switch_mutex_unlock(smh->sdp_mutex); } @@ -6299,6 +6383,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess vp8 = ianacode; } + if (!strcasecmp(imp->iananame, "red")) { + red = ianacode; + } + if (channels > 1) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", ianacode, imp->iananame, imp->samples_per_second, channels); @@ -6377,11 +6465,15 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=AS:%d\n", bw); } - if (vp8) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-fb:%d ccm fir\n", vp8); } + + if (red) { + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), + "a=rtcp-fb:%d nack\n", vp8); + } switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\n", v_engine->ssrc, smh->cname); switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s v0\n", v_engine->ssrc, smh->msid); @@ -7619,7 +7711,7 @@ SWITCH_DECLARE(stfu_instance_t *) switch_core_media_get_jb(switch_core_session_t //? -SWITCH_DECLARE(void) switch_core_media_set_sdp_codec_string(switch_core_session_t *session, const char *r_sdp) +SWITCH_DECLARE(void) switch_core_media_set_sdp_codec_string(switch_core_session_t *session, const char *r_sdp, switch_sdp_type_t sdp_type) { sdp_parser_t *parser; sdp_session_t *sdp; @@ -7635,7 +7727,7 @@ SWITCH_DECLARE(void) switch_core_media_set_sdp_codec_string(switch_core_session_ if ((parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) { if ((sdp = sdp_session(parser))) { - switch_core_media_set_r_sdp_codec_string(session, switch_core_media_get_codec_string(session), sdp); + switch_core_media_set_r_sdp_codec_string(session, switch_core_media_get_codec_string(session), sdp, sdp_type); } sdp_parser_free(parser); @@ -7699,7 +7791,7 @@ static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size } -SWITCH_DECLARE(void) switch_core_media_set_r_sdp_codec_string(switch_core_session_t *session, const char *codec_string, sdp_session_t *sdp) +static void switch_core_media_set_r_sdp_codec_string(switch_core_session_t *session, const char *codec_string, sdp_session_t *sdp, switch_sdp_type_t sdp_type) { char buf[1024] = { 0 }; sdp_media_t *m; @@ -7759,6 +7851,33 @@ SWITCH_DECLARE(void) switch_core_media_set_r_sdp_codec_string(switch_core_sessio for (m = sdp->sdp_media; m; m = m->m_next) { ptime = dptime; + + if ((m->m_type == sdp_media_audio || m->m_type == sdp_media_video) && m->m_port) { + for (map = m->m_rtpmaps; map; map = map->rm_next) { + for (attr = m->m_attributes; attr; attr = attr->a_next) { + if (zstr(attr->a_name)) { + continue; + } + if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) { + ptime = atoi(attr->a_value); + break; + } + } + switch_core_media_add_payload_map(session, + m->m_type == sdp_media_audio ? SWITCH_MEDIA_TYPE_AUDIO : SWITCH_MEDIA_TYPE_VIDEO, + map->rm_encoding, + sdp_type, + map->rm_pt, + map->rm_rate, + ptime, + SWITCH_FALSE); + } + } + } + + for (m = sdp->sdp_media; m; m = m->m_next) { + ptime = dptime; + if (m->m_type == sdp_media_image && m->m_port) { switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",t38"); } else if (m->m_type == sdp_media_audio && m->m_port) { diff --git a/src/switch_rtp.c b/src/switch_rtp.c index a0e80013f0..aa296c95da 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -399,7 +399,6 @@ struct switch_rtp { switch_core_session_t *session; payload_map_t **pmaps; payload_map_t *pmap_tail; - int pmap_ttl; #ifdef ENABLE_ZRTP zrtp_session_t *zrtp_session; @@ -6200,10 +6199,10 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra rtp_session->stats.outbound.packet_count++; } - if (frame->pmap && rtp_session->pmaps && *rtp_session->pmaps && rtp_session->pmap_ttl > 1) { + if (frame->pmap && rtp_session->pmaps && *rtp_session->pmaps) { payload_map_t *pmap; - switch_mutex_lock(rtp_session->flag_mutex); + switch_mutex_lock(rtp_session->flag_mutex); for (pmap = *rtp_session->pmaps; pmap; pmap = pmap->next) { if (pmap->hash == frame->pmap->hash && !strcmp(pmap->iananame, frame->pmap->iananame)) { payload = pmap->recv_pt;