From 0ecd7504b6d067ac1120d6d6200feef92eb9c6b8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 7 Oct 2013 08:05:10 -0500 Subject: [PATCH 01/34] FS-5848 --resolve --- src/switch_core_session.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/switch_core_session.c b/src/switch_core_session.c index f77ef60559..60358ca0dd 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -2480,8 +2480,8 @@ void switch_core_session_init(switch_memory_pool_t *pool) switch_queue_create(&session_manager.thread_queue, 100000, session_manager.memory_pool); switch_threadattr_create(&thd_attr, session_manager.memory_pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_thread_create(&session_manager.manager_thread, thd_attr, switch_core_session_thread_pool_manager, NULL, session_manager.memory_pool); session_manager.ready = 1; + switch_thread_create(&session_manager.manager_thread, thd_attr, switch_core_session_thread_pool_manager, NULL, session_manager.memory_pool); } } @@ -2491,15 +2491,16 @@ void switch_core_session_uninit(void) int sanity = 100; switch_status_t st = SWITCH_STATUS_FALSE; - switch_core_hash_destroy(&session_manager.session_table); session_manager.ready = 0; - - switch_thread_join(&st, session_manager.manager_thread); + wake_queue(); while(session_manager.running && --sanity > 0) { switch_queue_interrupt_all(session_manager.thread_queue); switch_yield(100000); } + + switch_thread_join(&st, session_manager.manager_thread); + switch_core_hash_destroy(&session_manager.session_table); } From cbdb174965fb4107e71b8a9656a2b1de9a1fbd3b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 26 Sep 2013 10:21:05 -0500 Subject: [PATCH 02/34] add gl git wrapper script to inline jira summaries into git log --- support-d/gl | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100755 support-d/gl diff --git a/support-d/gl b/support-d/gl new file mode 100755 index 0000000000..c4e878ba98 --- /dev/null +++ b/support-d/gl @@ -0,0 +1,82 @@ +#!/usr/bin/perl + +my $pager = `which less` || `which more`; +my $tmpdir = "/tmp/FSJIRA"; + +system("mkdir -p $tmpdir"); + +my $cmd = "git log " . join(" ", @ARGV); + +open(CMD, "$cmd |"); +open(PAGER, "|$pager"); +select PAGER; + +while(my $line = ) { + + print $line; + + if ($line =~ /([A-Z]+\-[0-9]+)/) { + my $bug = $1; + my $txt = bugtxt($bug); + if ($txt) { + print "=" x 80 . "\n"; + print $txt; + print "=" x 80 . "\n"; + } + } +} + +close(CMD); +close(PAGER); + +sub catfile($) { + my $file = shift; + open(I, $file) or return; + $/ = undef; + my $txt = ; + $/ = "\n"; + close(I); + return $txt; +} + + +sub bugtxt($) +{ + my $bug = shift or return ""; + my $now = time; + my $tmp; + + $bug =~ s/\.\.//g; + $bug =~ s/^\///g; + $bug =~ s/~//g; + $bug =~ s/[^a-zA-Z0-9\-]//g; + + $tmp = "$tmpdir/$bug.txt"; + + if(-f $tmp) { + return catfile($tmp); + } + + my $cmd = "wget -q http://jira.freeswitch.org/si/jira.issueviews:issue-xml/$bug/$bug.xml -O $tmp"; + + system($cmd); + + my $txt = catfile($tmp); + + my ($a,$title) = $txt =~ /\(.*?)\<\/title\>/smg; + my ($status) = $txt =~ /\(.*?)\<\/status\>/smg; + my ($a,$des) = $txt =~ /\(.*?)\<\/description\>/smg; + my ($alogin, $aname) = $txt =~ /\(.*?)\<\/assignee\>/smg; + my ($rlogin, $rname) = $txt =~ /\(.*?)\<\/reporter\>/smg; + + + if ($rname && $aname) { + my $data = "$title\nReporter: $rname [$rlogin]\nAssignee: $aname [$alogin]\nStatus: $status\nhttp://jira.freeswitch.org/browse/$bug\n"; + open(O, ">$tmp"); + print O $data; + close(O); + return $data; + } else { + unlink($tmp); + } +} From cb3cb7ff70c5babd10f859a972d652b2014650a2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 8 Oct 2013 09:40:01 -0500 Subject: [PATCH 03/34] FS-5851 --resolve --- .../applications/mod_dptools/mod_dptools.c | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index b49e1a02ee..1146dc38ca 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -4615,6 +4615,7 @@ static switch_status_t file_string_file_read(switch_file_handle_t *handle, void return status; } + static switch_status_t file_string_file_write(switch_file_handle_t *handle, void *data, size_t *len) { file_string_context_t *context = handle->private_info; @@ -4633,10 +4634,101 @@ static switch_status_t file_string_file_write(switch_file_handle_t *handle, void return status; } +static switch_status_t file_url_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence) +{ + switch_file_handle_t *fh = handle->private_info; + return switch_core_file_seek(fh, cur_sample, samples, whence); +} + +static switch_status_t file_url_file_close(switch_file_handle_t *handle) +{ + switch_file_handle_t *fh = handle->private_info; + if (switch_test_flag(fh, SWITCH_FILE_OPEN)) { + switch_core_file_close(fh); + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t file_url_file_read(switch_file_handle_t *handle, void *data, size_t *len) +{ + switch_file_handle_t *fh = handle->private_info; + return switch_core_file_read(fh, data, len); +} + +static switch_status_t file_url_file_open(switch_file_handle_t *handle, const char *path) +{ + switch_file_handle_t *fh = switch_core_alloc(handle->memory_pool, sizeof(*fh)); + switch_status_t status; + char *url_host; + char *url_path; + + if (zstr(path)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NULL path\n"); + return SWITCH_STATUS_FALSE; + } + + /* parse and check host */ + url_host = switch_core_strdup(handle->memory_pool, path); + if (!(url_path = strchr(url_host, '/'))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing path\n"); + return SWITCH_STATUS_FALSE; + } + *url_path = '\0'; + /* TODO allow this host */ + if (!zstr(url_host) && strcasecmp(url_host, "localhost")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not localhost\n"); + return SWITCH_STATUS_FALSE; + } + + /* decode and check path */ + url_path++; + if (zstr(url_path)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "empty path\n"); + return SWITCH_STATUS_FALSE; + } + if (strstr(url_path, "%2f") || strstr(url_path, "%2F")) { + /* don't allow %2f or %2F encoding (/) */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "encoded slash is not allowed\n"); + return SWITCH_STATUS_FALSE; + } + url_path = switch_core_sprintf(handle->memory_pool, "/%s", url_path); + switch_url_decode(url_path); + + /* TODO convert to native file separators? */ + + handle->private_info = fh; + status = switch_core_file_open(fh, url_path, handle->channels, handle->samplerate, handle->flags, NULL); + if (status == SWITCH_STATUS_SUCCESS) { + handle->samples = fh->samples; + handle->cur_samplerate = fh->samplerate; + handle->cur_channels = fh->channels; + handle->format = fh->format; + handle->sections = fh->sections; + handle->seekable = fh->seekable; + handle->speed = fh->speed; + handle->interval = fh->interval; + handle->max_samples = 0; + + if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) { + switch_set_flag(handle, SWITCH_FILE_NATIVE); + } else { + switch_clear_flag(handle, SWITCH_FILE_NATIVE); + } + } + return status; +} + +static switch_status_t file_url_file_write(switch_file_handle_t *handle, void *data, size_t *len) +{ + switch_file_handle_t *fh = handle->private_info; + return switch_core_file_write(fh, data, len); +} /* Registration */ static char *file_string_supported_formats[SWITCH_MAX_CODECS] = { 0 }; +static char *file_url_supported_formats[SWITCH_MAX_CODECS] = { 0 }; /* /FILE STRING INTERFACE */ @@ -5504,6 +5596,17 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) file_interface->file_write = file_string_file_write; file_interface->file_seek = file_string_file_seek; + file_url_supported_formats[0] = "file"; + + file_interface = (switch_file_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE); + file_interface->interface_name = modname; + file_interface->extens = file_url_supported_formats; + file_interface->file_open = file_url_file_open; + file_interface->file_close = file_url_file_close; + file_interface->file_read = file_url_file_read; + file_interface->file_write = file_url_file_write; + file_interface->file_seek = file_url_file_seek; + error_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE); error_endpoint_interface->interface_name = "error"; From 12409dbeffcfd513c8e54c4e9ad2b4664301e961 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 8 Oct 2013 21:57:12 +0500 Subject: [PATCH 04/34] FS-5849 --resolve --- .../mod_conference/mod_conference.c | 86 ++++++++++++++----- 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 8e06012b7d..6d5597efd9 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -283,6 +283,17 @@ struct vid_helper { int up; }; +struct conference_obj; + +/* Record Node */ +typedef struct conference_record { + struct conference_obj *conference; + char *path; + switch_memory_pool_t *pool; + switch_bool_t autorec; + struct conference_record *next; +} conference_record_t; + /* Conference Object */ typedef struct conference_obj { char *name; @@ -348,7 +359,7 @@ typedef struct conference_obj { int pin_retries; int broadcast_chat_messages; int comfort_noise_level; - int is_recording; + int auto_recording; int record_count; int video_running; int ivr_dtmf_timeout; @@ -381,6 +392,7 @@ typedef struct conference_obj { cdr_event_mode_t cdr_event_mode; struct vid_helper vh[2]; struct vid_helper mh; + conference_record_t *rec_node_head; } conference_obj_t; /* Relationship with another member */ @@ -450,13 +462,6 @@ struct conference_member { switch_thread_t *input_thread; }; -/* Record Node */ -typedef struct conference_record { - conference_obj_t *conference; - char *path; - switch_memory_pool_t *pool; -} conference_record_t; - typedef enum { CONF_API_SUB_ARGS_SPLIT, CONF_API_SUB_MEMBER_TARGET, @@ -524,7 +529,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c static switch_status_t chat_send(switch_event_t *message_event); -static void launch_conference_record_thread(conference_obj_t *conference, char *path); +static void launch_conference_record_thread(conference_obj_t *conference, char *path, switch_bool_t autorec); static int launch_conference_video_bridge_thread(conference_member_t *member_a, conference_member_t *member_b); static void launch_conference_video_mirror_thread(conference_member_t *member_a); @@ -1965,7 +1970,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v globals.threads++; switch_mutex_unlock(globals.hash_mutex); - conference->is_recording = 0; + conference->auto_recording = 0; conference->record_count = 0; @@ -2105,15 +2110,15 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v } /* Start recording if there's more than one participant. */ - if (conference->auto_record && !conference->is_recording && conference->count > 1) { - conference->is_recording = 1; + if (conference->auto_record && !conference->auto_recording && conference->count > 1) { + conference->auto_recording++; conference->record_count++; imember = conference->members; if (imember) { switch_channel_t *channel = switch_core_session_get_channel(imember->session); char *rfile = switch_channel_expand_variables(channel, conference->auto_record); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Auto recording file: %s\n", rfile); - launch_conference_record_thread(conference, rfile); + launch_conference_record_thread(conference, rfile, SWITCH_TRUE); if (rfile != conference->auto_record) { conference->record_filename = switch_core_strdup(conference->pool, rfile); switch_safe_free(rfile); @@ -3877,7 +3882,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th int16_t *data_buf; switch_file_handle_t fh = { 0 }; conference_member_t smember = { 0 }, *member; - conference_record_t *rec = (conference_record_t *) obj; + conference_record_t *rp, *last = NULL, *rec = (conference_record_t *) obj; conference_obj_t *conference = rec->conference; uint32_t samples = switch_samples_per_packet(conference->rate, conference->interval); uint32_t mux_used; @@ -4058,8 +4063,6 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th switch_mutex_unlock(member->audio_out_mutex); } - conference->is_recording = 0; - switch_safe_free(data_buf); switch_core_timer_destroy(&timer); conference_del_member(conference, member); @@ -4078,6 +4081,23 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th switch_event_fire(&event); } + if (rec->autorec && conference->auto_recording) { + conference->auto_recording--; + } + + switch_mutex_lock(conference->flag_mutex); + for (rp = conference->rec_node_head; rp; rp = rp->next) { + if (rec == rp) { + if (last) { + last->next = rp->next; + } else { + conference->rec_node_head = rp->next; + } + } + } + switch_mutex_unlock(conference->flag_mutex); + + if (rec->pool) { switch_memory_pool_t *pool = rec->pool; rec = NULL; @@ -6177,11 +6197,20 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc static switch_status_t conf_api_sub_check_record(conference_obj_t *conference, switch_stream_handle_t *stream, int arc, char **argv) { - if (conference->is_recording) { - stream->write_function(stream, "Record file %s\n", conference->record_filename); - } else { + conference_record_t *rec; + int x = 0; + + switch_mutex_lock(conference->flag_mutex); + for (rec = conference->rec_node_head; rec; rec = rec->next) { + stream->write_function(stream, "Record file %s%s%s\n", rec->path, rec->autorec ? " " : "", rec->autorec ? "(Auto)" : ""); + x++; + } + + if (!x) { stream->write_function(stream, "Conference is not being recorded.\n"); } + switch_mutex_unlock(conference->flag_mutex); + return SWITCH_STATUS_SUCCESS; } @@ -6196,7 +6225,7 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_ stream->write_function(stream, "Record file %s\n", argv[2]); conference->record_filename = switch_core_strdup(conference->pool, argv[2]); conference->record_count++; - launch_conference_record_thread(conference, argv[2]); + launch_conference_record_thread(conference, argv[2], SWITCH_FALSE); return SWITCH_STATUS_SUCCESS; } @@ -6282,6 +6311,13 @@ static switch_status_t conf_api_sub_recording(conference_obj_t *conference, swit switch_assert(conference != NULL); switch_assert(stream != NULL); + if (argc <= 3) { + if (strcasecmp(argv[2], "stop") == 0 || strcasecmp(argv[2], "check") == 0) { + argv[3] = "all"; + argc++; + } + } + if (argc <= 3) { /* It means that old syntax is used */ return conf_api_sub_record(conference,stream,argc,argv); @@ -8023,7 +8059,7 @@ static void launch_conference_video_mirror_thread(conference_member_t *member_a) launch_thread_detached(conference_video_mirror_thread_run, pool, &conference->mh); } -static void launch_conference_record_thread(conference_obj_t *conference, char *path) +static void launch_conference_record_thread(conference_obj_t *conference, char *path, switch_bool_t autorec) { switch_thread_t *thread; switch_threadattr_t *thd_attr = NULL; @@ -8042,11 +8078,15 @@ static void launch_conference_record_thread(conference_obj_t *conference, char * return; } - conference->is_recording = 1; - rec->conference = conference; rec->path = switch_core_strdup(pool, path); rec->pool = pool; + rec->autorec = autorec; + + switch_mutex_lock(conference->flag_mutex); + rec->next = conference->rec_node_head; + conference->rec_node_head = rec; + switch_mutex_unlock(conference->flag_mutex); switch_threadattr_create(&thd_attr, rec->pool); switch_threadattr_detach_set(thd_attr, 1); From 9764fb33cd40fefd97f9e85b4d2b9a2a9c4d41aa Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 8 Oct 2013 12:10:36 -0500 Subject: [PATCH 05/34] FS-5855 please try lastest HEAD Conflicts: libs/sofia-sip/.update --- libs/sofia-sip/.update | 2 +- libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 275b8aceb5..b07a4f4762 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Fri Sep 20 00:39:20 CDT 2013 +Tue Oct 8 23:05:34 CDT 2013 diff --git a/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c b/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c index 02b9a5c5a7..e20a9d19a6 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c +++ b/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c @@ -640,14 +640,16 @@ static void print_media(sdp_printer_t *p, print_key(p, m->m_key); for (rm = m->m_rtpmaps; rm; rm = rm->rm_next) { - if (!rm->rm_predef || p->pr_all_rtpmaps) - sdp_printf(p, "a=rtpmap:%u %s/%lu%s%s" CRLF, - rm->rm_pt, rm->rm_encoding, rm->rm_rate, - rm->rm_params ? "/" : "", - rm->rm_params ? rm->rm_params : ""); - if (rm->rm_fmtp) - sdp_printf(p, "a=fmtp:%u %s" CRLF, - rm->rm_pt, rm->rm_fmtp); + if (rm->rm_encoding && *rm->rm_encoding && (!rm->rm_predef || p->pr_all_rtpmaps)) { + sdp_printf(p, "a=rtpmap:%u %s/%lu%s%s" CRLF, + rm->rm_pt, rm->rm_encoding, rm->rm_rate, + rm->rm_params ? "/" : "", + rm->rm_params ? rm->rm_params : ""); + } + if (rm->rm_fmtp) { + sdp_printf(p, "a=fmtp:%u %s" CRLF, + rm->rm_pt, rm->rm_fmtp); + } } if (!p->pr_mode_manual && !m->m_rejected && From fadb5fe316d5ec52152ecc2ba7e7d594d34c42c4 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 9 Oct 2013 02:42:14 +0500 Subject: [PATCH 06/34] FS-5857 --resolve --- .../mod_conference/mod_conference.c | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 6d5597efd9..265effdb2e 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -428,6 +428,7 @@ struct conference_member { switch_codec_t write_codec; char *rec_path; switch_time_t rec_time; + conference_record_t *rec; uint8_t *frame; uint8_t *last_frame; uint32_t frame_size; @@ -1216,7 +1217,7 @@ static conference_member_t *conference_member_get(conference_obj_t *conference, } /* stop the specified recording */ -static switch_status_t conference_record_stop(conference_obj_t *conference, char *path) +static switch_status_t conference_record_stop(conference_obj_t *conference, switch_stream_handle_t *stream, char *path) { conference_member_t *member = NULL; int count = 0; @@ -1225,10 +1226,21 @@ static switch_status_t conference_record_stop(conference_obj_t *conference, char switch_mutex_lock(conference->member_mutex); for (member = conference->members; member; member = member->next) { if (switch_test_flag(member, MFLAG_NOCHANNEL) && (!path || !strcmp(path, member->rec_path))) { + if (member->rec && member->rec->autorec) { + stream->write_function(stream, "Stopped AUTO recording file %s (Auto Recording Now Disabled)\n", member->rec_path); + conference->auto_record = 0; + } else { + stream->write_function(stream, "Stopped recording file %s\n", member->rec_path); + } + switch_clear_flag_locked(member, MFLAG_RUNNING); count++; + } } + + conference->record_count -= count; + switch_mutex_unlock(conference->member_mutex); return count; } @@ -3920,7 +3932,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th fh.samplerate = conference->rate; member->id = next_member_id(); member->pool = rec->pool; - + member->rec = rec; member->frame_size = SWITCH_RECOMMENDED_BUFFER_SIZE; member->frame = switch_core_alloc(member->pool, member->frame_size); member->mux_frame = switch_core_alloc(member->pool, member->frame_size); @@ -6219,8 +6231,9 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_ switch_assert(conference != NULL); switch_assert(stream != NULL); - if (argc <= 2) + if (argc <= 2) { return SWITCH_STATUS_GENERR; + } stream->write_function(stream, "Record file %s\n", argv[2]); conference->record_filename = switch_core_strdup(conference->pool, argv[2]); @@ -6231,7 +6244,7 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv) { - int all; + int all, before = conference->record_count, ttl = 0; switch_event_t *event; switch_assert(conference != NULL); @@ -6241,15 +6254,10 @@ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switc return SWITCH_STATUS_GENERR; all = (strcasecmp(argv[2], "all") == 0); - stream->write_function(stream, "Stop recording file %s\n", argv[2]); - if (!conference_record_stop(conference, all ? NULL : argv[2]) && !all) { + + if (!conference_record_stop(conference, stream, all ? NULL : argv[2]) && !all) { stream->write_function(stream, "non-existant recording '%s'\n", argv[2]); } else { - if (all) { - conference->record_count = 0; - } else { - conference->record_count--; - } if (test_eflag(conference, EFLAG_RECORD) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_add_event_data(conference, event); @@ -6260,6 +6268,9 @@ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switc } } + ttl = before - conference->record_count; + stream->write_function(stream, "Stopped recording %d file%s\n", ttl, ttl == 1 ? "" : "s"); + return SWITCH_STATUS_SUCCESS; } @@ -6311,7 +6322,7 @@ static switch_status_t conf_api_sub_recording(conference_obj_t *conference, swit switch_assert(conference != NULL); switch_assert(stream != NULL); - if (argc <= 3) { + if (argc > 2 && argc <= 3) { if (strcasecmp(argv[2], "stop") == 0 || strcasecmp(argv[2], "check") == 0) { argv[3] = "all"; argc++; From f7c9c401a321aaa0eeed33d9a809d902ca60d815 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Wed, 9 Oct 2013 17:39:33 -0400 Subject: [PATCH 07/34] FS-5865 mod_rayo: send IQ result after join/unjoin completes --- src/mod/event_handlers/mod_rayo/mod_rayo.c | 155 +++++++++++++++------ 1 file changed, 109 insertions(+), 46 deletions(-) diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index e232ac8d38..92257aa2f6 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -128,6 +128,8 @@ struct rayo_call { switch_time_t idle_start_time; /** 1 if joined to call, 2 if joined to mixer */ int joined; + /** pending join */ + iks *pending_join_request; /** ID of joined party TODO this will be many mixers / calls */ const char *joined_id; /** set if response needs to be sent to IQ request */ @@ -937,6 +939,14 @@ static void rayo_call_cleanup(struct rayo_actor *actor) RAYO_SEND_MESSAGE_DUP(actor, rayo_call_get_dcp_jid(call), revent); } + /* lost the race: pending join failed... send IQ result to client now. */ + if (call->pending_join_request) { + iks *result = iks_new_error_detailed(call->pending_join_request, STANZA_ERROR_ITEM_NOT_FOUND, "call ended"); + RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result); + iks_delete(call->pending_join_request); + call->pending_join_request = NULL; + } + iks_delete(revent); switch_event_destroy(&event); } @@ -1068,6 +1078,7 @@ static struct rayo_call *rayo_call_init(struct rayo_call *call, switch_memory_po call->joined = 0; call->joined_id = NULL; call->ringing_sent = 0; + call->pending_join_request = NULL; switch_core_hash_init(&call->pcps, pool); switch_safe_free(call_jid); @@ -1292,6 +1303,17 @@ static struct rayo_peer_server *rayo_peer_server_create(const char *jid) return rserver; } +/** + * Check if message sender has control of offered call. + * @param call the Rayo call + * @param msg the message + * @return 1 if sender has call control, 0 if sender does not have control + */ +static int has_call_control(struct rayo_call *call, struct rayo_message *msg) +{ + return (!strcmp(rayo_call_get_dcp_jid(call), msg->from_jid) || is_internal_message(msg) || is_admin_client_message(msg)); +} + /** * Check if message sender has control of offered call. Take control if nobody else does. * @param call the Rayo call @@ -1299,7 +1321,7 @@ static struct rayo_peer_server *rayo_peer_server_create(const char *jid) * @param msg the message * @return 1 if sender has call control */ -static int has_call_control(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg) +static int take_call_control(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg) { int control = 0; @@ -1313,7 +1335,7 @@ static int has_call_control(struct rayo_call *call, switch_core_session_t *sessi control = 1; switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s has control of call\n", rayo_call_get_dcp_jid(call)); } - } else if (!strcmp(rayo_call_get_dcp_jid(call), msg->from_jid) || is_internal_message(msg) || is_admin_client_message(msg)) { + } else if (has_call_control(call, msg)) { control = 1; } @@ -1358,7 +1380,7 @@ static iks *rayo_call_command_ok(struct rayo_call *call, switch_core_session_t * if (bad) { response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST); - } else if (!has_call_control(call, session, msg)) { + } else if (!take_call_control(call, session, msg)) { response = iks_new_error(node, STANZA_ERROR_CONFLICT); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, %s conflict\n", msg->from_jid, RAYO_JID(call)); } @@ -1711,13 +1733,14 @@ static iks *on_rayo_hangup(struct rayo_actor *call, struct rayo_message *msg, vo * Join calls together * @param call the call that joins * @param session the session - * @param node the join request + * @param msg the rayo join message * @param call_uri to join * @param media mode (direct/bridge) * @return the response */ -static iks *join_call(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *call_uri, const char *media) +static iks *join_call(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *call_uri, const char *media) { + iks *node = msg->payload; iks *response = NULL; /* take call out of media path if media = "direct" */ const char *bypass = !strcmp("direct", media) ? "true" : "false"; @@ -1727,6 +1750,9 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, ik if (!b_call) { /* not a rayo call */ response = iks_new_error_detailed(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "b-leg is not a rayo call"); + } else if (!has_call_control(b_call, msg)) { + /* not allowed to join to this call */ + response = iks_new_error(node, STANZA_ERROR_NOT_ALLOWED); } else if (b_call->joined) { /* don't support multiple joined calls */ response = iks_new_error_detailed(node, STANZA_ERROR_CONFLICT, "multiple joined calls not supported"); @@ -1737,10 +1763,11 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, ik if (switch_false(bypass)) { switch_channel_pre_answer(switch_core_session_get_channel(session)); } - if (switch_ivr_uuid_bridge(rayo_call_get_uuid(call), rayo_call_get_uuid(b_call)) == SWITCH_STATUS_SUCCESS) { - response = iks_new_iq_result(node); - } else { + call->pending_join_request = iks_copy(node); + if (switch_ivr_uuid_bridge(rayo_call_get_uuid(call), rayo_call_get_uuid(b_call)) != SWITCH_STATUS_SUCCESS) { response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to bridge call"); + iks_delete(call->pending_join_request); + call->pending_join_request = NULL; } RAYO_UNLOCK(b_call); } @@ -1763,13 +1790,14 @@ static void exec_conference_api(switch_core_session_t *session, const char *conf * Join call to a mixer * @param call the call that joins * @param session the session - * @param node the join request + * @param msg the join request * @param mixer_name the mixer to join * @param direction the media direction * @return the response */ -static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *mixer_name, const char *direction) +static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *mixer_name, const char *direction) { + iks *node = msg->payload; iks *response = NULL; if (call->joined_id) { @@ -1806,14 +1834,13 @@ static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, i * Handle request * @param call the Rayo call * @param session the session - * @param node the node + * @param msg the rayo join message */ static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void *session_data) { - iks *node = msg->payload; switch_core_session_t *session = (switch_core_session_t *)session_data; iks *response = NULL; - iks *join = iks_find(node, "join"); + iks *join = iks_find(msg->payload, "join"); const char *join_id; const char *mixer_name; const char *call_uri; @@ -1821,7 +1848,7 @@ static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void /* validate input attributes */ if (!VALIDATE_RAYO_JOIN(join)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Bad join attrib\n"); - response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST); + response = iks_new_error(msg->payload, STANZA_ERROR_BAD_REQUEST); goto done; } mixer_name = iks_find_attrib(join, "mixer-name"); @@ -1835,29 +1862,35 @@ static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void /* can't join both mixer and call */ if (!zstr(mixer_name) && !zstr(call_uri)) { - response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "mixer-name and call-uri are mutually exclusive"); + response = iks_new_error_detailed(msg->payload, STANZA_ERROR_BAD_REQUEST, "mixer-name and call-uri are mutually exclusive"); goto done; } /* need to join *something* */ if (zstr(mixer_name) && zstr(call_uri)) { - response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "mixer-name or call-uri is required"); + response = iks_new_error_detailed(msg->payload, STANZA_ERROR_BAD_REQUEST, "mixer-name or call-uri is required"); goto done; } if ((RAYO_CALL(call)->joined == JOINED_CALL) || (RAYO_CALL(call)->joined == JOINED_MIXER && strcmp(RAYO_CALL(call)->joined_id, join_id))) { /* already joined */ - response = iks_new_error_detailed(node, STANZA_ERROR_CONFLICT, "call is already joined"); + response = iks_new_error_detailed(msg->payload, STANZA_ERROR_CONFLICT, "call is already joined"); + goto done; + } + + if (RAYO_CALL(call)->pending_join_request) { + /* don't allow concurrent join requests */ + response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending"); goto done; } if (!zstr(mixer_name)) { /* join conference */ - response = join_mixer(RAYO_CALL(call), session, node, mixer_name, iks_find_attrib(join, "direction")); + response = join_mixer(RAYO_CALL(call), session, msg, mixer_name, iks_find_attrib(join, "direction")); } else { /* bridge calls */ - response = join_call(RAYO_CALL(call), session, node, call_uri, iks_find_attrib(join, "media")); + response = join_call(RAYO_CALL(call), session, msg, call_uri, iks_find_attrib(join, "media")); } done: @@ -1868,12 +1901,13 @@ done: * unjoin call to a bridge * @param call the call that unjoined * @param session the session - * @param node the unjoin request + * @param msg the unjoin request * @param call_uri the b-leg xmpp URI * @return the response */ -static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *call_uri) +static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *call_uri) { + iks *node = msg->payload; iks *response = NULL; const char *bleg_uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_BRIDGE_UUID_VARIABLE); const char *bleg_uri = switch_core_session_sprintf(session, "xmpp:%s@%s", bleg_uuid ? bleg_uuid : "", RAYO_JID(globals.server)); @@ -1881,7 +1915,7 @@ static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session, /* bleg must match call_uri */ if (!zstr(bleg_uri) && !strcmp(bleg_uri, call_uri)) { /* unbridge call */ - response = iks_new_iq_result(node); + call->pending_join_request = iks_copy(node); switch_ivr_park_session(session); } else { /* not bridged or wrong b-leg URI */ @@ -1895,15 +1929,16 @@ static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session, * unjoin call to a mixer * @param call the call that unjoined * @param session the session - * @param node the unjoin request + * @param msg the unjoin request * @param mixer_name the mixer name * @return the response */ -static iks *unjoin_mixer(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *mixer_name) +static iks *unjoin_mixer(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *mixer_name) { switch_channel_t *channel = switch_core_session_get_channel(session); const char *conf_member_id = switch_channel_get_variable(channel, "conference_member_id"); const char *conf_name = switch_channel_get_variable(channel, "conference_name"); + iks *node = msg->payload; iks *response = NULL; /* not conferenced, or wrong conference */ @@ -1935,31 +1970,33 @@ done: */ static iks *on_rayo_unjoin(struct rayo_actor *call, struct rayo_message *msg, void *session_data) { - iks *node = msg->payload; switch_core_session_t *session = (switch_core_session_t *)session_data; iks *response = NULL; - iks *unjoin = iks_find(node, "unjoin"); + iks *unjoin = iks_find(msg->payload, "unjoin"); const char *call_uri = iks_find_attrib(unjoin, "call-uri"); const char *mixer_name = iks_find_attrib(unjoin, "mixer-name"); if (!zstr(call_uri) && !zstr(mixer_name)) { - response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST); + response = iks_new_error(msg->payload, STANZA_ERROR_BAD_REQUEST); + } else if (RAYO_CALL(call)->pending_join_request) { + /* need to let pending request finish first */ + response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending"); } else if (!RAYO_CALL(call)->joined) { /* not joined to anything */ - response = iks_new_error(node, STANZA_ERROR_SERVICE_UNAVAILABLE); + response = iks_new_error(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE); } else if (!zstr(call_uri)) { - response = unjoin_call(RAYO_CALL(call), session, node, call_uri); + response = unjoin_call(RAYO_CALL(call), session, msg, call_uri); } else if (!zstr(mixer_name)) { - response = unjoin_mixer(RAYO_CALL(call), session, node, mixer_name); + response = unjoin_mixer(RAYO_CALL(call), session, msg, mixer_name); } else { /* unjoin everything */ if (RAYO_CALL(call)->joined == JOINED_MIXER) { - response = unjoin_mixer(RAYO_CALL(call), session, node, RAYO_CALL(call)->joined_id); + response = unjoin_mixer(RAYO_CALL(call), session, msg, RAYO_CALL(call)->joined_id); } else if (RAYO_CALL(call)->joined == JOINED_CALL) { - response = unjoin_call(RAYO_CALL(call), session, node, RAYO_CALL(call)->joined_id); + response = unjoin_call(RAYO_CALL(call), session, msg, RAYO_CALL(call)->joined_id); } else { /* shouldn't happen */ - response = iks_new_error(node, STANZA_ERROR_INTERNAL_SERVER_ERROR); + response = iks_new_error(msg->payload, STANZA_ERROR_INTERNAL_SERVER_ERROR); } } @@ -2661,16 +2698,29 @@ static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *ev struct rayo_call *b_call; if (call) { - /* send A-leg event */ - iks *revent = iks_new_presence("joined", RAYO_NS, - switch_event_get_header(event, "variable_rayo_call_jid"), - switch_event_get_header(event, "variable_rayo_dcp_jid")); - iks *joined = iks_find(revent, "joined"); - iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server)); + iks *revent; + iks *joined; call->joined = JOINED_CALL; call->joined_id = switch_core_strdup(RAYO_POOL(call), b_uuid); + /* send IQ result to client now. */ + switch_mutex_lock(RAYO_ACTOR(call)->mutex); + if (call->pending_join_request) { + iks *result = iks_new_iq_result(call->pending_join_request); + RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result); + iks_delete(call->pending_join_request); + call->pending_join_request = NULL; + } + switch_mutex_unlock(RAYO_ACTOR(call)->mutex); + + /* send A-leg event */ + revent = iks_new_presence("joined", RAYO_NS, + switch_event_get_header(event, "variable_rayo_call_jid"), + switch_event_get_header(event, "variable_rayo_dcp_jid")); + joined = iks_find(revent, "joined"); + iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server)); + RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent); /* send B-leg event */ @@ -2703,17 +2753,30 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t * struct rayo_call *b_call; if (call) { - /* send A-leg event */ - iks *revent = iks_new_presence("unjoined", RAYO_NS, - switch_event_get_header(event, "variable_rayo_call_jid"), - switch_event_get_header(event, "variable_rayo_dcp_jid")); - iks *joined = iks_find(revent, "unjoined"); - iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server)); - RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent); + iks *revent; + iks *joined; call->joined = 0; call->joined_id = NULL; + /* send IQ result to client now. */ + switch_mutex_lock(RAYO_ACTOR(call)->mutex); + if (call->pending_join_request) { + iks *result = iks_new_iq_result(call->pending_join_request); + RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result); + iks_delete(call->pending_join_request); + call->pending_join_request = NULL; + } + switch_mutex_unlock(RAYO_ACTOR(call)->mutex); + + /* send A-leg event */ + revent = iks_new_presence("unjoined", RAYO_NS, + switch_event_get_header(event, "variable_rayo_call_jid"), + switch_event_get_header(event, "variable_rayo_dcp_jid")); + joined = iks_find(revent, "unjoined"); + iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server)); + RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent); + /* send B-leg event */ b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid); if (b_call) { From 6c5da6435dd93c4b1f03b4c10beb1140f455010b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 10 Oct 2013 04:40:56 +0500 Subject: [PATCH 08/34] FS-5861 --resolve --- src/mod/applications/mod_dptools/mod_dptools.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 1146dc38ca..5fe2c57e5b 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -283,10 +283,17 @@ SWITCH_STANDARD_APP(clear_digit_action_function) { //switch_channel_t *channel = switch_core_session_get_channel(session); switch_ivr_dmachine_t *dmachine; - char *realm = switch_core_session_strdup(session, data); + char *realm = NULL; char *target_str; switch_digit_action_target_t target = DIGIT_TARGET_SELF; + if (zstr(realm)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "clear_digit_action called with no args"); + return; + } + + realm = switch_core_session_strdup(session, data); + if ((target_str = strchr(realm, ','))) { *target_str++ = '\0'; target = str2target(target_str); From 167071cc77ce6a5e8a8e29f1ef370e74547c51c5 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Thu, 10 Oct 2013 11:48:57 -0400 Subject: [PATCH 09/34] FS-5866 --- src/mod/codecs/mod_com_g729/Makefile.am | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mod/codecs/mod_com_g729/Makefile.am b/src/mod/codecs/mod_com_g729/Makefile.am index a0d8b861df..e6586e159f 100644 --- a/src/mod/codecs/mod_com_g729/Makefile.am +++ b/src/mod/codecs/mod_com_g729/Makefile.am @@ -15,11 +15,11 @@ install: $(LICSERVER) $(VALIDATOR) $(MOD) $(LICSERVER) $(VALIDATOR) $(MOD): $(G729INSTALLER) $(SHELL) $(G729INSTALLER) $(bindir) $(moddir) nobanner - $(ECHO) - $(ECHO) - $(ECHO) Now you can activate your license by running $(MAKE) mod_com_g729-activate - $(ECHO) - $(ECHO) + @echo + @echo + @echo Now you can activate your license by running $(MAKE) mod_com_g729-activate + @echo + @echo $(G729INSTALLER): rm -f $(top_srcdir)/libs/fsg729-*-installer* From 1716dbc214e1cca4f2bc4e5c93c89f35cc8a9c4f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 10 Oct 2013 22:22:59 +0500 Subject: [PATCH 10/34] move shutdown of session to after switch_event --- src/switch_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core.c b/src/switch_core.c index 5fafa3de8a..b2a07f0c5f 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2600,7 +2600,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void) switch_nat_shutdown(); } switch_xml_destroy(); - switch_core_session_uninit(); switch_console_shutdown(); switch_channel_global_uninit(); @@ -2610,6 +2609,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n"); switch_log_shutdown(); + switch_core_session_uninit(); switch_core_unset_variables(); switch_core_memory_stop(); From c35ec2e208f811440a1c9eafc8fdd76d5db3d252 Mon Sep 17 00:00:00 2001 From: Brian West Date: Fri, 11 Oct 2013 17:20:46 -0500 Subject: [PATCH 11/34] url_decode the cid_name when you vm_cc --- src/mod/applications/mod_voicemail/mod_voicemail.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index cb54af30bf..22de3bf1cb 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -3078,10 +3078,17 @@ static switch_status_t deliver_vm(vm_profile_t *profile, vm_cc_num = switch_separate_string(vm_cc_dup, ',', vm_cc_list, (sizeof(vm_cc_list) / sizeof(vm_cc_list[0]))); for (vm_cc_i=0; vm_cc_i Date: Fri, 11 Oct 2013 17:23:47 -0500 Subject: [PATCH 12/34] doh, use the decoded value --- src/mod/applications/mod_voicemail/mod_voicemail.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 22de3bf1cb..07d4d2fe95 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -3086,7 +3086,7 @@ static switch_status_t deliver_vm(vm_profile_t *profile, cmd = switch_mprintf("%s %s %s '%s' %s@%s %s", vm_cc_current, file_path, caller_id_number, - caller_id_name, myid, domain_name, read_flags); + val, myid, domain_name, read_flags); free(val); From d820e981ca0a1e64d78f96f56ea245ca83eb8b65 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 12 Oct 2013 17:58:57 +0000 Subject: [PATCH 13/34] Force preference on ssmtp if no MTA is installed FS-5872 --resolve --- debian/control-modules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control-modules b/debian/control-modules index 919382ce93..57051e5638 100644 --- a/debian/control-modules +++ b/debian/control-modules @@ -229,7 +229,7 @@ Description: Voicemail detection Module: applications/mod_voicemail Description: Voicemail This module provides a voicemail system. -Depends: mail-transport-agent +Depends: ssmtp | mail-transport-agent Module: applications/mod_voicemail_ivr Description: Voicemail IVR From 4edd7b74223a7ddedd7dd65ed033b4d1da7fb6ba Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 14 Oct 2013 21:03:39 +0500 Subject: [PATCH 14/34] FS-5835 --resolve --- src/mod/endpoints/mod_sofia/sofia_glue.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 74b27f3676..146d63b973 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4414,7 +4414,6 @@ int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) switch_channel_stop_broadcast(b_channel); switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL); } - switch_core_session_rwunlock(b_session); } sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD); From 1f9a22b43d0ee97e7ef445517000c0bb0d560e10 Mon Sep 17 00:00:00 2001 From: Ken Rice Date: Mon, 14 Oct 2013 11:18:40 -0500 Subject: [PATCH 15/34] Rev Bump --- build/next-release.txt | 2 +- configure.in | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/next-release.txt b/build/next-release.txt index c11470058f..fd9d1a5aca 100644 --- a/build/next-release.txt +++ b/build/next-release.txt @@ -1 +1 @@ -1.2.11 +1.2.14 diff --git a/configure.in b/configure.in index b1e7e5f9cb..c416a52c15 100644 --- a/configure.in +++ b/configure.in @@ -3,10 +3,10 @@ # Must change all of the below together # For a release, set revision for that tagged release as well and uncomment -AC_INIT([freeswitch], [1.2.13], bugs@freeswitch.org) +AC_INIT([freeswitch], [1.2.14], bugs@freeswitch.org) AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MINOR, [2]) -AC_SUBST(SWITCH_VERSION_MICRO, [13]) +AC_SUBST(SWITCH_VERSION_MICRO, [14]) AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, []) From 647cd6827093ceece14d6f5c374b09b0474f2f0f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 14 Oct 2013 13:06:41 -0500 Subject: [PATCH 16/34] remove timestamp and raw_rtp flag from loopback frames --- src/mod/endpoints/mod_loopback/mod_loopback.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c index 41f5849655..c6cbfc8994 100644 --- a/src/mod/endpoints/mod_loopback/mod_loopback.c +++ b/src/mod/endpoints/mod_loopback/mod_loopback.c @@ -709,6 +709,10 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch } tech_pvt->write_frame = (switch_frame_t *) pop; + + switch_clear_flag(tech_pvt->write_frame, SFF_RAW_RTP); + tech_pvt->write_frame->timestamp = 0; + tech_pvt->write_frame->codec = &tech_pvt->read_codec; *frame = tech_pvt->write_frame; tech_pvt->packet_count++; From be4dec6f155862d17bfaac928a51a06f823ae6aa Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 14 Oct 2013 17:36:17 -0500 Subject: [PATCH 17/34] Fix my snafu and allow [:port] [[: 0 && iport < 0xFFFF) { + port = (switch_port_t) iport; + } + } else if (!zstr(src_ip)) { + ip = src_ip; } - if (pip) { - switch_copy_string(ip_buf, pip, sizeof(ip_buf)); + if ( !zstr(src_ip) ) { + switch_copy_string(ip_buf, src_ip, sizeof(ip_buf)); } else { switch_find_local_ip(ip_buf, sizeof(ip_buf), NULL, AF_INET); } @@ -6150,7 +6157,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "sql_escape", "Escape a string to prevent sql injection", sql_escape, SQL_ESCAPE_SYNTAX); SWITCH_ADD_API(commands_api_interface, "status", "Show current status", status_function, ""); SWITCH_ADD_API(commands_api_interface, "strftime_tz", "Display formatted time of timezone", strftime_tz_api_function, " [|][format string]"); - SWITCH_ADD_API(commands_api_interface, "stun", "Execute STUN lookup", stun_function, "[:port]"); + SWITCH_ADD_API(commands_api_interface, "stun", "Execute STUN lookup", stun_function, "[:port] [[: [count]"); SWITCH_ADD_API(commands_api_interface, "timer_test", "Exercise FS timer", timer_test_function, TIMER_TEST_SYNTAX); From 40111509d77dee28554fb8114d64ed527cdbac90 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 15 Oct 2013 09:16:36 -0700 Subject: [PATCH 18/34] FS-5819: configure fix for new clang detection and adjust cflags for building with newest clang --- build/config/ax_compiler_vendor.m4 | 2 +- configure.in | 23 ++++++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/build/config/ax_compiler_vendor.m4 b/build/config/ax_compiler_vendor.m4 index a24a58da0f..b506b78aae 100644 --- a/build/config/ax_compiler_vendor.m4 +++ b/build/config/ax_compiler_vendor.m4 @@ -3,7 +3,7 @@ AC_DEFUN([AX_COMPILER_VENDOR], AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown # note: don't check for gcc first since some other compilers define __GNUC__ - for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do + for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ clang:__clang__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")" AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ #if !($vencpp) diff --git a/configure.in b/configure.in index c416a52c15..fd3d08bc96 100644 --- a/configure.in +++ b/configure.in @@ -167,11 +167,19 @@ SWITCH_AM_LDFLAGS="-lm" #set SOLINK variable based on compiler and host if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then SOLINK="-Bdynamic -dy -G" -elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then +elif test "x${ax_cv_c_compiler_vendor}" = "xclang" ; then case "$host" in - *darwin12.*|*darwin11.*|*darwin10.*) + *darwin*) SOLINK="-dynamic -force-flat-namespace" ;; + *) + AC_ERROR([Please update configure.in with SOLINK values for your compiler]) + ;; + + esac +elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then + case "$host" in +# older Xcode test for darwin, Xcode 4/5 use clang above *darwin*) SOLINK="-dynamic -bundle -force-flat-namespace" ;; @@ -185,7 +193,6 @@ elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then else AC_ERROR([Please update configure.in with SOLINK values for your compiler]) fi - # set DYNAMIC_LIB_EXTEN # we should really be using libtool so we don't need to do this case "$host" in @@ -716,6 +723,16 @@ if test x"$ac_cv_gcc_declaration_after_statement" = xyes; then fi CFLAGS="$saved_CFLAGS" +# Next check added for Xcode 5 and systems with clang 5 llvm 3.3 or above, extended offset must be off +AC_CACHE_CHECK([whether compiler supports -Wextended-offsetof], [ac_cv_clang_extended_offsetof], [ +AC_TRY_COMPILE([],[return 0;],[ac_cv_clang_extended_offsetof=yes],[ac_cv_clang_extended_offsetof=no]) +]) +AC_MSG_RESULT($ac_cv_clang_extended_offsetof) +if test x"$ac_cv_clang_extended_offsetof" = xyes; then + APR_ADDTO(CFLAGS, -Wno-extended-offsetof) +fi + + # Tested and fixed lot of modules, but some are untested. Will be added back when the core team decide it ready # Untested modules : mod_osp mod_soundtouch mod_sangoma_codec mod_dingaling mod_opal mod_skypopen mod_h323 mod_khomp # mod_unimrcp mod_cepstral mod_erlang_event mod_snmp mod_perl mod_java mod_managed From 0f0816aac2b579358a3c9d99daeaf17f2293a78e Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 15 Oct 2013 09:34:15 -0700 Subject: [PATCH 19/34] FS-5819: configure fix for new clang detection and adjust cflags for building with newest clang --- libs/openzap/configure.ac | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/openzap/configure.ac b/libs/openzap/configure.ac index d2c23c1091..9b41d26953 100644 --- a/libs/openzap/configure.ac +++ b/libs/openzap/configure.ac @@ -80,6 +80,15 @@ esac #set SOLINK variable based on compiler and host if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then SOLINK="-Bdynamic -dy -G" +elif test "x${ax_cv_c_compiler_vendor}" = "xclang" ; then + case "$host" in + *darwin*) + SOLINK="-dynamic -bundle -force-flat-namespace" + ;; + *) + AC_ERROR([Please update configure.in with SOLINK values for your compiler]) + ;; + esac elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then case "$host" in *darwin*) From b29a4eb39f7be61b33cf6e7883b6a000a8f986d0 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Tue, 15 Oct 2013 14:17:33 -0400 Subject: [PATCH 20/34] FS-5865 --resolve mod_rayo: fix join/unjoin IQ result for mixers --- src/mod/event_handlers/mod_rayo/mod_rayo.c | 173 +++++++++++++++++---- 1 file changed, 142 insertions(+), 31 deletions(-) diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index 92257aa2f6..df1ce007c9 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -941,10 +941,11 @@ static void rayo_call_cleanup(struct rayo_actor *actor) /* lost the race: pending join failed... send IQ result to client now. */ if (call->pending_join_request) { - iks *result = iks_new_error_detailed(call->pending_join_request, STANZA_ERROR_ITEM_NOT_FOUND, "call ended"); - RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result); - iks_delete(call->pending_join_request); + iks *request = call->pending_join_request; + iks *result = iks_new_error_detailed(request, STANZA_ERROR_ITEM_NOT_FOUND, "call ended"); call->pending_join_request = NULL; + RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result); + iks_delete(call->pending_join_request); } iks_delete(revent); @@ -1765,9 +1766,11 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, st } call->pending_join_request = iks_copy(node); if (switch_ivr_uuid_bridge(rayo_call_get_uuid(call), rayo_call_get_uuid(b_call)) != SWITCH_STATUS_SUCCESS) { - response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to bridge call"); - iks_delete(call->pending_join_request); + iks *request = call->pending_join_request; + iks *result = iks_new_error_detailed(request, STANZA_ERROR_ITEM_NOT_FOUND, "failed to bridge call"); call->pending_join_request = NULL; + RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result); + iks_delete(call->pending_join_request); } RAYO_UNLOCK(b_call); } @@ -1776,14 +1779,66 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, st /** * Execute command on session's conference + * @param session to execute conference API on + * @param conf_name of conference + * @param command to send to conference + * @param node IQ request + * @return response on failure */ -static void exec_conference_api(switch_core_session_t *session, const char *conf_name, const char *command) +static iks *exec_conference_api(switch_core_session_t *session, const char *conf_name, const char *command, iks *node) { + iks *response = NULL; switch_stream_handle_t stream = { 0 }; const char *conf_member_id = switch_channel_get_variable(switch_core_session_get_channel(session), "conference_member_id"); SWITCH_STANDARD_STREAM(stream); switch_api_execute("conference", switch_core_session_sprintf(session, "%s %s %s", conf_name, command, conf_member_id), NULL, &stream); + if (!zstr(stream.data) && strncmp("OK", stream.data, 2)) { + response = iks_new_error_detailed_printf(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "%s", stream.data); + } switch_safe_free(stream.data); + return response; +} + +/** + * Execute conference app on session + * @param session to execute conference API on + * @param command to send to conference (conference name, member flags, etc) + * @param node IQ request + * @return response on failure + */ +static iks *exec_conference_app(switch_core_session_t *session, const char *command, iks *node) +{ + iks *response = NULL; + switch_event_t *execute_event = NULL; + switch_channel_t *channel = switch_core_session_get_channel(session); + + /* conference requires local media on channel */ + if (!switch_channel_media_ready(channel) && switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { + /* shit */ + response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to start media"); + return response; + } + + /* send execute conference event to session */ + if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "conference"); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", command); + //switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event_uuid", uuid); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); + if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) { + switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); + } + + if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { + response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to join mixer (queue event failed)"); + if (execute_event) { + switch_event_destroy(&execute_event); + } + return response; + } + } + return response; } /** @@ -1803,14 +1858,20 @@ static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, s if (call->joined_id) { /* adjust join conference params */ if (!strcmp("duplex", direction)) { - exec_conference_api(session, mixer_name, "unmute"); - exec_conference_api(session, mixer_name, "undeaf"); + if ((response = exec_conference_api(session, mixer_name, "unmute", node)) || + (response = exec_conference_api(session, mixer_name, "undeaf", node))) { + return response; + } } else if (!strcmp("recv", direction)) { - exec_conference_api(session, mixer_name, "mute"); - exec_conference_api(session, mixer_name, "undeaf"); + if ((response = exec_conference_api(session, mixer_name, "mute", node)) || + (response = exec_conference_api(session, mixer_name, "undeaf", node))) { + return response; + } } else { - exec_conference_api(session, mixer_name, "unmute"); - exec_conference_api(session, mixer_name, "deaf"); + if ((response = exec_conference_api(session, mixer_name, "unmute", node)) || + (response = exec_conference_api(session, mixer_name, "deaf", node))) { + return response; + } } response = iks_new_iq_result(node); } else { @@ -1821,10 +1882,12 @@ static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, s } else if (!strcmp("recv", direction)) { conf_args = switch_core_session_sprintf(session, "%s+flags{mute}", conf_args); } - if (switch_core_session_execute_application_async(session, "conference", conf_args) == SWITCH_STATUS_SUCCESS) { - response = iks_new_iq_result(node); - } else { - response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed execute conference app"); + + call->pending_join_request = iks_copy(node); + response = exec_conference_app(session, conf_args, node); + if (response) { + iks_delete(call->pending_join_request); + call->pending_join_request = NULL; } } return response; @@ -1951,11 +2014,12 @@ static iks *unjoin_mixer(struct rayo_call *call, switch_core_session_t *session, goto done; } - /* ack command */ - response = iks_new_iq_result(node); - /* kick the member */ - exec_conference_api(session, mixer_name, "hup"); + response = exec_conference_api(session, mixer_name, "hup", node); + if (!response) { + /* ack command */ + response = iks_new_iq_result(node); + } done: @@ -2538,6 +2602,15 @@ static void on_mixer_add_member_event(struct rayo_mixer *mixer, switch_event_t * call->joined = JOINED_MIXER; call->joined_id = switch_core_strdup(RAYO_POOL(call), rayo_mixer_get_name(mixer)); + /* send IQ result to client now. */ + if (call->pending_join_request) { + iks *request = call->pending_join_request; + iks *result = iks_new_iq_result(request); + call->pending_join_request = NULL; + RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result); + iks_delete(request); + } + /* send mixer joined event to member DCP */ add_member_event = iks_new_presence("joined", RAYO_NS, RAYO_JID(call), call->dcp_jid); x = iks_find(add_member_event, "joined"); @@ -2705,14 +2778,13 @@ static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *ev call->joined_id = switch_core_strdup(RAYO_POOL(call), b_uuid); /* send IQ result to client now. */ - switch_mutex_lock(RAYO_ACTOR(call)->mutex); if (call->pending_join_request) { - iks *result = iks_new_iq_result(call->pending_join_request); - RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result); - iks_delete(call->pending_join_request); + iks *request = call->pending_join_request; + iks *result = iks_new_iq_result(request); call->pending_join_request = NULL; + RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result); + iks_delete(request); } - switch_mutex_unlock(RAYO_ACTOR(call)->mutex); /* send A-leg event */ revent = iks_new_presence("joined", RAYO_NS, @@ -2760,14 +2832,13 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t * call->joined_id = NULL; /* send IQ result to client now. */ - switch_mutex_lock(RAYO_ACTOR(call)->mutex); if (call->pending_join_request) { - iks *result = iks_new_iq_result(call->pending_join_request); - RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result); - iks_delete(call->pending_join_request); + iks *request = call->pending_join_request; + iks *result = iks_new_iq_result(request); call->pending_join_request = NULL; + RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result); + iks_delete(request); } - switch_mutex_unlock(RAYO_ACTOR(call)->mutex); /* send A-leg event */ revent = iks_new_presence("unjoined", RAYO_NS, @@ -2793,6 +2864,36 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t * } } +/** + * Handle call execute application event + * @param rclient the Rayo client + * @param event the execute event + */ +static void on_call_execute_event(struct rayo_client *rclient, switch_event_t *event) +{ + struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID")); + if (call) { + switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Application %s execute\n", switch_event_get_header(event, "Application")); + RAYO_UNLOCK(call); + } +} + +/** + * Handle call execute application complete event + * @param rclient the Rayo client + * @param event the execute complete event + */ +static void on_call_execute_complete_event(struct rayo_client *rclient, switch_event_t *event) +{ + struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID")); + if (call) { + const char *app = switch_event_get_header(event, "Application"); + switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Application %s execute complete: %s \n", + app, + switch_event_get_header(event, "Application-Response")); + RAYO_UNLOCK(call); + } +} /** * Handle events to deliver to client connection @@ -2819,6 +2920,12 @@ static void rayo_client_handle_event(struct rayo_client *rclient, switch_event_t case SWITCH_EVENT_CHANNEL_UNBRIDGE: on_call_unbridge_event(rclient, event); break; + case SWITCH_EVENT_CHANNEL_EXECUTE: + on_call_execute_event(rclient, event); + break; + case SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE: + on_call_execute_complete_event(rclient, event); + break; default: /* don't care */ break; @@ -2944,7 +3051,9 @@ static switch_status_t rayo_call_on_read_frame(switch_core_session_t *session, s switch_time_t idle_start = call->idle_start_time; int idle_duration_ms = (now - idle_start) / 1000; /* detect idle session (rayo-client has stopped controlling call) and terminate call */ - if (!rayo_call_is_joined(call) && idle_duration_ms > globals.max_idle_ms) { + if (rayo_call_is_joined(call)) { + call->idle_start_time = now; + } else if (idle_duration_ms > globals.max_idle_ms) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Ending abandoned call. idle_duration_ms = %i ms\n", idle_duration_ms); switch_channel_hangup(channel, RAYO_CAUSE_HANGUP); } @@ -3891,6 +4000,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_rayo_load) switch_event_bind(modname, SWITCH_EVENT_CHANNEL_ANSWER, NULL, route_call_event, NULL); switch_event_bind(modname, SWITCH_EVENT_CHANNEL_BRIDGE, NULL, route_call_event, NULL); switch_event_bind(modname, SWITCH_EVENT_CHANNEL_UNBRIDGE, NULL, route_call_event, NULL); + switch_event_bind(modname, SWITCH_EVENT_CHANNEL_EXECUTE, NULL, route_call_event, NULL); + switch_event_bind(modname, SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE, NULL, route_call_event, NULL); switch_event_bind(modname, SWITCH_EVENT_CHANNEL_DESTROY, NULL, on_call_end_event, NULL); From d61a5b813538bec98c8b8d99db07f9c24d056d5e Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Tue, 15 Oct 2013 15:50:45 -0400 Subject: [PATCH 21/34] FS-5773 --resolve mod_ssml: allow rendering of documents if TTS is not configured --- src/mod/formats/mod_ssml/mod_ssml.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/mod/formats/mod_ssml/mod_ssml.c b/src/mod/formats/mod_ssml/mod_ssml.c index cb29c5e79d..8b172721c7 100644 --- a/src/mod/formats/mod_ssml/mod_ssml.c +++ b/src/mod/formats/mod_ssml/mod_ssml.c @@ -692,11 +692,14 @@ static int get_file_from_macro(struct ssml_parser *parsed_data, char *to_say) static int get_file_from_voice(struct ssml_parser *parsed_data, char *to_say) { struct ssml_node *cur_node = parsed_data->cur_node; - char *file = switch_core_sprintf(parsed_data->pool, "%s%s", cur_node->tts_voice->prefix, to_say); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding <%s>: \"%s\"\n", cur_node->tag_name, file); - parsed_data->files[parsed_data->num_files].name = file; - parsed_data->files[parsed_data->num_files++].prefix = NULL; - return 1; + if (cur_node->tts_voice) { + char *file = switch_core_sprintf(parsed_data->pool, "%s%s", cur_node->tts_voice->prefix, to_say); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding <%s>: \"%s\"\n", cur_node->tag_name, file); + parsed_data->files[parsed_data->num_files].name = file; + parsed_data->files[parsed_data->num_files++].prefix = NULL; + return 1; + } + return 0; } /** @@ -708,7 +711,7 @@ static int process_cdata_tts(struct ssml_parser *parsed_data, char *data, size_t if (!len) { return IKS_OK; } - if (cur_node && cur_node->tts_voice && parsed_data->num_files < parsed_data->max_files) { + if (cur_node && parsed_data->num_files < parsed_data->max_files) { int i = 0; int empty = 1; char *to_say; @@ -728,7 +731,9 @@ static int process_cdata_tts(struct ssml_parser *parsed_data, char *data, size_t to_say[len] = '\0'; if (!cur_node->say_macro || !get_file_from_macro(parsed_data, to_say)) { /* use voice instead */ - get_file_from_voice(parsed_data, to_say); + if (!get_file_from_voice(parsed_data, to_say)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No TTS voices available to render text!\n"); + } } free(to_say); return IKS_OK; From 96b948891031950e0b17338030b11404ac3dd9a0 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 15 Oct 2013 13:07:38 -0700 Subject: [PATCH 22/34] FS-5819: configure fix for new clang detection --- configure.in | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/configure.in b/configure.in index fd3d08bc96..b3d3cc6509 100644 --- a/configure.in +++ b/configure.in @@ -723,16 +723,17 @@ if test x"$ac_cv_gcc_declaration_after_statement" = xyes; then fi CFLAGS="$saved_CFLAGS" -# Next check added for Xcode 5 and systems with clang 5 llvm 3.3 or above, extended offset must be off -AC_CACHE_CHECK([whether compiler supports -Wextended-offsetof], [ac_cv_clang_extended_offsetof], [ -AC_TRY_COMPILE([],[return 0;],[ac_cv_clang_extended_offsetof=yes],[ac_cv_clang_extended_offsetof=no]) -]) -AC_MSG_RESULT($ac_cv_clang_extended_offsetof) -if test x"$ac_cv_clang_extended_offsetof" = xyes; then - APR_ADDTO(CFLAGS, -Wno-extended-offsetof) +if test "x${ax_cv_c_compiler_vendor}" = "xclang" ; then + # Next check added for Xcode 5 and systems with clang 5 llvm 3.3 or above, extended offset must be off + AC_CACHE_CHECK([whether compiler supports -Wextended-offsetof], [ac_cv_clang_extended_offsetof], [ + AC_TRY_COMPILE([],[return 0;],[ac_cv_clang_extended_offsetof=yes],[ac_cv_clang_extended_offsetof=no]) + ]) + AC_MSG_RESULT($ac_cv_clang_extended_offsetof) + if test x"$ac_cv_clang_extended_offsetof" = xyes; then + APR_ADDTO(CFLAGS, -Wno-extended-offsetof) + fi fi - # Tested and fixed lot of modules, but some are untested. Will be added back when the core team decide it ready # Untested modules : mod_osp mod_soundtouch mod_sangoma_codec mod_dingaling mod_opal mod_skypopen mod_h323 mod_khomp # mod_unimrcp mod_cepstral mod_erlang_event mod_snmp mod_perl mod_java mod_managed From bbabf652f8746149e1f65ef9d5274851e81d7de2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 16 Oct 2013 14:33:25 -0400 Subject: [PATCH 23/34] FS-5861 regression typo --- src/mod/applications/mod_dptools/mod_dptools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 5fe2c57e5b..8d7b5c6f37 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -287,7 +287,7 @@ SWITCH_STANDARD_APP(clear_digit_action_function) char *target_str; switch_digit_action_target_t target = DIGIT_TARGET_SELF; - if (zstr(realm)) { + if (zstr((char *)data)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "clear_digit_action called with no args"); return; } From f8abd0cc1d2cbed9a79b3b00a32387cead0c075e Mon Sep 17 00:00:00 2001 From: Marc Olivier Chouinard Date: Mon, 16 Sep 2013 22:00:35 -0400 Subject: [PATCH 24/34] Fix bootstrap from the removal of mod_html5 in previous commit and cleanup some other reference to it --- build/modules.conf.in | 3 +-- debian/control-modules | 4 ---- debian/copyright | 1 - src/mod/.gitignore | 3 --- 4 files changed, 1 insertion(+), 10 deletions(-) diff --git a/build/modules.conf.in b/build/modules.conf.in index d60b1211ef..3f77b125b5 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -82,7 +82,6 @@ dialplans/mod_dialplan_xml #endpoints/mod_dingaling #endpoints/mod_gsmopen #endpoints/mod_h323 -#endpoints/mod_html5 #endpoints/mod_khomp endpoints/mod_loopback #endpoints/mod_opal @@ -152,4 +151,4 @@ xml_int/mod_xml_scgi #../../libs/openzap/mod_openzap ## Experimental Modules (don't cry if they're broken) -#../../contrib/mod/xml_int/mod_xml_odbc \ No newline at end of file +#../../contrib/mod/xml_int/mod_xml_odbc diff --git a/debian/control-modules b/debian/control-modules index 57051e5638..61f0b33a80 100644 --- a/debian/control-modules +++ b/debian/control-modules @@ -395,10 +395,6 @@ Description: mod_h323 Adds mod_h323. Build-Depends: libopenh323-dev | libh323plus-dev, libpt-dev -Module: endpoints/mod_html5 -Description: HTML5 endpoint module - This module adds support for HTML5 technologies such as WebRTC. - Module: endpoints/mod_khomp Description: mod_khomp Adds mod_khomp. diff --git a/debian/copyright b/debian/copyright index fcea146b7a..d7ea35053f 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1765,7 +1765,6 @@ License: GPL-2+ Files: src/mod/endpoints/mod_rtmp/rtmp.c src/mod/endpoints/mod_rtmp/mod_rtmp.[ch] src/mod/endpoints/mod_rtmp/rtmp_sig.c - src/mod/endpoints/mod_html5/mod_html5.c src/mod/endpoints/mod_rtmp/rtmp_tcp.c Copyright: 2011-2012, Barracuda Networks Inc. License: MPL-1.1 diff --git a/src/mod/.gitignore b/src/mod/.gitignore index bfcc02ab70..78158b6fd1 100644 --- a/src/mod/.gitignore +++ b/src/mod/.gitignore @@ -36,7 +36,6 @@ /codecs/mod_vp8/Makefile /dialplans/mod_dialplan_asterisk/Makefile /dialplans/mod_dialplan_xml/Makefile -/endpoints/mod_html5/mod_html5.log /endpoints/mod_portaudio/Makefile /endpoints/mod_portaudio/Makefile.in /endpoints/mod_portaudio/mod_portaudio.log @@ -49,8 +48,6 @@ /endpoints/mod_sofia/Makefile /endpoints/mod_sofia/Makefile.in /endpoints/mod_sofia/mod_sofia.log -/endpoints/mod_html5/Makefile -/endpoints/mod_html5/Makefile.in /event_handlers/mod_erlang_event/Makefile /event_handlers/mod_event_socket/Makefile /formats/mod_native_file/Makefile From 697a6fcb71a127576b7c44f7b7c0943fc0b32a8b Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Thu, 17 Oct 2013 09:42:52 -0400 Subject: [PATCH 25/34] FS-5884 --resolve mod_rayo: detect unjoin mismatch --- src/mod/event_handlers/mod_rayo/mod_rayo.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index df1ce007c9..de89a32bb1 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -1793,7 +1793,7 @@ static iks *exec_conference_api(switch_core_session_t *session, const char *conf SWITCH_STANDARD_STREAM(stream); switch_api_execute("conference", switch_core_session_sprintf(session, "%s %s %s", conf_name, command, conf_member_id), NULL, &stream); if (!zstr(stream.data) && strncmp("OK", stream.data, 2)) { - response = iks_new_error_detailed_printf(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "%s", stream.data); + response = iks_new_error_detailed_printf(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "%s", stream.data); } switch_safe_free(stream.data); return response; @@ -2047,7 +2047,13 @@ static iks *on_rayo_unjoin(struct rayo_actor *call, struct rayo_message *msg, vo response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending"); } else if (!RAYO_CALL(call)->joined) { /* not joined to anything */ - response = iks_new_error(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE); + response = iks_new_error_detailed(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE, "not joined to anything"); + } else if (RAYO_CALL(call)->joined == JOINED_MIXER && !zstr(call_uri)) { + /* joined to mixer, not call */ + response = iks_new_error_detailed(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE, "not joined to call"); + } else if (RAYO_CALL(call)->joined == JOINED_CALL && !zstr(mixer_name)) { + /* joined to call, not mixer */ + response = iks_new_error_detailed(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE, "not joined to mixer"); } else if (!zstr(call_uri)) { response = unjoin_call(RAYO_CALL(call), session, msg, call_uri); } else if (!zstr(mixer_name)) { From 67c0f489bcea45314472231b2dbc20404c0b9bd5 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 17 Oct 2013 13:18:26 +0000 Subject: [PATCH 26/34] Ensure that flite gets configured before building Without this change, we would only configure flite if its Makefile did not exist. However in the tarball for flite (v1.5.4), there is a Makefile even before you run configure. So the only reason this worked at all was because make was calculating the rules to run before downloading and extracting flite. If you build flite without configuring it first, you get a flite with ALSA symbols that doesn't load in FS. In discussion with the flite guys, they indicated that the presence of the Makefile in the tarball is indeed intended. This change has the side-effect of fixing mod_flite in the Debian packages. FS-5873 --resolve --- src/mod/asr_tts/mod_flite/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/asr_tts/mod_flite/Makefile b/src/mod/asr_tts/mod_flite/Makefile index c93b48c1ca..360eb611e1 100644 --- a/src/mod/asr_tts/mod_flite/Makefile +++ b/src/mod/asr_tts/mod_flite/Makefile @@ -21,12 +21,12 @@ $(MODNAME).lo: $(FLITE_A) $(FLITE_DIR): $(GETLIB) $(FLITE)-current.tar.bz2 -$(FLITE_BUILDDIR)/Makefile: $(FLITE_DIR) +$(FLITE_BUILDDIR)/.stamp-configure: $(FLITE_DIR) mkdir -p $(FLITE_BUILDDIR) cd $(FLITE_BUILDDIR) && $(DEFAULT_VARS) $(FLITE_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(FLITE_DIR) --with-audio=none --with-pic --disable-shared - $(TOUCH_TARGET) + test -f Makefile && touch $@ -$(FLITE_A): $(FLITE_DIR) $(FLITE_BUILDDIR)/Makefile +$(FLITE_A): $(FLITE_DIR) $(FLITE_BUILDDIR)/.stamp-configure cd $(FLITE_BUILDDIR) && $(MAKE) -j1 test -d $(FLITE_LIBDIR) || mkdir $(FLITE_LIBDIR) TARGET_OS=`grep TARGET_OS $(FLITE_BUILDDIR)/config/config | sed "s/^.*= //"` ;\ From d98a1eb4f3914fe5ca86187e7431c90067d44f56 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 17 Oct 2013 21:05:27 +0500 Subject: [PATCH 27/34] FS-5883 --resolve --- src/mod/endpoints/mod_sofia/mod_sofia.h | 2 + src/mod/endpoints/mod_sofia/sofia_glue.c | 58 ++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index cfd14aba4d..567ee00ae5 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -718,6 +718,8 @@ struct private_object { sofia_private_t *sofia_private; uint8_t flags[TFLAG_MAX]; switch_payload_t agreed_pt; + int channels; + int adv_channels; switch_payload_t audio_recv_pt; switch_payload_t video_recv_pt; switch_core_session_t *session; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 146d63b973..e54beabd3d 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -39,6 +39,15 @@ switch_cache_db_handle_t *_sofia_glue_get_db_handle(sofia_profile_t *profile, const char *file, const char *func, int line); #define sofia_glue_get_db_handle(_p) _sofia_glue_get_db_handle(_p, __FILE__, __SWITCH_FUNC__, __LINE__) +static int get_channels(const switch_codec_implementation_t *imp) +{ + if (!strcasecmp(imp->iananame, "opus")) { + return 2; /* IKR???*/ + } + + return imp->number_of_channels; +} + void sofia_glue_set_udptl_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist) { char buf[2048] = ""; @@ -308,7 +317,14 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, } if (tech_pvt->ianacodes[i] > 95 || verbose_sdp) { - switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate); + int channels = get_channels(imp); + + if (channels > 1) { + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate, channels); + + } else { + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate); + } } if (fmtp) { @@ -530,7 +546,15 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n"); rate = tech_pvt->rm_rate; - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate); + + if (tech_pvt->adv_channels > 1) { + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", + tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate, tech_pvt->adv_channels); + } else { + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", + tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate); + } + if (fmtp_out) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->agreed_pt, fmtp_out); } @@ -735,6 +759,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; char *fmtp = NULL; uint32_t ianacode = tech_pvt->ianacodes[i]; + int channels = 1; if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) { continue; @@ -751,9 +776,15 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch rate = imp->samples_per_second; } - - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", ianacode, imp->iananame, - imp->samples_per_second); + channels = get_channels(imp); + + if (channels > 1) { + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", ianacode, imp->iananame, + imp->samples_per_second, channels); + } else { + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", ianacode, imp->iananame, + imp->samples_per_second); + } if (!zstr(ov_fmtp)) { fmtp = (char *) ov_fmtp; @@ -5314,6 +5345,23 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip); switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); tech_pvt->audio_recv_pt = (switch_payload_t)map->rm_pt; + + if (!strcasecmp((char *) map->rm_encoding, "opus")) { + if (tech_pvt->channels == 1) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid SDP for opus. Don't ask.. but it needs a /2\n"); + tech_pvt->adv_channels = 1; + } else { + tech_pvt->adv_channels = 2; /* IKR ???*/ + } + if (!zstr((char *) map->rm_fmtp) && switch_stristr("stereo=1", (char *) map->rm_fmtp)) { + tech_pvt->channels = 2; + } else { + tech_pvt->channels = 1; + } + } else { + tech_pvt->adv_channels = tech_pvt->channels; + } + if (!switch_true(mirror) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && From d5d45281f381196b30063d9fbed8beaa17dc950f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 17 Oct 2013 12:33:55 -0400 Subject: [PATCH 28/34] change dtmf vol to 13 --- src/switch_rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 39d1dd5303..f765ecf973 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -2777,7 +2777,7 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) rtp_session->dtmf_data.out_digit_dur = rdigit->duration; rtp_session->dtmf_data.out_digit = rdigit->digit; rtp_session->dtmf_data.out_digit_packet[0] = (unsigned char) switch_char_to_rfc2833(rdigit->digit); - rtp_session->dtmf_data.out_digit_packet[1] = 7; + rtp_session->dtmf_data.out_digit_packet[1] = 13; rtp_session->dtmf_data.out_digit_packet[2] = (unsigned char) (rtp_session->dtmf_data.out_digit_sub_sofar >> 8); rtp_session->dtmf_data.out_digit_packet[3] = (unsigned char) rtp_session->dtmf_data.out_digit_sub_sofar; From ddf44c089a7d31b13f12deb8e7c7751f148fb056 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 17 Oct 2013 03:05:12 +0000 Subject: [PATCH 29/34] Fix build of apr-util expat with libtool2 Applied patch from: http://people.apache.org/~rjung/patches/expat-libtool2.patch The failure that results from this seems to occur non-deterministically. FS-3185 --resolve --- libs/apr-util/xml/expat/buildconf.sh | 34 +++++++++++++++++----------- libs/apr-util/xml/expat/configure.in | 1 + 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/libs/apr-util/xml/expat/buildconf.sh b/libs/apr-util/xml/expat/buildconf.sh index 1f5789dc07..9050a0282a 100755 --- a/libs/apr-util/xml/expat/buildconf.sh +++ b/libs/apr-util/xml/expat/buildconf.sh @@ -28,26 +28,34 @@ rm -rf aclocal.m4 libtool.m4 ltsugar.m4 autom4te*.cache $libtoolize --copy --automake # -# Build aclocal.m4 from libtool's libtool.m4 +# find libtool.m4 # -if [ -f libtool.m4 ]; then - ltfile=libtool.m4 -else +if [ ! -f libtool.m4 ]; then ltpath=`dirname $libtoolize` ltfile=${LIBTOOL_M4-`cd $ltpath/../share/aclocal ; pwd`/libtool.m4} + if [ -f $ltfile ]; then + echo "libtool.m4 found at $ltfile" + cp $ltfile libtool.m4 + else + echo "libtool.m4 not found - aborting!" + exit 1 + fi fi -echo "Incorporating $ltfile into aclocal.m4 ..." + +# +# Build aclocal.m4 from libtool's m4 files +# echo "dnl THIS FILE IS AUTOMATICALLY GENERATED BY buildconf.sh" > aclocal.m4 echo "dnl edits here will be lost" >> aclocal.m4 -cat $ltfile >> aclocal.m4 -if [ -f ltsugar.m4 ]; then - echo "Incorporating ltsugar.m4 into aclocal.m4 ..." - cat ltsugar.m4 >> aclocal.m4 -fi - -# Clean up again -rm -f libtool.m4 ltsugar.m4 +for m4file in libtool.m4 ltsugar.m4 ltoptions.m4 ltversion.m4 lt~obsolete.m4 +do + if [ -f $m4file ]; then + echo "Incorporating $m4file into aclocal.m4 ..." + cat $m4file >> aclocal.m4 + rm -f $m4file + fi +done cross_compile_warning="warning: AC_TRY_RUN called without default to allow cross compiling" diff --git a/libs/apr-util/xml/expat/configure.in b/libs/apr-util/xml/expat/configure.in index 478d8d5313..f808df4cce 100644 --- a/libs/apr-util/xml/expat/configure.in +++ b/libs/apr-util/xml/expat/configure.in @@ -12,6 +12,7 @@ dnl AC_INIT(Makefile.in) AC_CONFIG_AUX_DIR(conftools) +AC_CONFIG_MACRO_DIR(.) dnl dnl Follow the GNU/Linux convention of odd number minor version for From 0c999603b9bd52d32252fa2404cdc975105d3b97 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Fri, 18 Oct 2013 09:47:30 -0400 Subject: [PATCH 30/34] mod_rayo: fix hangup after unjoining bridged calls --- src/mod/event_handlers/mod_rayo/mod_rayo.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index de89a32bb1..f653e9fc68 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -3152,8 +3152,10 @@ done: if (ok) { switch_channel_set_variable(channel, "hangup_after_bridge", "false"); - switch_channel_set_variable(channel, "transfer_after_bridge", "false"); - switch_channel_set_variable(channel, "park_after_bridge", "true"); + switch_channel_set_variable(channel, "transfer_after_bridge", ""); + switch_channel_set_variable(channel, "park_after_bridge", "false"); + switch_channel_set_variable(channel, "exec_after_bridge_app", "park"); + switch_channel_set_variable(channel, "exec_after_bridge_arg", ""); switch_channel_set_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE, "-1"); /* required so that output mixing works */ switch_core_event_hook_add_read_frame(session, rayo_call_on_read_frame); if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { From 91e9e3b587124f2aca3ee9bf0682c767d279eda2 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Fri, 18 Oct 2013 15:14:50 -0400 Subject: [PATCH 31/34] mod_rayo: allow unjoin of call without specifying call-uri, fix unjoin of call on hold so that b-leg is not hung up, allow unjoin command to b-leg --- src/mod/event_handlers/mod_rayo/mod_rayo.c | 82 +++++++++++++--------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index f653e9fc68..6dd58d29c6 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -1972,11 +1972,8 @@ static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session, { iks *node = msg->payload; iks *response = NULL; - const char *bleg_uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_BRIDGE_UUID_VARIABLE); - const char *bleg_uri = switch_core_session_sprintf(session, "xmpp:%s@%s", bleg_uuid ? bleg_uuid : "", RAYO_JID(globals.server)); - /* bleg must match call_uri */ - if (!zstr(bleg_uri) && !strcmp(bleg_uri, call_uri)) { + if (!strcmp(call_uri, call->joined_id)) { /* unbridge call */ call->pending_join_request = iks_copy(node); switch_ivr_park_session(session); @@ -2781,7 +2778,7 @@ static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *ev iks *joined; call->joined = JOINED_CALL; - call->joined_id = switch_core_strdup(RAYO_POOL(call), b_uuid); + call->joined_id = switch_core_sprintf(RAYO_POOL(call), "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server)); /* send IQ result to client now. */ if (call->pending_join_request) { @@ -2792,6 +2789,29 @@ static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *ev iks_delete(request); } + b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid); + if (b_call) { + b_call->joined = JOINED_CALL; + b_call->joined_id = switch_core_sprintf(RAYO_POOL(b_call), "xmpp:%s@s", a_uuid, RAYO_JID(globals.server)); + + /* send IQ result to client now. */ + if (b_call->pending_join_request) { + iks *request = b_call->pending_join_request; + iks *result = iks_new_iq_result(request); + b_call->pending_join_request = NULL; + RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result); + iks_delete(request); + } + + /* send B-leg event */ + revent = iks_new_presence("joined", RAYO_NS, RAYO_JID(b_call), rayo_call_get_dcp_jid(b_call)); + joined = iks_find(revent, "joined"); + iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", a_uuid, RAYO_JID(globals.server)); + + RAYO_SEND_MESSAGE(b_call, rayo_call_get_dcp_jid(b_call), revent); + RAYO_UNLOCK(b_call); + } + /* send A-leg event */ revent = iks_new_presence("joined", RAYO_NS, switch_event_get_header(event, "variable_rayo_call_jid"), @@ -2801,19 +2821,6 @@ static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *ev RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent); - /* send B-leg event */ - b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid); - if (b_call) { - revent = iks_new_presence("joined", RAYO_NS, RAYO_JID(b_call), rayo_call_get_dcp_jid(b_call)); - joined = iks_find(revent, "joined"); - iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", a_uuid, RAYO_JID(globals.server)); - - b_call->joined = JOINED_CALL; - b_call->joined_id = switch_core_strdup(RAYO_POOL(b_call), a_uuid); - - RAYO_SEND_MESSAGE(b_call, rayo_call_get_dcp_jid(b_call), revent); - RAYO_UNLOCK(b_call); - } RAYO_UNLOCK(call); } } @@ -2846,6 +2853,28 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t * iks_delete(request); } + b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid); + if (b_call) { + b_call->joined = 0; + b_call->joined_id = NULL; + + /* send IQ result to client now. */ + if (b_call->pending_join_request) { + iks *request = b_call->pending_join_request; + iks *result = iks_new_iq_result(request); + b_call->pending_join_request = NULL; + RAYO_SEND_REPLY(b_call, iks_find_attrib_soft(request, "from"), result); + iks_delete(request); + } + + /* send B-leg event */ + revent = iks_new_presence("unjoined", RAYO_NS, RAYO_JID(b_call), rayo_call_get_dcp_jid(b_call)); + joined = iks_find(revent, "unjoined"); + iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", a_uuid, RAYO_JID(globals.server)); + RAYO_SEND_MESSAGE(b_call, rayo_call_get_dcp_jid(b_call), revent); + RAYO_UNLOCK(b_call); + } + /* send A-leg event */ revent = iks_new_presence("unjoined", RAYO_NS, switch_event_get_header(event, "variable_rayo_call_jid"), @@ -2854,18 +2883,6 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t * iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server)); RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent); - /* send B-leg event */ - b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid); - if (b_call) { - revent = iks_new_presence("unjoined", RAYO_NS, RAYO_JID(b_call), rayo_call_get_dcp_jid(b_call)); - joined = iks_find(revent, "unjoined"); - iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", a_uuid, RAYO_JID(globals.server)); - RAYO_SEND_MESSAGE(b_call, rayo_call_get_dcp_jid(b_call), revent); - - b_call->joined = 0; - b_call->joined_id = NULL; - RAYO_UNLOCK(b_call); - } RAYO_UNLOCK(call); } } @@ -3153,9 +3170,8 @@ done: if (ok) { switch_channel_set_variable(channel, "hangup_after_bridge", "false"); switch_channel_set_variable(channel, "transfer_after_bridge", ""); - switch_channel_set_variable(channel, "park_after_bridge", "false"); - switch_channel_set_variable(channel, "exec_after_bridge_app", "park"); - switch_channel_set_variable(channel, "exec_after_bridge_arg", ""); + switch_channel_set_variable(channel, "park_after_bridge", "true"); + switch_channel_set_variable(channel, "hold_hangup_xfer_exten", "foo"); /* Icky hack to prevent unjoin of call on hold from hanging up b-leg. park_after_bridge will take precedence over the transfer_after_bridge variable that gets set by this var */ switch_channel_set_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE, "-1"); /* required so that output mixing works */ switch_core_event_hook_add_read_frame(session, rayo_call_on_read_frame); if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { From f075d258194732e0e625cb6d6e97566efced3438 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 18 Oct 2013 08:17:50 +0000 Subject: [PATCH 32/34] Add freeswitch-all debian package This package bundles all modules and extras into a single DEB. This can have some advantages in terms of convenience and speed of apt operations. --- debian/.gitignore | 1 + debian/bootstrap.sh | 100 +++++++++++++++++++++++++++++++++++++++----- debian/rules | 1 + 3 files changed, 91 insertions(+), 11 deletions(-) diff --git a/debian/.gitignore b/debian/.gitignore index 81fc750bf9..896d998162 100644 --- a/debian/.gitignore +++ b/debian/.gitignore @@ -5,6 +5,7 @@ /files /modules.conf /modules_.conf +/freeswitch-all.* /freeswitch-autotools.install /freeswitch-mod-*.install /freeswitch-conf-*.install diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 5843872904..2f9665a5c8 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -6,7 +6,7 @@ mod_dir="../src/mod" conf_dir="../conf" lang_dir="../conf/vanilla/lang" fs_description="FreeSWITCH is a scalable open source cross-platform telephony platform designed to route and interconnect popular communication protocols using audio, video, text or any other form of media." -mod_build_depends="." +mod_build_depends="." mod_depends="." mod_recommends="." mod_suggests="." supported_distros="squeeze wheezy jessie sid" avoid_mods=( applications/mod_limit @@ -204,6 +204,26 @@ EOF print_core_control () { cat <= 1.0.8), + freeswitch-sounds-en-us-callie (>= 1.0.25) | freeswitch-sounds, + $(debian_wrap "${mod_depends}") +Recommends: + $(debian_wrap "${mod_recommends}") +Suggests: freeswitch-all-dbg, + $(debian_wrap "${mod_suggests}") +Description: Cross-Platform Scalable Multi-Protocol Soft Switch + $(debian_wrap "${fs_description}") + . + This package contains FreeSWITCH and all modules and extras. + Package: freeswitch Architecture: any Depends: \${shlibs:Depends}, \${perl:Depends}, \${misc:Depends}, @@ -616,6 +636,16 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch This is a metapackage which depends on all mod_say languages for FreeSWITCH. +Package: freeswitch-all-dbg +Section: debug +Priority: extra +Architecture: any +Depends: \${misc:Depends}, freeswitch (= \${binary:Version}) +Description: debugging symbols for FreeSWITCH + $(debian_wrap "${fs_description}") + . + This package contains debugging symbols for FreeSWITCH. + Package: freeswitch-dbg Section: debug Priority: extra @@ -890,6 +920,7 @@ gencontrol_per_cat () { geninstall_per_mod () { local f=freeswitch-${module_name//_/-}.install (print_edit_warning; print_mod_install "$module_name") > $f + print_mod_install "$module_name" >> freeswitch-all.install test -f $f.tmpl && cat $f.tmpl >> $f } @@ -912,6 +943,7 @@ genconf () { local p=freeswitch-conf-${conf//_/-} local f=$p.install (print_edit_warning; print_conf_install) > $f + print_conf_install >> freeswitch-all.install test -f $f.tmpl && cat $f.tmpl >> $f local f=$p.lintian-overrides (print_edit_warning; print_conf_overrides "$p") > $f @@ -923,26 +955,50 @@ genlang () { local p=freeswitch-lang-${lang//_/-} local f=$p.install (print_edit_warning; print_lang_install) > $f + print_lang_install >> freeswitch-all.install test -f $f.tmpl && cat $f.tmpl >> $f local f=$p.lintian-overrides (print_edit_warning; print_lang_overrides "$p") > $f test -f $f.tmpl && cat $f.tmpl >> $f } -accumulate_build_depends () { +accumulate_mod_deps () { local x="" + # build-depends if [ -n "$(eval echo \$build_depends_$codename)" ]; then x="$(eval echo \$build_depends_$codename)" - else - x="${build_depends}" - fi + else x="${build_depends}"; fi if [ -n "$x" ]; then if [ ! "$mod_build_depends" = "." ]; then mod_build_depends="${mod_build_depends}, ${x}" - else - mod_build_depends="${x}" - fi - fi + else mod_build_depends="${x}"; fi; fi + # depends + if [ -n "$(eval echo \$depends_$codename)" ]; then + x="$(eval echo \$depends_$codename)" + else x="${depends}"; fi + x="$(echo "$x" | sed 's/, \?/\n/g' | grep -v '^freeswitch' | tr '\n' ',' | sed -e 's/,$//' -e 's/,/, /g')" + if [ -n "$x" ]; then + if [ ! "$mod_depends" = "." ]; then + mod_depends="${mod_depends}, ${x}" + else mod_depends="${x}"; fi; fi + # recommends + if [ -n "$(eval echo \$recommends_$codename)" ]; then + x="$(eval echo \$recommends_$codename)" + else x="${recommends}"; fi + x="$(echo "$x" | sed 's/, \?/\n/g' | grep -v '^freeswitch' | tr '\n' ',' | sed -e 's/,$//' -e 's/,/, /g')" + if [ -n "$x" ]; then + if [ ! "$mod_recommends" = "." ]; then + mod_recommends="${mod_recommends}, ${x}" + else mod_recommends="${x}"; fi; fi + # suggests + if [ -n "$(eval echo \$suggests_$codename)" ]; then + x="$(eval echo \$suggests_$codename)" + else x="${suggests}"; fi + x="$(echo "$x" | sed 's/, \?/\n/g' | grep -v '^freeswitch' | tr '\n' ',' | sed -e 's/,$//' -e 's/,/, /g')" + if [ -n "$x" ]; then + if [ ! "$mod_suggests" = "." ]; then + mod_suggests="${mod_suggests}, ${x}" + else mod_suggests="${x}"; fi; fi } genmodctl_new_mod () { @@ -1108,10 +1164,13 @@ echo "Generating control-modules.gen as sanity check..." >&2 map_modules ':' 'genmodctl_cat' 'genmodctl_mod' \ ) > control-modules.gen -echo "Accumulating build dependencies from modules..." >&2 -map_modules 'mod_filter' '' 'accumulate_build_depends' +echo "Accumulating dependencies from modules..." >&2 +map_modules 'mod_filter' '' 'accumulate_mod_deps' echo "Generating debian/..." >&2 > control +> freeswitch-all.install +(print_edit_warning; print_mod_overrides "freeswitch-all") \ + > freeswitch-all.lintian-overrides (print_edit_warning; print_source_control; print_core_control) >> control echo "Generating debian/ (conf)..." >&2 (echo "### conf"; echo) >> control @@ -1125,6 +1184,25 @@ print_edit_warning > modules_.conf map_modules "mod_filter" \ "gencontrol_per_cat genmodules_per_cat" \ "gencontrol_per_mod geninstall_per_mod genoverrides_per_mod genmodules_per_mod" +echo "Generating debian/ (-all package)..." >&2 +grep -e '^Package:' control | grep -v '^freeswitch-all$' | while xread l; do + m="${l#*: }" + f=$m.install + if [ -s $f ]; then + grep -v '^##\|^$' $f | while xread x; do + if ! grep -e "$x" freeswitch-all.install >/dev/null; then + printf '%s\n' "$x" >> freeswitch-all.install + fi + done + fi +done +for x in postinst postrm preinst prerm; do + cp -a freeswitch.$x freeswitch-all.$x +done +cp -a freeswitch-doc.docs freeswitch-all.docs +#cp -a freeswitch-systemd.freeswitch.service freeswitch-all.freeswitch.service +cp -a freeswitch-sysvinit.freeswitch.default freeswitch-all.freeswitch.default +cp -a freeswitch-sysvinit.freeswitch.init freeswitch-all.freeswitch.init echo "Generating additional lintian overrides..." >&2 grep -e '^Package:' control | while xread l; do diff --git a/debian/rules b/debian/rules index 7da66a8eaa..7d7d50fd71 100755 --- a/debian/rules +++ b/debian/rules @@ -104,6 +104,7 @@ override_dh_auto_install: override_dh_installinit: dh_installinit -pfreeswitch-sysvinit --name=freeswitch + dh_installinit -pfreeswitch-all --name=freeswitch debian-bootstrap: debian/.stamp-bootstrap debian/.stamp-bootstrap: From c4b2d79159d69294abf57535eb1de328dd685637 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 18 Oct 2013 20:14:42 +0000 Subject: [PATCH 33/34] Limit version of packages we replace --- debian/bootstrap.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 2f9665a5c8..b9776f14ac 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -207,10 +207,16 @@ cat <= 1.0.8), freeswitch-sounds-en-us-callie (>= 1.0.25) | freeswitch-sounds, From 44680b31d94a34e7864b40e53699abde8f0f8ab6 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 19 Oct 2013 18:42:21 +0000 Subject: [PATCH 34/34] Install perl module files needed by mod_perl FS-5892 --resolve --- debian/freeswitch-mod-perl.install.tmpl | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 debian/freeswitch-mod-perl.install.tmpl diff --git a/debian/freeswitch-mod-perl.install.tmpl b/debian/freeswitch-mod-perl.install.tmpl new file mode 100644 index 0000000000..5b2fe712f3 --- /dev/null +++ b/debian/freeswitch-mod-perl.install.tmpl @@ -0,0 +1,2 @@ +debian/tmp/usr/perl/freeswitch.pm /usr/lib/perl5 +debian/tmp/usr/perl/freeswitch.so /usr/lib/perl5/auto/freeswitch