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:
parent
4968e0f6a1
commit
efb1b62938
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"))) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue