[Freeswitch-svn] [commit] r4464 - in freeswitch/trunk/src: . include mod/endpoints/mod_dingaling mod/endpoints/mod_sofia mod/xml_int/mod_xml_rpc

Freeswitch SVN anthm at freeswitch.org
Wed Mar 7 13:34:22 EST 2007


Author: anthm
Date: Wed Mar  7 13:34:22 2007
New Revision: 4464

Modified:
   freeswitch/trunk/src/include/switch.h
   freeswitch/trunk/src/include/switch_core.h
   freeswitch/trunk/src/include/switch_loadable_module.h
   freeswitch/trunk/src/include/switch_module_interfaces.h
   freeswitch/trunk/src/include/switch_rtp.h
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
   freeswitch/trunk/src/switch_core.c
   freeswitch/trunk/src/switch_loadable_module.c
   freeswitch/trunk/src/switch_rtp.c

Log:
add management interface and some rtp goodies

Modified: freeswitch/trunk/src/include/switch.h
==============================================================================
--- freeswitch/trunk/src/include/switch.h	(original)
+++ freeswitch/trunk/src/include/switch.h	Wed Mar  7 13:34:22 2007
@@ -47,6 +47,10 @@
 #include <switch_am_config.h>
 #endif
 
+#define FREESWITCH_PEN "27880"
+#define FREESWITCH_MIB ".1.3.6.1.4.1." FREESWITCH_PEN
+#define FREESWITCH_ITAD "543"
+
 #include <switch_platform.h>
 #include <assert.h>
 #include <setjmp.h>

Modified: freeswitch/trunk/src/include/switch_core.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core.h	(original)
+++ freeswitch/trunk/src/include/switch_core.h	Wed Mar  7 13:34:22 2007
@@ -1405,6 +1405,19 @@
 */
 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

Modified: freeswitch/trunk/src/include/switch_loadable_module.h
==============================================================================
--- freeswitch/trunk/src/include/switch_loadable_module.h	(original)
+++ freeswitch/trunk/src/include/switch_loadable_module.h	Wed Mar  7 13:34:22 2007
@@ -76,9 +76,11 @@
 	/*! 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_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

Modified: freeswitch/trunk/src/include/switch_module_interfaces.h
==============================================================================
--- freeswitch/trunk/src/include/switch_module_interfaces.h	(original)
+++ freeswitch/trunk/src/include/switch_module_interfaces.h	Wed Mar  7 13:34:22 2007
@@ -430,6 +430,15 @@
 	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 */

Modified: freeswitch/trunk/src/include/switch_rtp.h
==============================================================================
--- freeswitch/trunk/src/include/switch_rtp.h	(original)
+++ freeswitch/trunk/src/include/switch_rtp.h	Wed Mar  7 13:34:22 2007
@@ -376,6 +376,13 @@
 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
   \return the pointer to the private data

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Wed Mar  7 13:34:22 2007
@@ -187,6 +187,11 @@
 	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 @@
 #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 @@
 	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 @@
 	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
 </pre>
  */
 typedef enum {
@@ -324,7 +332,8 @@
 	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_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);

Modified: freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	Wed Mar  7 13:34:22 2007
@@ -753,6 +753,8 @@
 	  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 @@
 
 	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;
 	}

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	Wed Mar  7 13:34:22 2007
@@ -252,6 +252,7 @@
 	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 @@
 	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 @@
 		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 @@
 		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 @@
 	} 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 @@
         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 @@
                               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 @@
 #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 @@
 			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 @@
 						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 @@
 					}
 				}
 
+                if (!profile->cng_pt) {
+					profile->cng_pt = 127;
+				}
+
                 if (!profile->sipip) {
                     profile->sipip = switch_core_strdup(profile->pool, globals.guess_ip);
                 }

Modified: freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
==============================================================================
--- freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c	(original)
+++ freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c	Wed Mar  7 13:34:22 2007
@@ -197,13 +197,13 @@
     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 @@
         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 @@
 	
     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");

Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Wed Mar  7 13:34:22 2007
@@ -447,6 +447,23 @@
 	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;

Modified: freeswitch/trunk/src/switch_loadable_module.c
==============================================================================
--- freeswitch/trunk/src/switch_loadable_module.c	(original)
+++ freeswitch/trunk/src/switch_loadable_module.c	Wed Mar  7 13:34:22 2007
@@ -55,6 +55,7 @@
 	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 @@
 			}
 		}
 	}
+
+	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_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 @@
 	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)
 {

Modified: freeswitch/trunk/src/switch_rtp.c
==============================================================================
--- freeswitch/trunk/src/switch_rtp.c	(original)
+++ freeswitch/trunk/src/switch_rtp.c	Wed Mar  7 13:34:22 2007
@@ -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 @@
 	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_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 @@
 };
 
 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_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 @@
 			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 @@
 
 		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 @@
 	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 @@
 		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 @@
 
 		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;
 		}



More information about the Freeswitch-svn mailing list