From 5131ee1cae07709b9c17dbe0393cd3a827b81112 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 7 Mar 2007 18:34:22 +0000 Subject: [PATCH] add management interface and some rtp goodies git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4464 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch.h | 4 + src/include/switch_core.h | 13 ++++ src/include/switch_loadable_module.h | 10 ++- src/include/switch_module_interfaces.h | 9 +++ src/include/switch_rtp.h | 7 ++ src/include/switch_types.h | 14 +++- .../endpoints/mod_dingaling/mod_dingaling.c | 4 +- src/mod/endpoints/mod_sofia/mod_sofia.c | 42 ++++++++++- src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c | 75 ++++++++++++++++--- src/switch_core.c | 17 +++++ src/switch_loadable_module.c | 25 +++++++ src/switch_rtp.c | 46 ++++++++++-- 12 files changed, 242 insertions(+), 24 deletions(-) diff --git a/src/include/switch.h b/src/include/switch.h index 7a19d23116..954ad3bd04 100644 --- a/src/include/switch.h +++ b/src/include/switch.h @@ -47,6 +47,10 @@ #include #endif +#define FREESWITCH_PEN "27880" +#define FREESWITCH_MIB ".1.3.6.1.4.1." FREESWITCH_PEN +#define FREESWITCH_ITAD "543" + #include #include #include diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 3e79e238e1..e784f427ce 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1405,6 +1405,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_directory_close(switch_directory_han */ SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel); +/*! + \brief Execute a management operation. + \param relative_oid the relative oid of the operation. + \param action the action to perform. + \param data input/output string. + \param datalen size in bytes of data. + \return SUCCESS on sucess. +*/ +SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, + switch_management_action_t action, + char *data, + switch_size_t datalen); + /*! \brief Set the maximum priority the process can obtain diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h index 7b9c8b384e..e66b35c65a 100644 --- a/src/include/switch_loadable_module.h +++ b/src/include/switch_loadable_module.h @@ -76,9 +76,11 @@ struct switch_loadable_module_interface { /*! the table of chat interfaces the module has implmented */ const switch_chat_interface_t *chat_interface; /*! the table of say interfaces the module has implmented */ - const switch_say_interface_t *say_interface; + const switch_say_interface_t *say_interface; /*! the table of asr interfaces the module has implmented */ const switch_asr_interface_t *asr_interface; + /*! the table of management interfaces the module has implmented */ + const switch_management_interface_t *management_interface; }; /*! @@ -190,6 +192,12 @@ SWITCH_DECLARE(switch_chat_interface_t *) switch_loadable_module_get_chat_interf */ SWITCH_DECLARE(switch_say_interface_t *) switch_loadable_module_get_say_interface(char *name); +/*! + \brief Retrieve the management interface by it's registered name + \param relative_oid the relative oid of the management interface + \return the desired management interface + */ +SWITCH_DECLARE(switch_management_interface_t *) switch_loadable_module_get_management_interface(char *relative_oid); /*! \brief Retrieve the list of loaded codecs into an array diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index b9576372bf..c7ee72fe5e 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -430,6 +430,15 @@ struct switch_chat_interface { const struct switch_chat_interface *next; }; +/*! \brief Abstract interface to a management module */ +struct switch_management_interface { + /*! the name of the interface */ + const char *relative_oid; + /*! function to open the directory interface */ + switch_status_t (*management_function)(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen); + const struct switch_management_interface *next; +}; + /*! \brief Abstract interface to a directory module */ struct switch_directory_interface { /*! the name of the interface */ diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 182889fc59..6f83f33757 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -375,6 +375,13 @@ SWITCH_DECLARE(void) switch_rtp_set_private(switch_rtp_t *rtp_session, void *pri */ SWITCH_DECLARE(void) switch_rtp_set_telephony_event(switch_rtp_t *rtp_session, switch_payload_t te); +/*! + \brief Set the payload type for comfort noise + \param rtp_session the RTP session to modify + \param pt the payload type +*/ +SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_payload_t pt); + /*! \brief Retrieve the private data from a given RTP session \param rtp_session the RTP session to retrieve the data from diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 5fac010ec2..ab2b10b024 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -187,6 +187,11 @@ typedef enum { SST_NAME_PHONETIC, } switch_say_type_t; +typedef enum { + SMA_NONE, + SMA_GET, + SMA_SET +} switch_management_action_t; typedef enum { SMF_NONE = 0, @@ -248,6 +253,7 @@ SWITCH_DECLARE_DATA extern switch_directories SWITCH_GLOBAL_dirs; #define SWITCH_TRUE 1 #define SWITCH_FALSE 0 #define SWITCH_CORE_QUEUE_LEN 100000 +#define SWITCH_MAX_MANAGEMENT_BUFFER_LEN 1024 * 8 typedef enum { SWITCH_CPF_SCREEN = (1 << 0), @@ -289,6 +295,7 @@ typedef enum { SWITCH_VAD_FLAG_CNG = ( 1 << 3) } switch_vad_flag_t; +#define SWITCH_RTP_CNG_PAYLOAD 13 /*! \enum switch_rtp_flag_t @@ -307,7 +314,8 @@ typedef enum { SWITCH_RTP_FLAG_MINI - Use mini RTP when possible SWITCH_RTP_FLAG_DATAWAIT - Do not return from reads unless there is data even when non blocking SWITCH_RTP_FLAG_BUGGY_2833 - Emulate the bug in cisco equipment to allow interop - SWITCH_RTP_FLAG_PASS_RFC2833 - Pass 2833 (ignore it) + SWITCH_RTP_FLAG_PASS_RFC2833 - Pass 2833 (ignore it) + SWITCH_RTP_FLAG_AUTO_CNG - Generate outbound CNG frames when idle */ typedef enum { @@ -324,7 +332,8 @@ typedef enum { SWITCH_RTP_FLAG_MINI = ( 1 << 10), SWITCH_RTP_FLAG_DATAWAIT = (1 << 11), SWITCH_RTP_FLAG_BUGGY_2833 = (1 << 12), - SWITCH_RTP_FLAG_PASS_RFC2833 = (1 << 13) + SWITCH_RTP_FLAG_PASS_RFC2833 = (1 << 13), + SWITCH_RTP_FLAG_AUTO_CNG = (1 << 14) } switch_rtp_flag_t; /*! @@ -985,6 +994,7 @@ typedef struct switch_speech_interface switch_speech_interface_t; typedef struct switch_asr_interface switch_asr_interface_t; typedef struct switch_directory_interface switch_directory_interface_t; typedef struct switch_chat_interface switch_chat_interface_t; +typedef struct switch_management_interface switch_management_interface_t; typedef struct switch_core_port_allocator switch_core_port_allocator_t; typedef struct switch_media_bug switch_media_bug_t; typedef void (*switch_media_bug_callback_t)(switch_media_bug_t *, void *, switch_abc_type_t); diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 4477e7ffaf..0fe30287f7 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -753,6 +753,8 @@ static int activate_rtp(struct private_object *tech_pvt) flags |= SWITCH_RTP_FLAG_USE_TIMER; } + flags |= SWITCH_RTP_FLAG_AUTO_CNG; + if (!(tech_pvt->rtp_session = switch_rtp_new(tech_pvt->profile->ip, tech_pvt->local_port, tech_pvt->remote_ip, @@ -1357,7 +1359,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc samples = frames * tech_pvt->read_codec.implementation->samples_per_frame; tech_pvt->timestamp_send += samples; - if (switch_rtp_write_frame(tech_pvt->rtp_session, frame, tech_pvt->timestamp_send) < 0) { + if (switch_rtp_write_frame(tech_pvt->rtp_session, frame, 0) < 0) { terminate_session(&session, __LINE__, SWITCH_CAUSE_NORMAL_CLEARING); return SWITCH_STATUS_FALSE; } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 6bf99d454a..8ebc5a0c1d 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -252,6 +252,7 @@ struct sofia_profile { su_root_t *s_root; sip_alias_node_t *aliases; switch_payload_t te; + switch_payload_t cng_pt; uint32_t codec_flags; switch_mutex_t *ireg_mutex; switch_mutex_t *oreg_mutex; @@ -319,6 +320,8 @@ struct private_object { switch_mutex_t *flag_mutex; switch_payload_t te; switch_payload_t bte; + switch_payload_t cng_pt; + switch_payload_t bcng_pt; nua_handle_t *nh; nua_handle_t *nh2; su_home_t *home; @@ -747,6 +750,14 @@ static void set_local_sdp(private_object_t *tech_pvt, char *ip, uint32_t port, c snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %d", tech_pvt->te); } + if (tech_pvt->read_codec.implementation->samples_per_second == 8000) { + tech_pvt->cng_pt = SWITCH_RTP_CNG_PAYLOAD; + } + + if (tech_pvt->cng_pt) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %d", tech_pvt->cng_pt); + } + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "\n"); if (tech_pvt->rm_encoding) { @@ -776,6 +787,8 @@ static void set_local_sdp(private_object_t *tech_pvt, char *ip, uint32_t port, c snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", tech_pvt->te, tech_pvt->te); } + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=rtpmap:%d CN/%d\n", tech_pvt->cng_pt, tech_pvt->read_codec.implementation->samples_per_second); + if (ptime) { snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=ptime:%d\n", ptime); } @@ -870,9 +883,16 @@ static void attach_private(switch_core_session_t *session, } else { tech_pvt->te = profile->te; } + + if (tech_pvt->bcng_pt) { + tech_pvt->cng_pt = tech_pvt->bcng_pt; + } else { + tech_pvt->cng_pt = profile->cng_pt; + } + tech_pvt->session = session; tech_pvt->home = su_home_new(sizeof(*tech_pvt->home)); - + switch_core_session_set_private(session, tech_pvt); @@ -1543,6 +1563,10 @@ static switch_status_t activate_rtp(private_object_t *tech_pvt) flags |= SWITCH_RTP_FLAG_PASS_RFC2833; } + if (tech_pvt->cng_pt) { + flags |= SWITCH_RTP_FLAG_AUTO_CNG; + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, @@ -1602,6 +1626,12 @@ static switch_status_t activate_rtp(private_object_t *tech_pvt) switch_channel_get_name(switch_core_session_get_channel(tech_pvt->session)), vad_in ? "in" : "", vad_out ? "out" : ""); } + + switch_rtp_set_telephony_event(tech_pvt->rtp_session, tech_pvt->te); + if (tech_pvt->cng_pt) { + switch_rtp_set_cng_pt(tech_pvt->rtp_session, tech_pvt->cng_pt); + } + } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTP REPORTS ERROR: [%s]\n", err); terminate_session(&tech_pvt->session, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, __LINE__); @@ -1881,7 +1911,8 @@ static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_ #endif tech_pvt->timestamp_send += samples; - switch_rtp_write_frame(tech_pvt->rtp_session, frame, tech_pvt->timestamp_send); + //switch_rtp_write_frame(tech_pvt->rtp_session, frame, tech_pvt->timestamp_send); + switch_rtp_write_frame(tech_pvt->rtp_session, frame, 0); switch_clear_flag_locked(tech_pvt, TFLAG_WRITING); return status; @@ -2347,6 +2378,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session ctech_pvt = switch_core_session_get_private(session); assert(ctech_pvt != NULL); tech_pvt->bte = ctech_pvt->te; + tech_pvt->bcng_pt = ctech_pvt->cng_pt; } } @@ -5181,6 +5213,8 @@ static switch_status_t config_sofia(int reload) switch_set_flag(profile, TFLAG_LATE_NEGOTIATION); } else if (!strcasecmp(var, "rfc2833-pt")) { profile->te = (switch_payload_t) atoi(val); + } else if (!strcasecmp(var, "cng-pt")) { + profile->cng_pt = (switch_payload_t) atoi(val); } else if (!strcasecmp(var, "sip-port")) { profile->sip_port = atoi(val); } else if (!strcasecmp(var, "vad")) { @@ -5270,6 +5304,10 @@ static switch_status_t config_sofia(int reload) } } + if (!profile->cng_pt) { + profile->cng_pt = 127; + } + if (!profile->sipip) { profile->sipip = switch_core_strdup(profile->pool, globals.guess_ip); } diff --git a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c index 417b481c63..eeff72777b 100644 --- a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c +++ b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c @@ -197,13 +197,13 @@ abyss_bool HandleHook(TSession *r) return TRUE; } -#define CMDLEN 1024 * 256 + static xmlrpc_value *freeswitch_api(xmlrpc_env *const envP, xmlrpc_value *const paramArrayP, void *const userData) { char *command, *arg; - char *retbuf = malloc(CMDLEN); switch_stream_handle_t stream = {0}; - xmlrpc_value *val; + xmlrpc_value *val = NULL; + /* Parse our argument array. */ xmlrpc_decompose_value(envP, paramArrayP, "(ss)", &command, &arg); @@ -211,16 +211,67 @@ static xmlrpc_value *freeswitch_api(xmlrpc_env *const envP, xmlrpc_value *const return NULL; } - memset(retbuf, 0, CMDLEN); - stream.data = retbuf; - stream.end = stream.data; - stream.data_size = CMDLEN; - stream.write_function = switch_console_stream_write; - switch_api_execute(command, arg, NULL, &stream); + SWITCH_STANDARD_STREAM(stream); + if (switch_api_execute(command, arg, NULL, &stream) == SWITCH_STATUS_SUCCESS) { + /* Return our result. */ + val = xmlrpc_build_value(envP, "s", stream.data); + free(stream.data); + } else { + val = xmlrpc_build_value(envP, "s", "ERROR!"); + } + + return val; +} + +static xmlrpc_value *freeswitch_man(xmlrpc_env *const envP, xmlrpc_value *const paramArrayP, void *const userData) +{ + char *oid, *relative_oid, *s_action, *data; + char buf[SWITCH_MAX_MANAGEMENT_BUFFER_LEN] = ""; + switch_management_action_t action = SMA_NONE; + switch_stream_handle_t stream = {0}; + xmlrpc_value *val; + + /* Parse our argument array. */ + xmlrpc_decompose_value(envP, paramArrayP, "(sss)", &oid, &s_action, &data); + if (envP->fault_occurred) { + return NULL; + } + + if (!strncasecmp(oid, FREESWITCH_MIB, strlen(FREESWITCH_MIB))) { + relative_oid = oid + strlen(FREESWITCH_MIB); + } else { + relative_oid = oid; + } + + if (!switch_strlen_zero(data)) { + switch_copy_string(buf, data, sizeof(buf)); + } + + if (!strcasecmp(s_action, "get")) { + action = SMA_GET; + } else if (!strcasecmp(s_action, "set")) { + action = SMA_SET; + } + + if (action) { + if (switch_core_management_exec(relative_oid, action, buf, sizeof(buf)) == SWITCH_STATUS_SUCCESS) { + if (action == SMA_SET) { + if (switch_strlen_zero(buf)) { + snprintf(buf, sizeof(buf), "OK\n"); + } + } + } else { + if (switch_strlen_zero(buf)) { + snprintf(buf, sizeof(buf), "ERROR\n"); + } + } + } else { + snprintf(buf, sizeof(buf), "Invalid Action %s\n", s_action); + } /* Return our result. */ - val = xmlrpc_build_value(envP, "s", retbuf); - free(retbuf); + val = xmlrpc_build_value(envP, "s", buf); + return val; } @@ -240,6 +291,8 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void) xmlrpc_registry_add_method(&env, registryP, NULL, "freeswitch.api", &freeswitch_api, NULL); xmlrpc_registry_add_method(&env, registryP, NULL,"freeswitch_api", &freeswitch_api, NULL); + xmlrpc_registry_add_method(&env, registryP, NULL, "freeswitch.management", &freeswitch_man, NULL); + xmlrpc_registry_add_method(&env, registryP, NULL,"freeswitch_management", &freeswitch_man, NULL); MIMETypeInit(); MIMETypeAdd("text/html", "html"); diff --git a/src/switch_core.c b/src/switch_core.c index 06b00efaa9..5f6e120db1 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -447,6 +447,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_new(switch_port_t sta return SWITCH_STATUS_SUCCESS; } +SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, + switch_management_action_t action, + char *data, + switch_size_t datalen) +{ + const switch_management_interface_t *ptr; + switch_status_t status = SWITCH_STATUS_FALSE; + + if ((ptr = switch_loadable_module_get_management_interface(relative_oid))) { + status = ptr->management_function(relative_oid, action, data, datalen); + } + + return status; +} + + + SWITCH_DECLARE(switch_port_t) switch_core_port_allocator_request_port(switch_core_port_allocator_t *alloc) { switch_port_t port; diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index 7f1788d565..8db5395c60 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -55,6 +55,7 @@ struct switch_loadable_module_container { switch_hash_t *directory_hash; switch_hash_t *chat_hash; switch_hash_t *say_hash; + switch_hash_t *management_hash; switch_memory_pool_t *pool; }; @@ -332,6 +333,24 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable } } } + + if (new_module->module_interface->management_interface) { + const switch_management_interface_t *ptr; + + for (ptr = new_module->module_interface->management_interface; ptr; ptr = ptr->next) { + if (!ptr->relative_oid) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load management interface from %s due to no interface name.\n", key); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Management interface '%s'\n", ptr->relative_oid); + if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "management"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->relative_oid); + switch_event_fire(&event); + } + switch_core_hash_insert(loadable_modules.management_hash, ptr->relative_oid, (const void *) ptr); + } + } + } return SWITCH_STATUS_SUCCESS; @@ -585,6 +604,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init() switch_core_hash_init(&loadable_modules.directory_hash, loadable_modules.pool); switch_core_hash_init(&loadable_modules.chat_hash, loadable_modules.pool); switch_core_hash_init(&loadable_modules.say_hash, loadable_modules.pool); + switch_core_hash_init(&loadable_modules.management_hash, loadable_modules.pool); switch_core_hash_init(&loadable_modules.dialplan_hash, loadable_modules.pool); if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) { @@ -767,6 +787,11 @@ SWITCH_DECLARE(switch_say_interface_t *) switch_loadable_module_get_say_interfac return switch_core_hash_find(loadable_modules.say_hash, name); } +SWITCH_DECLARE(switch_management_interface_t *) switch_loadable_module_get_management_interface(char *relative_oid) +{ + return switch_core_hash_find(loadable_modules.management_hash, relative_oid); +} + SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool, const switch_codec_implementation_t **array, int arraylen) { diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 8ec9a14b42..f7ceb0564b 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -46,7 +46,6 @@ #define rtp_header_len 12 #define RTP_START_PORT 16384 #define RTP_END_PORT 32768 -#define SWITCH_RTP_CNG_PAYLOAD 13 #define MAX_KEY_LEN 64 #define MASTER_KEY_LEN 30 #define RTP_MAGIC_NUMBER 42 @@ -131,11 +130,10 @@ struct switch_rtp { uint16_t rseq; switch_payload_t payload; switch_payload_t rpayload; - switch_rtp_invalid_handler_t invalid_handler; void *private_data; - uint32_t ts; + uint32_t auto_write_ts; uint32_t last_write_ts; uint16_t last_write_seq; uint32_t last_write_ssrc; @@ -157,6 +155,7 @@ struct switch_rtp { struct switch_rtp_vad_data vad_data; struct switch_rtp_rfc2833_data dtmf_data; switch_payload_t te; + switch_payload_t cng_pt; switch_mutex_t *flag_mutex; switch_timer_t timer; uint8_t ready; @@ -164,6 +163,7 @@ struct switch_rtp { }; static int global_init = 0; +static int rtp_common_write(switch_rtp_t *rtp_session, void *data, uint32_t datalen, uint8_t m, switch_payload_t payload, switch_frame_flag_t *flags); static switch_status_t ice_out(switch_rtp_t *rtp_session) { @@ -536,6 +536,13 @@ SWITCH_DECLARE(void) switch_rtp_set_telephony_event(switch_rtp_t *rtp_session, s } } +SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_payload_t pt) +{ + + rtp_session->cng_pt = pt; + +} + SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_session, char *login, char *rlogin) { char ice_user[80]; @@ -773,15 +780,16 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ switch_core_timer_step(&rtp_session->timer); } - if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BREAK)) { + if (!bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BREAK)) { switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK); - memset(&rtp_session->recv_msg, 0, SWITCH_RTP_CNG_PAYLOAD); + memset(&rtp_session->recv_msg.body, 0, 2); + rtp_session->recv_msg.body[0] = 127; rtp_session->recv_msg.header.pt = SWITCH_RTP_CNG_PAYLOAD; *flags |= SFF_CNG; /* Return a CNG frame */ *payload_type = SWITCH_RTP_CNG_PAYLOAD; - return SWITCH_RTP_CNG_PAYLOAD + rtp_header_len; + return 2 + rtp_header_len; } if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO)) { @@ -807,8 +815,25 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if (rtp_session->timer.interval) { check = (uint8_t)(switch_core_timer_check(&rtp_session->timer) == SWITCH_STATUS_SUCCESS); + + if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTO_CNG) && + rtp_session->timer.samplecount >= (rtp_session->auto_write_ts + (rtp_session->packet_size * 5))) { + uint8_t data[2] = {0}; + switch_frame_flag_t flags = SFF_NONE; + data[0] = 127; + + rtp_session->auto_write_ts = rtp_session->timer.samplecount; + rtp_session->seq = ntohs(rtp_session->seq) + 1; + rtp_session->seq = htons(rtp_session->seq); + rtp_session->send_msg.header.seq = rtp_session->seq; + rtp_session->send_msg.header.ts = htonl(rtp_session->auto_write_ts); + + rtp_common_write(rtp_session, (void *) data, sizeof(data), 0, rtp_session->cng_pt, &flags); + } } + + if (check) { do_2833(rtp_session); @@ -1047,6 +1072,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp frame->packetlen = bytes; frame->source = __FILE__; frame->flags |= SFF_RAW_RTP; + frame->timestamp = ntohl(rtp_session->recv_msg.header.ts); if (bytes < 0) { frame->datalen = 0; @@ -1309,7 +1335,11 @@ SWITCH_DECLARE(int) switch_rtp_write(switch_rtp_t *rtp_session, void *data, uint return -1; } - rtp_session->ts = ts; + if (!ts && rtp_session->timer.timer_interface) { + rtp_session->auto_write_ts = rtp_session->ts = rtp_session->timer.samplecount; + } else { + rtp_session->ts = ts; + } if (rtp_session->ts > rtp_session->last_write_ts + rtp_session->packet_size || rtp_session->ts == rtp_session->packet_size) { mark++; @@ -1345,6 +1375,8 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra if (frame->timestamp) { rtp_session->ts = (uint32_t) frame->timestamp; + } else if (!ts && rtp_session->timer.timer_interface) { + rtp_session->auto_write_ts = rtp_session->ts = rtp_session->timer.samplecount; } else { rtp_session->ts = ts; }