[Freeswitch-svn] [commit] r6658 - in freeswitch/trunk/src: . include mod/applications/mod_esf mod/endpoints/mod_dingaling mod/endpoints/mod_sofia

Freeswitch SVN anthm at freeswitch.org
Tue Dec 11 14:15:03 EST 2007


Author: anthm
Date: Tue Dec 11 14:15:02 2007
New Revision: 6658

Modified:
   freeswitch/trunk/src/include/switch_core.h
   freeswitch/trunk/src/include/switch_rtp.h
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/applications/mod_esf/mod_esf.c
   freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
   freeswitch/trunk/src/switch_core.c
   freeswitch/trunk/src/switch_core_port_allocator.c
   freeswitch/trunk/src/switch_rtp.c

Log:
add rtp port allocator

Modified: freeswitch/trunk/src/include/switch_core.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core.h	(original)
+++ freeswitch/trunk/src/include/switch_core.h	Tue Dec 11 14:15:02 2007
@@ -216,14 +216,16 @@
   \return SWITCH_STATUS_SUCCESS if the operation was a success
 */
 SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_new(switch_port_t start,
-															   switch_port_t end, uint8_t inc, switch_core_port_allocator_t **new_allocator);
+															   switch_port_t end, switch_port_flag_t flags, switch_core_port_allocator_t **new_allocator);
 
 /*!
   \brief Get a port from the port allocator
   \param alloc the allocator object
-  \return the port
+  \param port a pointer to the port
+  \return SUCCESS
 */
-SWITCH_DECLARE(switch_port_t) switch_core_port_allocator_request_port(switch_core_port_allocator_t *alloc);
+SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_request_port(switch_core_port_allocator_t *alloc, switch_port_t *port_ptr);
+SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_free_port(switch_core_port_allocator_t *alloc, switch_port_t port);
 
 /*!
   \brief destroythe port allocator

Modified: freeswitch/trunk/src/include/switch_rtp.h
==============================================================================
--- freeswitch/trunk/src/include/switch_rtp.h	(original)
+++ freeswitch/trunk/src/include/switch_rtp.h	Tue Dec 11 14:15:02 2007
@@ -53,6 +53,7 @@
   \note Generally called by the core_init
 */
 SWITCH_DECLARE(void) switch_rtp_init(switch_memory_pool_t *pool);
+SWITCH_DECLARE(void) switch_rtp_shutdown(void);
 
 /*!
   \brief Set/Get RTP start port
@@ -70,9 +71,10 @@
 
 /*! 
   \brief Request a new port to be used for media
+  \param ip the ip to request a port from
   \return the new port to use
 */
-SWITCH_DECLARE(switch_port_t) switch_rtp_request_port(void);
+SWITCH_DECLARE(switch_port_t) switch_rtp_request_port(const char *ip);
 
 /*! 
   \brief create a new RTP session handle

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Tue Dec 11 14:15:02 2007
@@ -137,6 +137,12 @@
 typedef uint8_t switch_byte_t;
 
 typedef enum {
+	SPF_NONE = 0,
+	SPF_ODD = (1 << 0),
+	SPF_EVEN = (1 << 1)
+} switch_port_flag_t;
+
+typedef enum {
 	ED_MUX_READ = (1 << 0),
 	ED_MUX_WRITE = (1 << 1),
 	ED_DTMF = (1 << 2)

Modified: freeswitch/trunk/src/mod/applications/mod_esf/mod_esf.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_esf/mod_esf.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_esf/mod_esf.c	Tue Dec 11 14:15:02 2007
@@ -153,7 +153,10 @@
 	}
 
 	if (ready == SEND_TYPE_RTP) {
-		rtp_port = switch_rtp_request_port();
+		if (!(rtp_port = switch_rtp_request_port(guess_ip))) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTP Port Error\n");
+			goto fail;
+		}
 		switch_find_local_ip(guess_ip, sizeof(guess_ip), AF_INET);
 		rtp_session = switch_rtp_new(guess_ip,
 									 rtp_port,

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	Tue Dec 11 14:15:02 2007
@@ -1697,7 +1697,11 @@
 			switch_core_session_set_private(*new_session, tech_pvt);
 			tech_pvt->session = *new_session;
 			tech_pvt->codec_index = -1;
-			tech_pvt->local_port = switch_rtp_request_port();
+			if (!(tech_pvt->local_port = switch_rtp_request_port(tech_pvt->profile->ip))) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No RTP port available!\n");
+				terminate_session(new_session, __LINE__, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+				return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+			}
 			tech_pvt->recip = switch_core_session_strdup(*new_session, full_id);
 			tech_pvt->dnis = switch_core_session_strdup(*new_session, dnis);
 		} else {
@@ -2584,7 +2588,12 @@
 				tech_pvt->session = session;
 				tech_pvt->codec_index = -1;
 				tech_pvt->profile = profile;
-				tech_pvt->local_port = switch_rtp_request_port();
+				if (!(tech_pvt->local_port = switch_rtp_request_port(profile->ip))) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No RTP port available!\n");
+					terminate_session(&session, __LINE__, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+					status = LDL_STATUS_FALSE;
+					goto done;
+				}
 				switch_set_flag_locked(tech_pvt, TFLAG_ANSWER);
 				tech_pvt->recip = switch_core_session_strdup(session, from);
 				if (!(exten = ldl_session_get_value(dlsession, "dnis"))) {

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	Tue Dec 11 14:15:02 2007
@@ -398,7 +398,10 @@
 	}
 
 	tech_pvt->local_sdp_audio_ip = ip;
-	tech_pvt->local_sdp_audio_port = switch_rtp_request_port();
+	if (!(tech_pvt->local_sdp_audio_port = switch_rtp_request_port(tech_pvt->profile->rtpip))) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No RTP ports available!\n");
+		return SWITCH_STATUS_FALSE;
+	}
 	sdp_port = tech_pvt->local_sdp_audio_port;
 
 	if (tech_pvt->profile->extrtpip) {
@@ -428,7 +431,10 @@
 		return SWITCH_STATUS_SUCCESS;
 	}
 
-	tech_pvt->local_sdp_video_port = switch_rtp_request_port();
+	if (!(tech_pvt->local_sdp_video_port = switch_rtp_request_port(tech_pvt->profile->rtpip))) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No RTP ports available!\n");
+		return SWITCH_STATUS_FALSE;
+	}
 	sdp_port = tech_pvt->local_sdp_video_port;
 
 	if (tech_pvt->profile->extrtpip) {

Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Tue Dec 11 14:15:02 2007
@@ -994,13 +994,12 @@
 	}
 	switch_scheduler_task_thread_stop();
 
+	switch_rtp_shutdown();
 	switch_xml_destroy();
 	switch_core_memory_stop();
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n");
 	switch_log_shutdown();
 
-
-
 	if (runtime.console && runtime.console != stdout && runtime.console != stderr) {
 		fclose(runtime.console);
 		runtime.console = NULL;
@@ -1028,6 +1027,18 @@
 	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(void) switch_core_memory_reclaim_all(void)
 {
 	switch_core_memory_reclaim_logger();	

Modified: freeswitch/trunk/src/switch_core_port_allocator.c
==============================================================================
--- freeswitch/trunk/src/switch_core_port_allocator.c	(original)
+++ freeswitch/trunk/src/switch_core_port_allocator.c	Tue Dec 11 14:15:02 2007
@@ -38,18 +38,21 @@
 	switch_port_t start;
 	switch_port_t end;
 	switch_port_t next;
-	uint8_t inc;
+	switch_byte_t *track;
+	uint32_t track_len;
+	uint32_t track_used;
+	switch_port_flag_t flags;
 	switch_mutex_t *mutex;
 	switch_memory_pool_t *pool;
 };
 
 SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_new(switch_port_t start,
-															   switch_port_t end, uint8_t inc, switch_core_port_allocator_t **new_allocator)
+															   switch_port_t end, switch_port_flag_t flags, switch_core_port_allocator_t **new_allocator)
 {
 	switch_status_t status;
 	switch_memory_pool_t *pool;
 	switch_core_port_allocator_t *alloc;
-
+	
 	if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) {
 		return status;
 	}
@@ -58,13 +61,21 @@
 		switch_core_destroy_memory_pool(&pool);
 		return SWITCH_STATUS_MEMERR;
 	}
+	
+	alloc->track_len = (end - start) + 2;
+	alloc->flags = flags;
+
+	if (!(switch_test_flag(alloc, SPF_EVEN) && switch_test_flag(alloc, SPF_ODD))) {
+		alloc->track_len /= 2;
+	}
+
+	alloc->track = switch_core_alloc(pool, (alloc->track_len + 2) * sizeof(switch_byte_t));
 
 	alloc->start = start;
 	alloc->next = start;
 	alloc->end = end;
-	if (!(alloc->inc = inc)) {
-		alloc->inc = 2;
-	}
+
+
 	switch_mutex_init(&alloc->mutex, SWITCH_MUTEX_NESTED, pool);
 	alloc->pool = pool;
 	*new_allocator = alloc;
@@ -72,34 +83,89 @@
 	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)
+
+SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_request_port(switch_core_port_allocator_t *alloc, switch_port_t *port_ptr)
 {
-	const switch_management_interface_t *ptr;
+	switch_port_t port = 0;
 	switch_status_t status = SWITCH_STATUS_FALSE;
+	int even = switch_test_flag(alloc, SPF_EVEN);
+	int odd = switch_test_flag(alloc, SPF_ODD);
+
+	switch_mutex_lock(alloc->mutex);
+	srand(getpid() + time(NULL));
+	
+	while(alloc->track_used < alloc->track_len) {
+		double r;
+		int index;
+		int tries = 0;
+
+		do {
+			r = ((double)rand() / ((double)(RAND_MAX)+(double)(1)));
+			index = (int) (r * alloc->track_len);
+			tries++;
+		} while((alloc->track[index] || index >= alloc->track_len) && tries < 10000);
+		
+		while(alloc->track[index]) {
+			if (++index >= alloc->track_len) {
+				index = 0;
+			}
+		}
+
+		if (index < alloc->track_len) {
+			alloc->track[index] = 1;
+			alloc->track_used++;
+			status = SWITCH_STATUS_SUCCESS;
+
+			if ((even && odd)) {
+				port = index + alloc->start;
+			} else {
+				port = index + (alloc->start / 2);
+				port *= 2;
+			} 
+			goto end;
+		}
+	}
+	
+	
+ end:
 
-	if ((ptr = switch_loadable_module_get_management_interface(relative_oid))) {
-		status = ptr->management_function(relative_oid, action, data, datalen);
+	switch_mutex_unlock(alloc->mutex);
+	
+	if (status == SWITCH_STATUS_SUCCESS) {
+		*port_ptr = port;
+	} else {
+		*port_ptr = 0;
 	}
 
+	
 	return status;
+	
 }
 
 
-
-SWITCH_DECLARE(switch_port_t) switch_core_port_allocator_request_port(switch_core_port_allocator_t *alloc)
+SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_free_port(switch_core_port_allocator_t *alloc, switch_port_t port)
 {
-	switch_port_t port;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+	int even = switch_test_flag(alloc, SPF_EVEN);
+	int odd = switch_test_flag(alloc, SPF_ODD);
+	int index = port - alloc->start;
+	
+	if (!(even && odd)) {
+		index /= 2;
+	}
 
 	switch_mutex_lock(alloc->mutex);
-	port = alloc->next;
-	alloc->next = alloc->next + alloc->inc;
-	if (alloc->next > alloc->end) {
-		alloc->next = alloc->start;
+	if (alloc->track[index]) {
+		alloc->track[index] = 0;
+		alloc->track_used--;
+		status = SWITCH_STATUS_SUCCESS;
 	}
 	switch_mutex_unlock(alloc->mutex);
-	return port;
+
+	return status;
 }
 
+
 SWITCH_DECLARE(void) switch_core_port_allocator_destroy(switch_core_port_allocator_t **alloc)
 {
 	switch_memory_pool_t *pool = (*alloc)->pool;

Modified: freeswitch/trunk/src/switch_rtp.c
==============================================================================
--- freeswitch/trunk/src/switch_rtp.c	(original)
+++ freeswitch/trunk/src/switch_rtp.c	Tue Dec 11 14:15:02 2007
@@ -67,7 +67,7 @@
 #pragma pack()
 #endif
 
-
+static switch_hash_t *alloc_hash = NULL;
 
 typedef struct {
 	srtp_hdr_t header;
@@ -147,7 +147,8 @@
 	uint32_t flags;
 	switch_memory_pool_t *pool;
 	switch_sockaddr_t *from_addr;
-
+	char *rx_host;
+	switch_port_t rx_port;
 	char *ice_user;
 	char *user_ice;
 	char *timer_name;
@@ -261,12 +262,17 @@
 	if (global_init) {
 		return;
 	}
-
+	switch_core_hash_init(&alloc_hash, pool);
 	srtp_init();
 	switch_mutex_init(&port_lock, SWITCH_MUTEX_NESTED, pool);
 	global_init = 1;
 }
 
+SWITCH_DECLARE(void) switch_rtp_shutdown(void)
+{
+	switch_core_hash_destroy(&alloc_hash);
+}
+
 SWITCH_DECLARE(switch_port_t) switch_rtp_set_start_port(switch_port_t port)
 {
 	if (port) {
@@ -304,16 +310,43 @@
         return END_PORT;
 }
 
-SWITCH_DECLARE(switch_port_t) switch_rtp_request_port(void)
+static void release_port(switch_rtp_t *rtp_session)
 {
-	switch_port_t port;
+	switch_core_port_allocator_t *alloc = NULL;
 
+	if (!rtp_session->rx_host) {
+		return;
+	}
+
+    switch_mutex_lock(port_lock);
+    if ((alloc = switch_core_hash_find(alloc_hash, rtp_session->rx_host))) {
+		switch_core_port_allocator_free_port(alloc, rtp_session->rx_port);
+	}
+	switch_mutex_unlock(port_lock);
+
+}
+
+SWITCH_DECLARE(switch_port_t) switch_rtp_request_port(const char *ip)
+{
+	switch_port_t port = 0;
+	switch_core_port_allocator_t *alloc = NULL;
+	
 	switch_mutex_lock(port_lock);
-	port = NEXT_PORT;
-	NEXT_PORT += 2;
-	if (NEXT_PORT > END_PORT) {
-		NEXT_PORT = START_PORT;
+	alloc = switch_core_hash_find(alloc_hash, ip);
+	if (!alloc) {
+		if (switch_core_port_allocator_new(START_PORT, END_PORT, SPF_EVEN, &alloc) != SWITCH_STATUS_SUCCESS) {
+			port = 0;
+			goto end;
+		}
+
+		switch_core_hash_insert(alloc_hash, ip, alloc);
+	}
+	
+	if (switch_core_port_allocator_request_port(alloc, &port) != SWITCH_STATUS_SUCCESS) {
+		port = 0;
 	}
+
+ end:
 	switch_mutex_unlock(port_lock);
 	return port;
 }
@@ -379,7 +412,8 @@
 		*err = "Send myself a packet failed!";
 		goto done;
 	}
-
+	release_port(rtp_session);
+	
 	old_sock = rtp_session->sock;
 	rtp_session->sock = new_sock;
 	new_sock = NULL;
@@ -395,7 +429,9 @@
 
   done:
 
-	if (status != SWITCH_STATUS_SUCCESS) {
+	if (status == SWITCH_STATUS_SUCCESS) {
+		rtp_session->rx_host = switch_core_strdup(rtp_session->pool, host);
+		rtp_session->rx_port = port;
 		rtp_session->ready = 1;
 	}
 
@@ -653,6 +689,7 @@
 		return;
 	}
 
+
 	(*rtp_session)->ready = 0;
 
 	switch_mutex_lock((*rtp_session)->flag_mutex);
@@ -683,6 +720,8 @@
 		switch_core_timer_destroy(&(*rtp_session)->timer);
 	}
 
+	release_port(*rtp_session);
+
 	switch_mutex_unlock((*rtp_session)->flag_mutex);
 	return;
 }



More information about the Freeswitch-svn mailing list