add rtp port allocator

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6658 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2007-12-11 19:15:02 +00:00
parent 4968e0f6a1
commit efb1b62938
9 changed files with 194 additions and 50 deletions

View File

@ -216,14 +216,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b
\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

View File

@ -53,6 +53,7 @@ typedef void (*switch_rtp_invalid_handler_t) (switch_rtp_t *rtp_session,
\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 @@ SWITCH_DECLARE(switch_port_t) switch_rtp_set_end_port(switch_port_t port);
/*!
\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

View File

@ -136,6 +136,12 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_BITS_PER_BYTE 8
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),

View File

@ -153,7 +153,10 @@ SWITCH_STANDARD_APP(bcast_function)
}
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,

View File

@ -1697,7 +1697,11 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
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 @@ static ldl_status handle_signalling(ldl_handle_t * handle, ldl_session_t * dlses
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"))) {

View File

@ -398,7 +398,10 @@ switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt)
}
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 @@ switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt)
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) {

View File

@ -994,13 +994,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
}
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 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
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();

View File

@ -38,18 +38,21 @@ struct switch_core_port_allocator {
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_DECLARE(switch_status_t) switch_core_port_allocator_new(switch_port_t sta
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 @@ 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);
SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_request_port(switch_core_port_allocator_t *alloc, switch_port_t *port_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:
switch_mutex_unlock(alloc->mutex);
if (status == SWITCH_STATUS_SUCCESS) {
*port_ptr = port;
} else {
*port_ptr = 0;
}
return status;
}
SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_free_port(switch_core_port_allocator_t *alloc, 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);
if (alloc->track[index]) {
alloc->track[index] = 0;
alloc->track_used--;
status = SWITCH_STATUS_SUCCESS;
}
switch_mutex_unlock(alloc->mutex);
return status;
}
SWITCH_DECLARE(switch_port_t) switch_core_port_allocator_request_port(switch_core_port_allocator_t *alloc)
{
switch_port_t port;
switch_mutex_lock(alloc->mutex);
port = alloc->next;
alloc->next = alloc->next + alloc->inc;
if (alloc->next > alloc->end) {
alloc->next = alloc->start;
}
switch_mutex_unlock(alloc->mutex);
return port;
}
SWITCH_DECLARE(void) switch_core_port_allocator_destroy(switch_core_port_allocator_t **alloc)
{
switch_memory_pool_t *pool = (*alloc)->pool;

View File

@ -67,7 +67,7 @@ typedef srtp_hdr_t rtp_hdr_t;
#pragma pack()
#endif
static switch_hash_t *alloc_hash = NULL;
typedef struct {
srtp_hdr_t header;
@ -147,7 +147,8 @@ struct switch_rtp {
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 @@ SWITCH_DECLARE(void) switch_rtp_init(switch_memory_pool_t *pool)
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 @@ SWITCH_DECLARE(switch_port_t) switch_rtp_set_end_port(switch_port_t port)
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;
switch_mutex_lock(port_lock);
port = NEXT_PORT;
NEXT_PORT += 2;
if (NEXT_PORT > END_PORT) {
NEXT_PORT = START_PORT;
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);
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 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_s
*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 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_s
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 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
return;
}
(*rtp_session)->ready = 0;
switch_mutex_lock((*rtp_session)->flag_mutex);
@ -683,6 +720,8 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
switch_core_timer_destroy(&(*rtp_session)->timer);
}
release_port(*rtp_session);
switch_mutex_unlock((*rtp_session)->flag_mutex);
return;
}