forked from Mirrors/freeswitch
add new stub module mod_rtc dummy signaling-free media engine endpoint
This commit is contained in:
parent
94921247d5
commit
5138f4d5a7
|
@ -82,6 +82,7 @@ dialplans/mod_dialplan_xml
|
|||
#endpoints/mod_gsmopen
|
||||
#endpoints/mod_h323
|
||||
#endpoints/mod_khomp
|
||||
endpoints/mod_rtc
|
||||
endpoints/mod_loopback
|
||||
#endpoints/mod_opal
|
||||
#endpoints/mod_portaudio
|
||||
|
|
|
@ -1499,6 +1499,7 @@ AC_CONFIG_FILES([Makefile
|
|||
src/mod/endpoints/mod_skypopen/Makefile
|
||||
src/mod/endpoints/mod_sofia/Makefile
|
||||
src/mod/endpoints/mod_unicall/Makefile
|
||||
src/mod/endpoints/mod_rtc/Makefile
|
||||
src/mod/event_handlers/mod_cdr_csv/Makefile
|
||||
src/mod/event_handlers/mod_cdr_mongodb/Makefile
|
||||
src/mod/event_handlers/mod_cdr_pg_csv/Makefile
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
include $(top_srcdir)/build/modmake.rulesam
|
||||
MODNAME=mod_rtc
|
||||
|
||||
mod_LTLIBRARIES = mod_rtc.la
|
||||
mod_rtc_la_SOURCES = mod_rtc.c
|
||||
mod_rtc_la_CFLAGS = $(AM_CFLAGS)
|
||||
mod_rtc_la_LIBADD = $(switch_builddir)/libfreeswitch.la
|
||||
mod_rtc_la_LDFLAGS = -avoid-version -module -no-undefined -shared
|
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
*
|
||||
* mod_rtc.c -- RTC Endpoint
|
||||
*
|
||||
*/
|
||||
|
||||
/* Best viewed in a 160 x 60 VT100 Terminal or so the line below at least fits across your screen*/
|
||||
/*************************************************************************************************************************************************************/
|
||||
#include <switch.h>
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_rtc_load);
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_rtc_shutdown);
|
||||
SWITCH_MODULE_DEFINITION(mod_rtc, mod_rtc_load, mod_rtc_shutdown, NULL);
|
||||
|
||||
|
||||
switch_endpoint_interface_t *rtc_endpoint_interface;
|
||||
|
||||
#define STRLEN 15
|
||||
|
||||
static switch_status_t rtc_on_init(switch_core_session_t *session);
|
||||
|
||||
static switch_status_t rtc_on_exchange_media(switch_core_session_t *session);
|
||||
static switch_status_t rtc_on_soft_execute(switch_core_session_t *session);
|
||||
static switch_call_cause_t rtc_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
|
||||
switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session,
|
||||
switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
|
||||
static switch_status_t rtc_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
|
||||
static switch_status_t rtc_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
|
||||
static switch_status_t rtc_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
|
||||
static switch_status_t rtc_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
|
||||
static switch_status_t rtc_kill_channel(switch_core_session_t *session, int sig);
|
||||
|
||||
typedef struct {
|
||||
switch_channel_t *channel;
|
||||
switch_core_session_t *session;
|
||||
switch_caller_profile_t *caller_profile;
|
||||
switch_media_handle_t *media_handle;
|
||||
switch_core_media_params_t mparams;
|
||||
} private_object_t;
|
||||
|
||||
static struct {
|
||||
switch_memory_pool_t *pool;
|
||||
switch_mutex_t *mutex;
|
||||
int running;
|
||||
} mod_rtc_globals;
|
||||
|
||||
|
||||
/* BODY OF THE MODULE */
|
||||
/*************************************************************************************************************************************************************/
|
||||
|
||||
/*
|
||||
State methods they get called when the state changes to the specific state
|
||||
returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
|
||||
so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
|
||||
*/
|
||||
static switch_status_t rtc_on_init(switch_core_session_t *session)
|
||||
{
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t rtc_on_routing(switch_core_session_t *session)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s RTC ROUTING\n",
|
||||
switch_channel_get_name(switch_core_session_get_channel(session)));
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t rtc_on_reset(switch_core_session_t *session)
|
||||
{
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s RTC RESET\n",
|
||||
switch_channel_get_name(switch_core_session_get_channel(session)));
|
||||
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t rtc_on_hibernate(switch_core_session_t *session)
|
||||
{
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s RTC HIBERNATE\n",
|
||||
switch_channel_get_name(switch_core_session_get_channel(session)));
|
||||
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t rtc_on_execute(switch_core_session_t *session)
|
||||
{
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s RTC EXECUTE\n",
|
||||
switch_channel_get_name(switch_core_session_get_channel(session)));
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
switch_status_t rtc_on_destroy(switch_core_session_t *session)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s RTC DESTROY\n", switch_channel_get_name(channel));
|
||||
switch_media_handle_destroy(session);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
switch_status_t rtc_on_hangup(switch_core_session_t *session)
|
||||
{
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t rtc_on_exchange_media(switch_core_session_t *session)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "RTC EXCHANGE_MEDIA\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t rtc_on_soft_execute(switch_core_session_t *session)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "RTC SOFT_EXECUTE\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t rtc_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
|
||||
{
|
||||
return switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_VIDEO);
|
||||
}
|
||||
|
||||
static switch_status_t rtc_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
|
||||
{
|
||||
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
|
||||
switch_assert(tech_pvt != NULL);
|
||||
|
||||
|
||||
if (SWITCH_STATUS_SUCCESS == switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_VIDEO)) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
static switch_status_t rtc_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
status = switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_AUDIO);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t rtc_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
status = switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_AUDIO);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t rtc_kill_channel(switch_core_session_t *session, int sig)
|
||||
{
|
||||
private_object_t *tech_pvt = switch_core_session_get_private(session);
|
||||
|
||||
if (!tech_pvt) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch (sig) {
|
||||
case SWITCH_SIG_BREAK:
|
||||
if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
|
||||
switch_core_media_break(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
|
||||
}
|
||||
if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO)) {
|
||||
switch_core_media_break(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO);
|
||||
}
|
||||
break;
|
||||
case SWITCH_SIG_KILL:
|
||||
default:
|
||||
|
||||
if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
|
||||
switch_core_media_kill_socket(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
|
||||
}
|
||||
if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO)) {
|
||||
switch_core_media_kill_socket(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t rtc_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
|
||||
{
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t rtc_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
private_object_t *tech_pvt = switch_core_session_get_private(session);
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
const char *var;
|
||||
|
||||
if (switch_channel_down(channel) || !tech_pvt) {
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* ones that do not need to lock rtp mutex */
|
||||
switch (msg->message_id) {
|
||||
|
||||
case SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS:
|
||||
break;
|
||||
case SWITCH_MESSAGE_INDICATE_ANSWER:
|
||||
case SWITCH_MESSAGE_INDICATE_PROGRESS:
|
||||
{
|
||||
|
||||
if (((var = switch_channel_get_variable(channel, "rtp_secure_media"))) &&
|
||||
(switch_true(var) || switch_core_media_crypto_str2type(var) != CRYPTO_INVALID)) {
|
||||
switch_channel_set_flag(tech_pvt->channel, CF_SECURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
static switch_status_t rtc_receive_event(switch_core_session_t *session, switch_event_t *event)
|
||||
{
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_io_routines_t rtc_io_routines = {
|
||||
/*.outgoing_channel */ rtc_outgoing_channel,
|
||||
/*.read_frame */ rtc_read_frame,
|
||||
/*.write_frame */ rtc_write_frame,
|
||||
/*.kill_channel */ rtc_kill_channel,
|
||||
/*.send_dtmf */ rtc_send_dtmf,
|
||||
/*.receive_message */ rtc_receive_message,
|
||||
/*.receive_event */ rtc_receive_event,
|
||||
/*.state_change */ NULL,
|
||||
/*.read_video_frame */ rtc_read_video_frame,
|
||||
/*.write_video_frame */ rtc_write_video_frame,
|
||||
/*.state_run*/ NULL,
|
||||
/*.get_jb*/ NULL
|
||||
};
|
||||
|
||||
switch_state_handler_table_t rtc_event_handlers = {
|
||||
/*.on_init */ rtc_on_init,
|
||||
/*.on_routing */ rtc_on_routing,
|
||||
/*.on_execute */ rtc_on_execute,
|
||||
/*.on_hangup */ rtc_on_hangup,
|
||||
/*.on_exchange_media */ rtc_on_exchange_media,
|
||||
/*.on_soft_execute */ rtc_on_soft_execute,
|
||||
/*.on_consume_media */ NULL,
|
||||
/*.on_hibernate */ rtc_on_hibernate,
|
||||
/*.on_reset */ rtc_on_reset,
|
||||
/*.on_park */ NULL,
|
||||
/*.on_reporting */ NULL,
|
||||
/*.on_destroy */ rtc_on_destroy
|
||||
};
|
||||
|
||||
|
||||
void rtc_set_name(private_object_t *tech_pvt, const char *channame)
|
||||
{
|
||||
char name[256];
|
||||
|
||||
switch_snprintf(name, sizeof(name), "rtc/%s", channame);
|
||||
switch_channel_set_name(tech_pvt->channel, name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void rtc_attach_private(switch_core_session_t *session, private_object_t *tech_pvt, const char *channame)
|
||||
{
|
||||
|
||||
switch_assert(session != NULL);
|
||||
switch_assert(tech_pvt != NULL);
|
||||
|
||||
switch_core_session_add_stream(session, NULL);
|
||||
|
||||
tech_pvt->session = session;
|
||||
tech_pvt->channel = switch_core_session_get_channel(session);
|
||||
switch_core_media_check_dtmf_type(session);
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_JITTERBUFFER);
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_FS_RTP);
|
||||
switch_media_handle_create(&tech_pvt->media_handle, session, &tech_pvt->mparams);
|
||||
switch_core_session_set_private(session, tech_pvt);
|
||||
|
||||
if (channame) {
|
||||
rtc_set_name(tech_pvt, channame);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private_object_t *rtc_new_pvt(switch_core_session_t *session)
|
||||
{
|
||||
private_object_t *tech_pvt = (private_object_t *) switch_core_session_alloc(session, sizeof(private_object_t));
|
||||
return tech_pvt;
|
||||
}
|
||||
|
||||
static switch_call_cause_t rtc_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
|
||||
switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session,
|
||||
switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
|
||||
{
|
||||
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||
switch_core_session_t *nsession = NULL;
|
||||
switch_caller_profile_t *caller_profile = NULL;
|
||||
private_object_t *tech_pvt = NULL;
|
||||
switch_channel_t *nchannel;
|
||||
const char *hval = NULL;
|
||||
|
||||
*new_session = NULL;
|
||||
|
||||
|
||||
if (!(nsession = switch_core_session_request_uuid(rtc_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND,
|
||||
flags, pool, switch_event_get_header(var_event, "origination_uuid")))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
tech_pvt = rtc_new_pvt(nsession);
|
||||
|
||||
nchannel = switch_core_session_get_channel(nsession);
|
||||
|
||||
if (outbound_profile) {
|
||||
caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
|
||||
switch_channel_set_caller_profile(nchannel, caller_profile);
|
||||
}
|
||||
|
||||
if ((hval = switch_event_get_header(var_event, "media_webrtc")) && switch_true(hval)) {
|
||||
switch_channel_set_variable(nchannel, "rtc_secure_media", SWITCH_RTP_CRYPTO_KEY_80);
|
||||
}
|
||||
|
||||
if ((hval = switch_event_get_header(var_event, "rtc_secure_media"))) {
|
||||
switch_channel_set_variable(nchannel, "rtc_secure_media", hval);
|
||||
}
|
||||
|
||||
rtc_attach_private(nsession, tech_pvt, NULL);
|
||||
|
||||
|
||||
if (switch_channel_get_state(nchannel) == CS_NEW) {
|
||||
switch_channel_set_state(nchannel, CS_INIT);
|
||||
}
|
||||
|
||||
tech_pvt->caller_profile = caller_profile;
|
||||
*new_session = nsession;
|
||||
cause = SWITCH_CAUSE_SUCCESS;
|
||||
|
||||
|
||||
if (session) {
|
||||
switch_ivr_transfer_variable(session, nsession, "rtc_video_fmtp");
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
error:
|
||||
|
||||
if (nsession) {
|
||||
switch_core_session_destroy(&nsession);
|
||||
}
|
||||
|
||||
if (pool) {
|
||||
*pool = NULL;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
return cause;
|
||||
}
|
||||
|
||||
static int rtc_recover_callback(switch_core_session_t *session)
|
||||
{
|
||||
private_object_t *tech_pvt = rtc_new_pvt(session);
|
||||
rtc_attach_private(session, tech_pvt, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_rtc_load)
|
||||
{
|
||||
memset(&mod_rtc_globals, 0, sizeof(mod_rtc_globals));
|
||||
mod_rtc_globals.pool = pool;
|
||||
switch_mutex_init(&mod_rtc_globals.mutex, SWITCH_MUTEX_NESTED, mod_rtc_globals.pool);
|
||||
|
||||
switch_mutex_lock(mod_rtc_globals.mutex);
|
||||
mod_rtc_globals.running = 1;
|
||||
switch_mutex_unlock(mod_rtc_globals.mutex);
|
||||
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
rtc_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
|
||||
rtc_endpoint_interface->interface_name = "rtc";
|
||||
rtc_endpoint_interface->io_routines = &rtc_io_routines;
|
||||
rtc_endpoint_interface->state_handler = &rtc_event_handlers;
|
||||
rtc_endpoint_interface->recover_callback = rtc_recover_callback;
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_rtc_shutdown)
|
||||
{
|
||||
switch_mutex_lock(mod_rtc_globals.mutex);
|
||||
if (mod_rtc_globals.running == 1) {
|
||||
mod_rtc_globals.running = 0;
|
||||
}
|
||||
switch_mutex_unlock(mod_rtc_globals.mutex);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
|
Loading…
Reference in New Issue