From ad2344cb842f2e582c129f8d621d8f93757177ea Mon Sep 17 00:00:00 2001 From: Vladimir Ralev Date: Thu, 8 Nov 2018 23:59:59 +0200 Subject: [PATCH 01/24] FS-10534 [mod_loopback] Add null pointer check to avoid crashing loopbacks --- src/mod/endpoints/mod_loopback/mod_loopback.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c index 1ef3690578..73cc080266 100644 --- a/src/mod/endpoints/mod_loopback/mod_loopback.c +++ b/src/mod/endpoints/mod_loopback/mod_loopback.c @@ -831,7 +831,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc if (switch_test_flag(frame, SFF_CNG) || (switch_test_flag(tech_pvt, TFLAG_BOWOUT) && switch_test_flag(tech_pvt, TFLAG_BOWOUT_USED))) { switch_core_timer_sync(&tech_pvt->timer); - switch_core_timer_sync(&tech_pvt->other_tech_pvt->timer); + if (tech_pvt->other_tech_pvt) switch_core_timer_sync(&tech_pvt->other_tech_pvt->timer); return SWITCH_STATUS_SUCCESS; } @@ -991,10 +991,10 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s done = 1; switch_set_flag(tech_pvt, TFLAG_CLEAR); - switch_set_flag(tech_pvt->other_tech_pvt, TFLAG_CLEAR); + if (tech_pvt->other_tech_pvt) switch_set_flag(tech_pvt->other_tech_pvt, TFLAG_CLEAR); switch_core_timer_sync(&tech_pvt->timer); - switch_core_timer_sync(&tech_pvt->other_tech_pvt->timer); + if (tech_pvt->other_tech_pvt) switch_core_timer_sync(&tech_pvt->other_tech_pvt->timer); } break; default: From e7c63eec0c4a66741f5035efba47260b8caf05a8 Mon Sep 17 00:00:00 2001 From: Christian Schmidt Date: Wed, 5 Dec 2018 22:10:25 +0100 Subject: [PATCH 02/24] FS-11552: [mod_v8] Crash when accessing props of dead session --- src/mod/languages/mod_v8/src/fssession.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/mod/languages/mod_v8/src/fssession.cpp b/src/mod/languages/mod_v8/src/fssession.cpp index a34406a493..c8a315ced0 100644 --- a/src/mod/languages/mod_v8/src/fssession.cpp +++ b/src/mod/languages/mod_v8/src/fssession.cpp @@ -1530,11 +1530,23 @@ JS_SESSION_GET_PROPERTY_IMPL(GetProperty) info.GetReturnValue().Set(Integer::New(info.GetIsolate(), this->_cause)); } } else if (!strcmp(prop, "name")) { - info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), switch_channel_get_name(channel))); + if (channel) { + info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), switch_channel_get_name(channel))); + } else { + info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), "")); + } } else if (!strcmp(prop, "uuid")) { - info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), switch_channel_get_uuid(channel))); + if (channel) { + info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), switch_channel_get_uuid(channel))); + } else { + info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), "")); + } } else if (!strcmp(prop, "state")) { - info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), switch_channel_state_name(switch_channel_get_state(channel)))); + if (channel) { + info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), switch_channel_state_name(switch_channel_get_state(channel)))); + } else { + info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), "")); + } } else if (!strcmp(prop, "dialplan")) { if (caller_profile) { info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), caller_profile->dialplan)); From 85cfd5b5ab1b4f183b23a5de627b5e3588f373f7 Mon Sep 17 00:00:00 2001 From: netoguimaraes Date: Wed, 26 Dec 2018 17:16:36 -0300 Subject: [PATCH 03/24] FS-11584: [verto_communicator] make user able to login using url params --- .../vertoControllers/controllers/LoginController.js | 13 ++++++++++++- .../vertoControllers/controllers/MainController.js | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/html5/verto/verto_communicator/src/vertoControllers/controllers/LoginController.js b/html5/verto/verto_communicator/src/vertoControllers/controllers/LoginController.js index d6f1d0366f..d9caa5c1f0 100644 --- a/html5/verto/verto_communicator/src/vertoControllers/controllers/LoginController.js +++ b/html5/verto/verto_communicator/src/vertoControllers/controllers/LoginController.js @@ -11,7 +11,18 @@ } } preRoute(); - + + var name = $location.search().name; + var email = $location.search().email; + var skipPreview = $location.search().skipPreview; + + if (name && email) { + verto.data.name = name; + verto.data.email = email; + $scope.login(true, skipPreview); + return; + } + verto.data.name = $scope.storage.data.name; verto.data.email = $scope.storage.data.email; diff --git a/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js b/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js index 066b69b33e..5534a6b817 100644 --- a/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js +++ b/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js @@ -77,7 +77,7 @@ * Login the user to verto server and * redirects him to dialpad page. */ - $scope.login = function(redirect) { + $rootScope.login = function(redirect, skipPreview = false) { if(redirect == undefined) { redirect = true; } @@ -97,7 +97,7 @@ verto.testSpeed(); } - if (redirect && storage.data.preview) { + if (redirect && storage.data.preview && !skipPreview) { $location.path('/loading'); } else if (redirect) { $location.path('/dialpad'); From c3f80bb78dc5b0b43a553c621facf01c0bed7ee4 Mon Sep 17 00:00:00 2001 From: Mike Jerris Date: Wed, 2 Jan 2019 15:07:19 -0500 Subject: [PATCH 04/24] FS-11579: [mod_signalwire] use detected curl cflags and libraries to link mod_signalwire --- src/mod/applications/mod_signalwire/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_signalwire/Makefile.am b/src/mod/applications/mod_signalwire/Makefile.am index d46251b832..405dea9807 100644 --- a/src/mod/applications/mod_signalwire/Makefile.am +++ b/src/mod/applications/mod_signalwire/Makefile.am @@ -7,9 +7,9 @@ if HAVE_SIGNALWIRE_CLIENT mod_LTLIBRARIES = mod_signalwire.la mod_signalwire_la_SOURCES = mod_signalwire.c mod_signalwire_la_CFLAGS = $(AM_CFLAGS) -mod_signalwire_la_CFLAGS += $(KS_CFLAGS) $(SIGNALWIRE_CLIENT_CFLAGS) +mod_signalwire_la_CFLAGS += $(CURL_CFLAGS) $(KS_CFLAGS) $(SIGNALWIRE_CLIENT_CFLAGS) mod_signalwire_la_LIBADD = $(switch_builddir)/libfreeswitch.la -mod_signalwire_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(KS_LIBS) $(SIGNALWIRE_CLIENT_LIBS) +mod_signalwire_la_LDFLAGS = $(CURL_LIBS) -avoid-version -module -no-undefined -shared $(KS_LIBS) $(SIGNALWIRE_CLIENT_LIBS) else install: error From 34b573998be9f27eb1d148768ae7387a8ca5d37b Mon Sep 17 00:00:00 2001 From: Seven Du Date: Wed, 14 Nov 2018 14:36:18 +0800 Subject: [PATCH 05/24] FS-11521: [mod_av] WIP add test code and add png --- conf/vanilla/autoload_configs/av.conf.xml | 1 + src/mod/applications/mod_av/test/Makefile.am | 2 +- src/mod/applications/mod_av/test/cluecon.png | Bin 0 -> 213752 bytes .../applications/mod_av/test/test_avformat.c | 110 ++++++++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/mod/applications/mod_av/test/cluecon.png create mode 100644 src/mod/applications/mod_av/test/test_avformat.c diff --git a/conf/vanilla/autoload_configs/av.conf.xml b/conf/vanilla/autoload_configs/av.conf.xml index cf28fab3d3..5a53668c4d 100644 --- a/conf/vanilla/autoload_configs/av.conf.xml +++ b/conf/vanilla/autoload_configs/av.conf.xml @@ -141,5 +141,6 @@ enum AVColorRange { + diff --git a/src/mod/applications/mod_av/test/Makefile.am b/src/mod/applications/mod_av/test/Makefile.am index 4c66bd22f6..b7111a2275 100644 --- a/src/mod/applications/mod_av/test/Makefile.am +++ b/src/mod/applications/mod_av/test/Makefile.am @@ -1,4 +1,4 @@ -bin_PROGRAMS = test_mod_av +bin_PROGRAMS = test_mod_av test_avformat AM_CFLAGS = $(SWITCH_AM_CFLAGS) -I../ $(AVFORMAT_CFLAGS) $(AVCODEC_CFLAGS) $(SWSCALE_CFLAGS) $(AVUTIL_CFLAGS) $(AVRESAMPLE_CFALGS) AM_LDFLAGS = $(switch_builddir)/libfreeswitch.la $(AVFORMAT_LIBS) $(AVCODEC_LIBS) $(SWSCALE_LIBS) $(AVUTIL_LIBS) $(AVRESAMPLE_LIBS) -avoid-version -no-undefined $(SWITCH_AM_LDFLAGS) ../mod_av.la TESTS = $(bin_PROGRAMS) diff --git a/src/mod/applications/mod_av/test/cluecon.png b/src/mod/applications/mod_av/test/cluecon.png new file mode 100644 index 0000000000000000000000000000000000000000..91abe81dd83a317a250c008a0744200119988d36 GIT binary patch literal 213752 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 + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Seven Du + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * + * test_avformat -- avformat tests + * + */ + +#include + +#define SAMPLES 160 + +FST_CORE_BEGIN("conf") +{ + FST_MODULE_BEGIN(mod_av, mod_av_test) + { + FST_SETUP_BEGIN() + { + fst_requires_module("mod_av"); + } + FST_SETUP_END() + + FST_TEST_BEGIN(avformat_test) + { + switch_status_t status; + switch_image_t *img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, 1280, 720, 1); + switch_file_handle_t fh = { 0 }; + uint8_t data[SAMPLES * 2] = { 0 }; + switch_frame_t frame = { 0 }; + switch_size_t len = SAMPLES; + uint32_t flags = SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT | SWITCH_FILE_FLAG_VIDEO; + + fst_requires(img); + + status = switch_core_file_open(&fh, "./test.mp4", 1, 8000, flags, fst_pool); + fst_requires(status == SWITCH_STATUS_SUCCESS); + fst_requires(switch_test_flag(&fh, SWITCH_FILE_OPEN)); + + status = switch_core_file_write(&fh, data, &len); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "status: %d len: %d\n", status, len); + fst_check(status == SWITCH_STATUS_SUCCESS); + // fst_requires(len == SAMPLES); + + frame.img = img; + status = switch_core_file_write_video(&fh, &frame); + fst_check(status == SWITCH_STATUS_SUCCESS); + + switch_image_t *ccimg = switch_img_read_png("./cluecon.png", SWITCH_IMG_FMT_ARGB); + fst_requires(ccimg); + + switch_rgb_color_t color = {0}; + color.a = 255; + + for (int i = 0; i < 30; i++) { + len = SAMPLES; + + if (i == 10) { + color.r = 255; + } else if (i == 20) { + color.r = 0; + color.b = 255; + } + + switch_img_fill(img, 0, 0, img->d_w, img->d_h, &color); + switch_img_patch(img, ccimg, i * 10, i * 10); + + status = switch_core_file_write(&fh, data, &len); + status = switch_core_file_write_video(&fh, &frame); + switch_yield(100000); + } + + switch_core_file_close(&fh); + switch_img_free(&img); + switch_img_free(&ccimg); + } + FST_TEST_END() + + FST_TEARDOWN_BEGIN() + { + const char *err = NULL; + switch_sleep(1000000); + fst_check(switch_loadable_module_unload_module(SWITCH_GLOBAL_dirs.mod_dir, (char *)"mod_av", SWITCH_TRUE, &err) == SWITCH_STATUS_SUCCESS); + } + FST_TEARDOWN_END() + } + FST_MODULE_END() +} +FST_CORE_END() From 863a0b1d2a0d3490c96644336fe7cedc34cf9952 Mon Sep 17 00:00:00 2001 From: Liyang Date: Wed, 14 Nov 2018 16:27:21 +0800 Subject: [PATCH 06/24] FS-11521: [mod_av] read colorspace param from config for avformat --- src/mod/applications/mod_av/avformat.c | 43 +++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_av/avformat.c b/src/mod/applications/mod_av/avformat.c index 42abce911c..d338ed8b8c 100644 --- a/src/mod/applications/mod_av/avformat.c +++ b/src/mod/applications/mod_av/avformat.c @@ -50,6 +50,7 @@ GCC_DIAG_ON(deprecated-declarations) #define AVUTIL_TIMESTAMP_H #define AV_TS_MAX_STRING_SIZE 32 +#define UINTVAL(v) (v > 0 ? v : 0); // Compatibility with old libav on Debian Jessie // Not required if libavcodec version > 56.34.1 @@ -59,6 +60,12 @@ GCC_DIAG_ON(deprecated-declarations) #define AV_CODEC_CAP_VARIABLE_FRAME_SIZE CODEC_CAP_VARIABLE_FRAME_SIZE #endif +struct avformat_globals { + enum AVColorSpace colorspace; +}; + +struct avformat_globals avformat_globals = { 0 }; + /* App interface */ // a wrapper around a single output AVStream @@ -566,7 +573,7 @@ GCC_DIAG_ON(deprecated-declarations) // av_opt_set_int(c->priv_data, "slice-max-size", SWITCH_DEFAULT_VIDEO_SIZE, 0); - c->colorspace = AVCOL_SPC_RGB; + c->colorspace = avformat_globals.colorspace; c->color_range = AVCOL_RANGE_JPEG; break; @@ -2626,11 +2633,45 @@ static char *supported_formats[SWITCH_MAX_CODECS] = { 0 }; static const char modname[] = "mod_av"; +static switch_status_t load_config() +{ + char *cf = "avformat.conf"; + switch_xml_t cfg, xml, param, settings; + + if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "open of %s failed\n", cf); + return SWITCH_STATUS_TERM; + } + + if ((settings = switch_xml_child(cfg, "settings"))) { + for (param = switch_xml_child(settings, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (!strcasecmp(var, "colorspace")) { + int value = atoi(val); + + avformat_globals.colorspace = UINTVAL(value); + + if (avformat_globals.colorspace > AVCOL_SPC_NB) { + avformat_globals.colorspace = AVCOL_SPC_RGB; + } + } + } + } + + switch_xml_free(xml); + return SWITCH_STATUS_SUCCESS; +} + SWITCH_MODULE_LOAD_FUNCTION(mod_avformat_load) { switch_file_interface_t *file_interface; int i = 0; + memset(&avformat_globals, 0, sizeof(struct avformat_globals)); + load_config(); + supported_formats[i++] = "av"; supported_formats[i++] = "rtmp"; supported_formats[i++] = "rtsp"; From 036d3e80857ad1414fb036ca9e6e6cb0a9d477f4 Mon Sep 17 00:00:00 2001 From: Liyang Date: Wed, 14 Nov 2018 17:04:48 +0800 Subject: [PATCH 07/24] FS-11521: [mod_av] support colorspace from params of file interface https://freeswitch.org/jira/browse/FS-11521 --- src/mod/applications/mod_av/avformat.c | 15 ++++- .../applications/mod_av/test/test_avformat.c | 67 +++++++++++++++++-- 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/mod/applications/mod_av/avformat.c b/src/mod/applications/mod_av/avformat.c index d338ed8b8c..67628da7cd 100644 --- a/src/mod/applications/mod_av/avformat.c +++ b/src/mod/applications/mod_av/avformat.c @@ -126,6 +126,7 @@ struct av_file_context { AVFormatContext *fc; AVCodec *audio_codec; AVCodec *video_codec; + enum AVColorSpace colorspace; int has_audio; int has_video; @@ -573,8 +574,9 @@ GCC_DIAG_ON(deprecated-declarations) // av_opt_set_int(c->priv_data, "slice-max-size", SWITCH_DEFAULT_VIDEO_SIZE, 0); - c->colorspace = avformat_globals.colorspace; + c->colorspace = context->colorspace; c->color_range = AVCOL_RANGE_JPEG; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "colorspace = %d\n", c->colorspace); break; default: @@ -1605,7 +1607,8 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa context->offset = DFT_RECORD_OFFSET; context->handle = handle; context->audio_timer = 1; - + context->colorspace = avformat_globals.colorspace; + if (handle->params) { if ((tmp = switch_event_get_header(handle->params, "av_video_offset"))) { context->offset = atoi(tmp); @@ -1615,6 +1618,14 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa context->audio_timer = 0; } } + if ((tmp = switch_event_get_header(handle->params, "colorspace"))) { + int value = atoi(tmp); + enum AVColorSpace colorspace = UINTVAL(value); + + if (colorspace <= AVCOL_SPC_NB) { + context->colorspace = colorspace; + } + } } switch_mutex_init(&context->mutex, SWITCH_MUTEX_NESTED, handle->memory_pool); diff --git a/src/mod/applications/mod_av/test/test_avformat.c b/src/mod/applications/mod_av/test/test_avformat.c index 248d43f930..39df7d6c01 100644 --- a/src/mod/applications/mod_av/test/test_avformat.c +++ b/src/mod/applications/mod_av/test/test_avformat.c @@ -42,11 +42,11 @@ FST_CORE_BEGIN("conf") } FST_SETUP_END() - FST_TEST_BEGIN(avformat_test) + FST_TEST_BEGIN(avformat_test_colorspace_RGB) { switch_status_t status; switch_image_t *img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, 1280, 720, 1); - switch_file_handle_t fh = { 0 }; + switch_file_handle_t fh = { 0 }; uint8_t data[SAMPLES * 2] = { 0 }; switch_frame_t frame = { 0 }; switch_size_t len = SAMPLES; @@ -54,9 +54,9 @@ FST_CORE_BEGIN("conf") fst_requires(img); - status = switch_core_file_open(&fh, "./test.mp4", 1, 8000, flags, fst_pool); + status = switch_core_file_open(&fh, "{colorspace=0}./test_RGB.mp4", 1, 8000, flags, fst_pool); fst_requires(status == SWITCH_STATUS_SUCCESS); - fst_requires(switch_test_flag(&fh, SWITCH_FILE_OPEN)); + fst_requires(switch_test_flag(&fh, SWITCH_FILE_OPEN)); status = switch_core_file_write(&fh, data, &len); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "status: %d len: %d\n", status, len); @@ -91,7 +91,62 @@ FST_CORE_BEGIN("conf") switch_yield(100000); } - switch_core_file_close(&fh); + switch_core_file_close(&fh); + switch_img_free(&img); + switch_img_free(&ccimg); + } + FST_TEST_END() + + FST_TEST_BEGIN(avformat_test_colorspace_BT7) + { + switch_status_t status; + switch_image_t *img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, 1280, 720, 1); + switch_file_handle_t fh = { 0 }; + uint8_t data[SAMPLES * 2] = { 0 }; + switch_frame_t frame = { 0 }; + switch_size_t len = SAMPLES; + uint32_t flags = SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT | SWITCH_FILE_FLAG_VIDEO; + + fst_requires(img); + + status = switch_core_file_open(&fh, "{colorspace=1}./test_BT7.mp4", 1, 8000, flags, fst_pool); + fst_requires(status == SWITCH_STATUS_SUCCESS); + fst_requires(switch_test_flag(&fh, SWITCH_FILE_OPEN)); + + status = switch_core_file_write(&fh, data, &len); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "status: %d len: %d\n", status, len); + fst_check(status == SWITCH_STATUS_SUCCESS); + // fst_requires(len == SAMPLES); + + frame.img = img; + status = switch_core_file_write_video(&fh, &frame); + fst_check(status == SWITCH_STATUS_SUCCESS); + + switch_image_t *ccimg = switch_img_read_png("./cluecon.png", SWITCH_IMG_FMT_ARGB); + fst_requires(ccimg); + + switch_rgb_color_t color = {0}; + color.a = 255; + + for (int i = 0; i < 30; i++) { + len = SAMPLES; + + if (i == 10) { + color.r = 255; + } else if (i == 20) { + color.r = 0; + color.b = 255; + } + + switch_img_fill(img, 0, 0, img->d_w, img->d_h, &color); + switch_img_patch(img, ccimg, i * 10, i * 10); + + status = switch_core_file_write(&fh, data, &len); + status = switch_core_file_write_video(&fh, &frame); + switch_yield(100000); + } + + switch_core_file_close(&fh); switch_img_free(&img); switch_img_free(&ccimg); } @@ -101,7 +156,7 @@ FST_CORE_BEGIN("conf") { const char *err = NULL; switch_sleep(1000000); - fst_check(switch_loadable_module_unload_module(SWITCH_GLOBAL_dirs.mod_dir, (char *)"mod_av", SWITCH_TRUE, &err) == SWITCH_STATUS_SUCCESS); + //fst_check(switch_loadable_module_unload_module(SWITCH_GLOBAL_dirs.mod_dir, (char *)"mod_av", SWITCH_TRUE, &err) == SWITCH_STATUS_SUCCESS); } FST_TEARDOWN_END() } From 522d871f65a198232edc269df8ee3af084be0925 Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Wed, 14 Nov 2018 19:00:56 +0400 Subject: [PATCH 08/24] FS-11521: [Build-System] Fix C99 standard regression. --- src/mod/applications/mod_av/test/test_avformat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_av/test/test_avformat.c b/src/mod/applications/mod_av/test/test_avformat.c index 39df7d6c01..59f6fb68c8 100644 --- a/src/mod/applications/mod_av/test/test_avformat.c +++ b/src/mod/applications/mod_av/test/test_avformat.c @@ -51,6 +51,7 @@ FST_CORE_BEGIN("conf") switch_frame_t frame = { 0 }; switch_size_t len = SAMPLES; uint32_t flags = SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT | SWITCH_FILE_FLAG_VIDEO; + int i = 0; fst_requires(img); @@ -73,7 +74,7 @@ FST_CORE_BEGIN("conf") switch_rgb_color_t color = {0}; color.a = 255; - for (int i = 0; i < 30; i++) { + for (i = 0; i < 30; i++) { len = SAMPLES; if (i == 10) { @@ -106,6 +107,7 @@ FST_CORE_BEGIN("conf") switch_frame_t frame = { 0 }; switch_size_t len = SAMPLES; uint32_t flags = SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT | SWITCH_FILE_FLAG_VIDEO; + int i = 0; fst_requires(img); @@ -128,7 +130,7 @@ FST_CORE_BEGIN("conf") switch_rgb_color_t color = {0}; color.a = 255; - for (int i = 0; i < 30; i++) { + for (i = 0; i < 30; i++) { len = SAMPLES; if (i == 10) { From 9e0579011d36693d41cb85d13655a641dd648f36 Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Wed, 14 Nov 2018 19:51:33 +0400 Subject: [PATCH 09/24] FS-11521: [mod_av] Test program regression fix. --- src/mod/applications/mod_av/test/test_avformat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_av/test/test_avformat.c b/src/mod/applications/mod_av/test/test_avformat.c index 59f6fb68c8..fed0264d34 100644 --- a/src/mod/applications/mod_av/test/test_avformat.c +++ b/src/mod/applications/mod_av/test/test_avformat.c @@ -60,7 +60,7 @@ FST_CORE_BEGIN("conf") fst_requires(switch_test_flag(&fh, SWITCH_FILE_OPEN)); status = switch_core_file_write(&fh, data, &len); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "status: %d len: %d\n", status, len); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "status: %d len: %d\n", status, (int)len); fst_check(status == SWITCH_STATUS_SUCCESS); // fst_requires(len == SAMPLES); @@ -116,7 +116,7 @@ FST_CORE_BEGIN("conf") fst_requires(switch_test_flag(&fh, SWITCH_FILE_OPEN)); status = switch_core_file_write(&fh, data, &len); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "status: %d len: %d\n", status, len); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "status: %d len: %d\n", status, (int)len); fst_check(status == SWITCH_STATUS_SUCCESS); // fst_requires(len == SAMPLES); From fd7c6a8afa0d8c0e4dc47828c2d02ff166b20d4a Mon Sep 17 00:00:00 2001 From: netoguimaraes Date: Wed, 2 Jan 2019 17:36:03 -0300 Subject: [PATCH 10/24] FS-11589 [verto_communicator]: removing es6 use to support old browsers syntax --- .../src/vertoControllers/controllers/MainController.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js b/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js index 5534a6b817..a8bfe106db 100644 --- a/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js +++ b/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js @@ -77,10 +77,15 @@ * Login the user to verto server and * redirects him to dialpad page. */ - $rootScope.login = function(redirect, skipPreview = false) { + $rootScope.login = function(redirect, skipPreview) { if(redirect == undefined) { redirect = true; } + + if(skipPreview == undefined) { + redirect == false; + } + var connectCallback = function(v, connected) { $scope.$apply(function() { verto.data.connecting = false; From 6f811ca41f797c30939bb64289b5c353146ba052 Mon Sep 17 00:00:00 2001 From: netoguimaraes Date: Thu, 3 Jan 2019 13:10:31 -0300 Subject: [PATCH 11/24] FS-11589 [verto_communicator]: fixing a weird typo and keeps with the old behaviour when calling login with no args --- .../src/vertoControllers/controllers/MainController.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js b/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js index a8bfe106db..29d5ed8f44 100644 --- a/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js +++ b/html5/verto/verto_communicator/src/vertoControllers/controllers/MainController.js @@ -83,7 +83,7 @@ } if(skipPreview == undefined) { - redirect == false; + skipPreview = false; } var connectCallback = function(v, connected) { From 3d906ec3a63dbd374b25a3222f15d8715fc4dc0f Mon Sep 17 00:00:00 2001 From: Serj Date: Tue, 8 Jan 2019 19:29:07 +0000 Subject: [PATCH 12/24] FS-11600: [Build-System] Install mod_signalwire with freeswitch-meta-all --- debian/bootstrap.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 18c221bf5a..864114ad9c 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -624,6 +624,7 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), freeswitch-mod-png (= \${binary:Version}), freeswitch-mod-redis (= \${binary:Version}), freeswitch-mod-rss (= \${binary:Version}), + freeswitch-mod-signalwire (= \${binary:Version}), freeswitch-mod-shout (= \${binary:Version}), freeswitch-mod-sms (= \${binary:Version}), freeswitch-mod-snapshot (= \${binary:Version}), From 09941318946664566df3ecd3c7503840981d7516 Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Wed, 12 Dec 2018 01:33:06 +0400 Subject: [PATCH 13/24] FS-11564: [mod_verto] Add ext-rtp-ip detection using stun. --- src/include/switch_stun.h | 9 +++ src/mod/endpoints/mod_verto/mod_verto.c | 3 +- src/switch_stun.c | 73 +++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/include/switch_stun.h b/src/include/switch_stun.h index f05a6e11df..54b03088e8 100644 --- a/src/include/switch_stun.h +++ b/src/include/switch_stun.h @@ -259,6 +259,15 @@ SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_priority(switch_stun_pa SWITCH_DECLARE(switch_status_t) switch_stun_lookup(char **ip, switch_port_t *port, char *stunip, switch_port_t stunport, char **err, switch_memory_pool_t *pool); +/*! + \brief Perform a stun ip lookup + \param external_ip replaced with stun results + \param sourceip stun:, host: or an ip + \param external_pool the memory pool to use + \return SUCCESS or FAIL +*/ +SWITCH_DECLARE(switch_status_t) switch_stun_ip_lookup(char **external_ip, const char *sourceip, switch_memory_pool_t *external_pool); + /*! \brief Obtain the padded length of an attribute's value diff --git a/src/mod/endpoints/mod_verto/mod_verto.c b/src/mod/endpoints/mod_verto/mod_verto.c index 7dc8336bd9..6ad57d2760 100644 --- a/src/mod/endpoints/mod_verto/mod_verto.c +++ b/src/mod/endpoints/mod_verto/mod_verto.c @@ -31,6 +31,7 @@ */ #include #include +#include /* Prototypes */ @@ -4824,7 +4825,7 @@ static switch_status_t parse_config(const char *cf) if (zstr(val)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid External RTP IP.\n"); } else { - profile->extrtpip = switch_core_strdup(profile->pool, val); + switch_stun_ip_lookup(&profile->extrtpip, val, profile->pool); } } else if (!strcasecmp(var, "debug")) { if (val) { diff --git a/src/switch_stun.c b/src/switch_stun.c index 6573d3eceb..f759a2607c 100644 --- a/src/switch_stun.c +++ b/src/switch_stun.c @@ -851,6 +851,79 @@ SWITCH_DECLARE(switch_status_t) switch_stun_lookup(char **ip, return SWITCH_STATUS_FALSE; } +SWITCH_DECLARE(switch_status_t) switch_stun_ip_lookup(char **external_ip, const char *sourceip, switch_memory_pool_t *external_pool) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + char *stun_ip = NULL; + switch_port_t stun_port = (switch_port_t)SWITCH_STUN_DEFAULT_PORT; + char *p; + char ip_buf[256] = ""; + char *ip = NULL; + switch_port_t port = 0; + switch_memory_pool_t *local_pool = NULL; + char *error = ""; + + if (!sourceip || !external_pool) { + *external_ip = NULL; + goto end; + } + + ip = ip_buf; + + if (!strncasecmp(sourceip, "host:", 5)) { + status = (*external_ip = switch_stun_host_lookup(sourceip + 5, external_pool)) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; + } + else if (!strncasecmp(sourceip, "stun:", 5)) { + + switch_core_new_memory_pool(&local_pool); + + stun_ip = switch_core_strdup(local_pool, sourceip + 5); + + switch_assert(stun_ip); + + if ((p = strchr(stun_ip, ':'))) { + int iport; + *p++ = '\0'; + iport = atoi(p); + if (iport > 0 && iport < 0xFFFF) { + stun_port = (switch_port_t)iport; + } + } + else { + p = stun_ip; + } + + switch_find_local_ip(ip_buf, sizeof(ip_buf), NULL, AF_INET); + + if (zstr(stun_ip)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! NO STUN SERVER\n"); + } + else { + if ((switch_stun_lookup(&ip, &port, stun_ip, stun_port, &error, local_pool)) == SWITCH_STATUS_SUCCESS && ip && port) { + *external_ip = switch_core_strdup(external_pool, ip); + status = SWITCH_STATUS_SUCCESS; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "External ip address detected using STUN: %s\n", ip); + } + else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! [%s]\n", error); + } + } + + if (status != SWITCH_STATUS_SUCCESS) { + *external_ip = ""; + } + + switch_core_destroy_memory_pool(&local_pool); + } + else { + *external_ip = switch_core_strdup(external_pool, sourceip); + status = SWITCH_STATUS_SUCCESS; + } + +end: + + return status; +} From 0629f95cff12b270e912194d9f01fbb44cb42371 Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Thu, 13 Dec 2018 22:55:43 +0400 Subject: [PATCH 14/24] FS-11568: [core] Add stun-set command to X-PRE-PROCESS. --- src/switch_xml.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/switch_xml.c b/src/switch_xml.c index 37400a13b5..26e4481b53 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -56,6 +56,7 @@ */ #include +#include #ifndef WIN32 #include #include @@ -141,6 +142,46 @@ static void preprocess_exec_set(char *keyval) } } +static void preprocess_stun_set(char *keyval) +{ + char *key = keyval; + char *val = strchr(key, '='); + + if (val) { + char *ve = val++; + while (*val && *val == ' ') { + val++; + } + *ve-- = '\0'; + while (*ve && *ve == ' ') { + *ve-- = '\0'; + } + } + + if (key && val) { + char *external_ip = NULL; + switch_memory_pool_t *pool; + + switch_core_new_memory_pool(&pool); + + if (switch_stun_ip_lookup(&external_ip, val, pool) == SWITCH_STATUS_SUCCESS) { + if (!zstr(external_ip)) { + char *tmp = external_ip; + tmp = &tmp[strlen(tmp) - 1]; + while (tmp >= external_ip && (tmp[0] == ' ' || tmp[0] == '\n')) { + tmp[0] = '\0'; /* remove trailing spaces and newlines */ + tmp--; + } + switch_core_set_variable(key, external_ip); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "stun-set failed.\n"); + } + + switch_core_destroy_memory_pool(&pool); + } +} + static void preprocess_env_set(char *keyval) { char *key = keyval; @@ -1487,6 +1528,8 @@ static int preprocess(const char *cwd, const char *file, FILE *write_fd, int rle } else if (!strcasecmp(tcmd, "exec-set")) { preprocess_exec_set(targ); + } else if (!strcasecmp(tcmd, "stun-set")) { + preprocess_stun_set(targ); } else if (!strcasecmp(tcmd, "env-set")) { preprocess_env_set(targ); } else if (!strcasecmp(tcmd, "include")) { @@ -1549,6 +1592,8 @@ static int preprocess(const char *cwd, const char *file, FILE *write_fd, int rle } else if (!strcasecmp(cmd, "exec-set")) { preprocess_exec_set(arg); + } else if (!strcasecmp(cmd, "stun-set")) { + preprocess_stun_set(arg); } else if (!strcasecmp(cmd, "include")) { preprocess_glob(cwd, arg, write_fd, rlevel + 1); } else if (!strcasecmp(cmd, "exec")) { From 6ac8105944f717fcd5a357159e15c6bde13ad467 Mon Sep 17 00:00:00 2001 From: Mariah Yang Date: Wed, 9 Jan 2019 12:55:28 +0800 Subject: [PATCH 15/24] FS-11601: Fix some core function prototype --- src/include/switch_core.h | 2 +- src/include/switch_ivr.h | 6 +++--- src/include/switch_loadable_module.h | 2 +- src/switch_core_speech.c | 2 +- src/switch_ivr_async.c | 2 +- src/switch_ivr_play_say.c | 8 ++++---- src/switch_loadable_module.c | 12 ++++++------ 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 298639d6ab..526fe26323 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1992,7 +1992,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(_In_ switch_speech_handl \param flags flags in/out for fine tuning \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes written if successful */ -SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_tts(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags); +SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_tts(switch_speech_handle_t *sh, const char *text, switch_speech_flag_t *flags); /*! \brief Flush TTS audio on a given handle diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 3525ab28ff..5a444d552b 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -292,7 +292,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_start_input_timers(swit \param fh file handle to use (NULL for builtin one) \return SWITCH_STATUS_SUCCESS if all is well */ -SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t *session, char *file, uint32_t limit, switch_file_handle_t *fh); +SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t *session, const char *file, uint32_t limit, switch_file_handle_t *fh); SWITCH_DECLARE(switch_status_t) switch_ivr_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session); @@ -471,7 +471,7 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session, switch_speech_handle_t *sh, - switch_codec_t *codec, switch_timer_t *timer, char *text, switch_input_args_t *args); + switch_codec_t *codec, switch_timer_t *timer, const char *text, switch_input_args_t *args); SWITCH_DECLARE(void) switch_ivr_clear_speech_cache(switch_core_session_t *session); /*! \brief Speak given text with given tts engine @@ -483,7 +483,7 @@ SWITCH_DECLARE(void) switch_ivr_clear_speech_cache(switch_core_session_t *sessio \return SWITCH_STATUS_SUCCESS if all is well */ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *session, - const char *tts_name, const char *voice_name, char *text, switch_input_args_t *args); + const char *tts_name, const char *voice_name, const char *text, switch_input_args_t *args); /*! \brief Make an outgoing call diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h index 9299857f68..9cc99ee0be 100644 --- a/src/include/switch_loadable_module.h +++ b/src/include/switch_loadable_module.h @@ -302,7 +302,7 @@ SWITCH_DECLARE(switch_status_t) switch_json_api_execute(cJSON *json, switch_core \param err pointer to error message \return the status */ -SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime, const char **err); +SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(const char *dir, const char *fname, switch_bool_t runtime, const char **err); /*! \brief Check if a module is loaded diff --git a/src/switch_core_speech.c b/src/switch_core_speech.c index 91d7fa9f78..956b4ce37b 100644 --- a/src/switch_core_speech.c +++ b/src/switch_core_speech.c @@ -96,7 +96,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t * return status; } -SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_tts(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags) +SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_tts(switch_speech_handle_t *sh, const char *text, switch_speech_flag_t *flags) { switch_status_t status = SWITCH_STATUS_SUCCESS; char *param_string = NULL; diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index f318fd9874..db4ceac9cc 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -2538,7 +2538,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session return status; } -SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t *session, char *file, uint32_t limit, switch_file_handle_t *fh) +SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t *session, const char *file, uint32_t limit, switch_file_handle_t *fh) { switch_channel_t *channel = switch_core_session_get_channel(session); const char *p; diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index abc028852d..dd923be81a 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -2644,7 +2644,7 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session, switch_speech_handle_t *sh, - switch_codec_t *codec, switch_timer_t *timer, char *text, switch_input_args_t *args) + switch_codec_t *codec, switch_timer_t *timer, const char *text, switch_input_args_t *args) { switch_channel_t *channel = switch_core_session_get_channel(session); short abuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; @@ -2656,8 +2656,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session switch_status_t status = SWITCH_STATUS_SUCCESS; switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE; switch_size_t extra = 0; - char *p, *tmp = NULL; - const char *star, *pound; + char *tmp = NULL; + const char *star, *pound, *p; switch_size_t starlen, poundlen; if (!sh) { @@ -2940,7 +2940,7 @@ SWITCH_DECLARE(void) switch_ivr_clear_speech_cache(switch_core_session_t *sessio } SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *session, - const char *tts_name, const char *voice_name, char *text, switch_input_args_t *args) + const char *tts_name, const char *voice_name, const char *text, switch_input_args_t *args) { switch_channel_t *channel = switch_core_session_get_channel(session); uint32_t rate = 0; diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index 8a1d65379b..b3ec9d4ebb 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -95,7 +95,7 @@ struct switch_loadable_module_container { static struct switch_loadable_module_container loadable_modules; static switch_status_t do_shutdown(switch_loadable_module_t *module, switch_bool_t shutdown, switch_bool_t unload, switch_bool_t fail_if_busy, const char **err); -static switch_status_t switch_loadable_module_load_module_ex(char *dir, char *fname, switch_bool_t runtime, switch_bool_t global, const char **err); +static switch_status_t switch_loadable_module_load_module_ex(const char *dir, const char *fname, switch_bool_t runtime, switch_bool_t global, const char **err); static void *SWITCH_THREAD_FUNC switch_loadable_module_exec(switch_thread_t *thread, void *obj) { @@ -1544,12 +1544,12 @@ static switch_status_t switch_loadable_module_load_file(char *path, char *filena return SWITCH_STATUS_SUCCESS; } -SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime, const char **err) +SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(const char *dir, const char *fname, switch_bool_t runtime, const char **err) { return switch_loadable_module_load_module_ex(dir, fname, runtime, SWITCH_FALSE, err); } -static switch_status_t switch_loadable_module_load_module_ex(char *dir, char *fname, switch_bool_t runtime, switch_bool_t global, const char **err) +static switch_status_t switch_loadable_module_load_module_ex(const char *dir, const char *fname, switch_bool_t runtime, switch_bool_t global, const char **err) { switch_size_t len = 0; char *path; @@ -1902,7 +1902,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init(switch_bool_t autolo if (path && zstr(path)) { path = SWITCH_GLOBAL_dirs.mod_dir; } - if (switch_loadable_module_load_module_ex((char *) path, (char *) val, SWITCH_FALSE, global, &err) == SWITCH_STATUS_GENERR) { + if (switch_loadable_module_load_module_ex(path, val, SWITCH_FALSE, global, &err) == SWITCH_STATUS_GENERR) { if (critical && switch_true(critical)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load critical module '%s', abort()\n", val); abort(); @@ -1935,7 +1935,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init(switch_bool_t autolo if (path && zstr(path)) { path = SWITCH_GLOBAL_dirs.mod_dir; } - switch_loadable_module_load_module_ex((char *) path, (char *) val, SWITCH_FALSE, global, &err); + switch_loadable_module_load_module_ex(path, val, SWITCH_FALSE, global, &err); count++; } } @@ -1975,7 +1975,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init(switch_bool_t autolo continue; } - switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) fname, SWITCH_FALSE, &err); + switch_loadable_module_load_module(SWITCH_GLOBAL_dirs.mod_dir, fname, SWITCH_FALSE, &err); } apr_dir_close(module_dir_handle); } From 0eae20e5306c2ff43b5e8782cae3076ff0172412 Mon Sep 17 00:00:00 2001 From: lazedo Date: Tue, 18 Dec 2018 12:01:56 +0000 Subject: [PATCH 16/24] FS-11610 [mod_http_cache] add video flag to http_cache --- src/mod/applications/mod_http_cache/mod_http_cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_http_cache/mod_http_cache.c b/src/mod/applications/mod_http_cache/mod_http_cache.c index 2af2cd1770..dd4b1ef2c8 100644 --- a/src/mod/applications/mod_http_cache/mod_http_cache.c +++ b/src/mod/applications/mod_http_cache/mod_http_cache.c @@ -1708,7 +1708,7 @@ static switch_status_t http_cache_file_open(switch_file_handle_t *handle, const { switch_status_t status = SWITCH_STATUS_SUCCESS; struct http_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context)); - int file_flags = SWITCH_FILE_DATA_SHORT; + int file_flags = SWITCH_FILE_DATA_SHORT | (switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO) ? SWITCH_FILE_FLAG_VIDEO : 0); if (handle->params) { context->profile = url_cache_http_profile_find(&gcache, switch_event_get_header(handle->params, "profile")); From 185ddcb860f4c5561a9285dcbb33bc758d36c4de Mon Sep 17 00:00:00 2001 From: Luis Azedo Date: Tue, 13 Mar 2018 19:52:40 +0000 Subject: [PATCH 17/24] FS-11026 [mod_sofia] set proxy on bye if available --- src/mod/endpoints/mod_sofia/mod_sofia.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 0c7a27534d..d4e6bb2285 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -502,6 +502,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending BYE to %s\n", switch_channel_get_name(channel)); if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) { nua_bye(tech_pvt->nh, + TAG_IF(tech_pvt->record_route, NUTAG_PROXY(tech_pvt->record_route)), SIPTAG_CONTACT(SIP_NONE), TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason)), TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)), From 48a6916d906923bba940786236f811a2d3f8b4e9 Mon Sep 17 00:00:00 2001 From: Jeremiah Gowdy Date: Mon, 14 Jan 2019 10:47:15 -0800 Subject: [PATCH 18/24] Fix FS-11611 by commenting locals which are unused if configured with --disable-core-libedit-support --- libs/esl/fs_cli.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 3bdadf11d3..609d9e2e00 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -1420,8 +1420,10 @@ int main(int argc, char *argv[]) const char *line = NULL; char cmd_str[2048] = ""; cli_profile_t *profile = NULL; +#ifdef HAVE_LIBEDIT int argv_use_history_file = 1; int use_history_file = 0; +#endif #ifndef WIN32 char hfile[512] = "/tmp/fs_cli_history"; char cfile[512] = "/etc/fs_cli.conf"; @@ -1581,7 +1583,9 @@ int main(int argc, char *argv[]) argv_batch = 1; break; case 'Q': +#ifdef HAVE_LIBEDIT argv_use_history_file = 0; +#endif break; case 'i': allow_ctl_c = 1; @@ -1645,9 +1649,11 @@ int main(int argc, char *argv[]) profile->batch_mode = 1; feature_level=0; } +#ifdef HAVE_LIBEDIT if (argv_use_history_file && profile->use_history_file) { use_history_file = 1; } +#endif if (*argv_loglevel) { esl_set_string(profile->loglevel, argv_loglevel); profile->quiet = 0; From fc26de0ad34ffbdc2b63d84f7b7cc49bb3909809 Mon Sep 17 00:00:00 2001 From: Serj Date: Wed, 16 Jan 2019 21:44:19 +0000 Subject: [PATCH 19/24] FS-11614: [Packaging] Systemd unit fixes. --- debian/freeswitch-systemd.freeswitch.service | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/debian/freeswitch-systemd.freeswitch.service b/debian/freeswitch-systemd.freeswitch.service index 6225d37d5c..879a00ea13 100644 --- a/debian/freeswitch-systemd.freeswitch.service +++ b/debian/freeswitch-systemd.freeswitch.service @@ -2,8 +2,9 @@ [Unit] Description=freeswitch +Wants=network-online.target Requires=syslog.socket network.target local-fs.target -After=syslog.socket network.target local-fs.target +After=syslog.socket network.target network-online.target local-fs.target [Service] ; service @@ -11,6 +12,7 @@ Type=forking PIDFile=/run/freeswitch/freeswitch.pid Environment="DAEMON_OPTS=-nonat" EnvironmentFile=-/etc/default/freeswitch +ExecStartPre=chown -R freeswitch:freeswitch /var/lib/freeswitch /var/log/freeswitch /etc/freeswitch /usr/share/freeswitch /var/run/freeswitch ExecStart=/usr/bin/freeswitch -u freeswitch -g freeswitch -ncwait $DAEMON_OPTS TimeoutSec=45s Restart=always @@ -28,6 +30,7 @@ IOSchedulingPriority=2 CPUSchedulingPolicy=rr CPUSchedulingPriority=89 UMask=0007 +NoNewPrivileges=false ; alternatives which you can enforce by placing a unit drop-in into ; /etc/systemd/system/freeswitch.service.d/*.conf: From d76cac15fcc6a68a3e713dc9b04873a4d89a364a Mon Sep 17 00:00:00 2001 From: Seven Du Date: Thu, 17 Jan 2019 15:38:13 +0800 Subject: [PATCH 20/24] FS-11615 fix compiler warning --- tests/unit/switch_event.c | 8 ++++---- tests/unit/switch_hash.c | 4 ++-- tests/unit/switch_ivr_originate.c | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/unit/switch_event.c b/tests/unit/switch_event.c index c11dfc24d3..1f55b574b9 100644 --- a/tests/unit/switch_event.c +++ b/tests/unit/switch_event.c @@ -27,7 +27,7 @@ FST_TEST_BEGIN(benchmark) int rc = 0, loops = 10, x = 0; switch_status_t status = SWITCH_STATUS_SUCCESS; char **index = NULL; - unsigned long long micro_total = 0; + uint64_t micro_total = 0; double micro_per = 0; double rate_per_sec = 0; @@ -63,7 +63,7 @@ FST_TEST_BEGIN(benchmark) micro_total = small_end_ts - small_start_ts; micro_per = micro_total / (double) loops; rate_per_sec = 1000000 / micro_per; - printf("switch_event add_header: Total %ldus / %ld loops, %.2f us per loop, %.0f loops per second\n", + printf("switch_event add_header: Total %" SWITCH_UINT64_T_FMT "us / %d loops, %.2f us per loop, %.0f loops per second\n", micro_total, loops, micro_per, rate_per_sec); #endif @@ -84,7 +84,7 @@ FST_TEST_BEGIN(benchmark) micro_total = small_end_ts - small_start_ts; micro_per = micro_total / (double) loops; rate_per_sec = 1000000 / micro_per; - printf("switch_event get_header: Total %ldus / %ld loops, %.2f us per loop, %.0f loops per second\n", + printf("switch_event get_header: Total %" SWITCH_UINT64_T_FMT "us / %d loops, %.2f us per loop, %.0f loops per second\n", micro_total, loops, micro_per, rate_per_sec); #endif @@ -101,7 +101,7 @@ FST_TEST_BEGIN(benchmark) micro_total = end_ts - start_ts; micro_per = micro_total / (double) loops; rate_per_sec = 1000000 / micro_per; - printf("switch_event Total %ldus / %d loops, %.2f us per loop, %.0f loops per second\n", + printf("switch_event Total %" SWITCH_UINT64_T_FMT "us / %d loops, %.2f us per loop, %.0f loops per second\n", micro_total, loops, micro_per, rate_per_sec); } diff --git a/tests/unit/switch_hash.c b/tests/unit/switch_hash.c index a8d57c527c..43d3e18692 100644 --- a/tests/unit/switch_hash.c +++ b/tests/unit/switch_hash.c @@ -24,7 +24,7 @@ FST_TEST_BEGIN(benchmark) switch_bool_t verbose = SWITCH_TRUE; const char *err = NULL; switch_time_t start_ts, end_ts; - unsigned long long micro_total = 0; + uint64_t micro_total = 0; double micro_per = 0; double rate_per_sec = 0; int x = 0; @@ -131,7 +131,7 @@ FST_TEST_BEGIN(benchmark) micro_total = end_ts - start_ts; micro_per = micro_total / (double) loops; rate_per_sec = 1000000 / micro_per; - printf("switch_hash Total %ldus / %d loops, %.2f us per loop, %.0f loops per second\n", + printf("switch_hash Total %" SWITCH_UINT64_T_FMT "us / %d loops, %.2f us per loop, %.0f loops per second\n", micro_total, loops, micro_per, rate_per_sec); } FST_TEST_END() diff --git a/tests/unit/switch_ivr_originate.c b/tests/unit/switch_ivr_originate.c index 3b2cb4154b..1b7ff19a4a 100644 --- a/tests/unit/switch_ivr_originate.c +++ b/tests/unit/switch_ivr_originate.c @@ -42,6 +42,8 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) switch_assert(session); reporting++; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "session reporting %d\n", reporting); + + return SWITCH_STATUS_SUCCESS; } static switch_status_t my_on_destroy(switch_core_session_t *session) @@ -49,6 +51,8 @@ static switch_status_t my_on_destroy(switch_core_session_t *session) switch_assert(session); destroy++; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "session destroy %d\n", destroy); + + return SWITCH_STATUS_SUCCESS; } static switch_state_handler_table_t state_handlers = { From 9c18e272f9f50c2ee3fe5dafd5d407103adf61ea Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Sat, 13 Oct 2018 02:24:31 +0300 Subject: [PATCH 21/24] FS-11458: [core] Fix video timing. --- src/switch_time.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/switch_time.c b/src/switch_time.c index 2847158861..a90d1a863e 100644 --- a/src/switch_time.c +++ b/src/switch_time.c @@ -692,7 +692,6 @@ static switch_status_t timer_init(switch_timer_t *timer) timer->start = switch_micro_time_now(); if (timer->interval == 1) { - runtime.microseconds_per_tick = 10000; switch_mutex_lock(globals.mutex); globals.timer_count++; switch_mutex_unlock(globals.mutex); From 2bf9878c2fad9354630c271b729168066dab8a66 Mon Sep 17 00:00:00 2001 From: Dragos Oancea Date: Fri, 18 Jan 2019 14:38:42 -0500 Subject: [PATCH 22/24] FS-11599: [core] fix inter-arrival jitter (timer) --- src/switch_rtp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 9f4de55f31..824e01b7ee 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1933,7 +1933,7 @@ static int rtcp_stats(switch_rtp_t *rtp_session) if (pkt_seq < max_seq) { stats->cycle++; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "rtcp_stats:[cycle change] pkt_seq[%d] cycle[%d] max_seq[%d] stats_ssrc[%u] local_ts[%u]\n", - pkt_seq, stats->cycle, max_seq, stats->ssrc, rtp_session->write_timer.samplecount); + pkt_seq, stats->cycle, max_seq, stats->ssrc, rtp_session->timer.samplecount); } pkt_extended_seq = stats->cycle << 16 | pkt_seq; /* getting the extended packet extended sequence ID */ if (pkt_extended_seq > stats->high_ext_seq_recv) { @@ -1963,7 +1963,7 @@ static int rtcp_stats(switch_rtp_t *rtp_session) stats->period_pkt_count, pkt_seq, stats->cycle, stats->ssrc, rtp_session->write_timer.samplecount); #endif /* Interarrival jitter calculation */ - pkt_tsdiff = abs((int32_t)(rtp_session->write_timer.samplecount - ntohl(hdr->ts))); /* relative transit times for this packet */ + pkt_tsdiff = abs((int32_t)(rtp_session->timer.samplecount - ntohl(hdr->ts))); /* relative transit times for this packet */ if (stats->pkt_count < 2) { /* Can not compute Jitter with only one packet */ stats->last_pkt_tsdiff = pkt_tsdiff; } else { @@ -1976,7 +1976,7 @@ static int rtcp_stats(switch_rtp_t *rtp_session) #ifdef DEBUG_RTCP switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "rtcp_stats: pkt_ts[%d]local_ts[%d]diff[%d]pkt_spacing[%d]inter_jitter[%f]seq[%d]stats_ssrc[%d]", - ntohl(hdr->ts), rtp_session->write_timer.samplecount, pkt_tsdiff, packet_spacing_diff, stats->inter_jitter, ntohs(hdr->seq), stats->ssrc); + ntohl(hdr->ts), rtp_session->timer.samplecount, pkt_tsdiff, packet_spacing_diff, stats->inter_jitter, ntohs(hdr->seq), stats->ssrc); #endif return 1; } From 179430ceccfa001e9987790d584663306714cc08 Mon Sep 17 00:00:00 2001 From: Dragos Oancea Date: Mon, 21 Jan 2019 18:00:36 -0500 Subject: [PATCH 23/24] FS-11622: WS headers case insensitive --- libs/sofia-sip/libsofia-sip-ua/tport/ws.c | 2 +- src/mod/endpoints/mod_verto/ws.c | 2 +- src/mod/xml_int/mod_xml_rpc/ws.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c index 8d6de2909b..c004781e12 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c @@ -150,7 +150,7 @@ static int cheezy_get_var(char *data, char *name, char *buf, size_t buflen) */ do { - if(!strncmp(p,name,strlen(name)) && *(p+strlen(name))==':') break; + if(!strncasecmp(p,name,strlen(name)) && *(p+strlen(name))==':') break; } while((p = (strstr(p,"\n")+1))!=(char *)1); diff --git a/src/mod/endpoints/mod_verto/ws.c b/src/mod/endpoints/mod_verto/ws.c index 86c73c18fa..b4702d30c3 100644 --- a/src/mod/endpoints/mod_verto/ws.c +++ b/src/mod/endpoints/mod_verto/ws.c @@ -150,7 +150,7 @@ static int cheezy_get_var(char *data, char *name, char *buf, size_t buflen) */ do { - if(!strncmp(p,name,strlen(name)) && *(p+strlen(name))==':') break; + if(!strncasecmp(p,name,strlen(name)) && *(p+strlen(name))==':') break; } while((p = (strstr(p,"\n")+1))!=(char *)1); diff --git a/src/mod/xml_int/mod_xml_rpc/ws.c b/src/mod/xml_int/mod_xml_rpc/ws.c index 44a3860ae4..a5ad9c7a3b 100644 --- a/src/mod/xml_int/mod_xml_rpc/ws.c +++ b/src/mod/xml_int/mod_xml_rpc/ws.c @@ -119,7 +119,7 @@ static int cheezy_get_var(char *data, char *name, char *buf, size_t buflen) */ do { - if(!strncmp(p,name,strlen(name)) && *(p+strlen(name))==':') break; + if(!strncasecmp(p,name,strlen(name)) && *(p+strlen(name))==':') break; } while((p = (strstr(p,"\n")+1))!=(char *)1); From f869288be10ce343f5cd9c0d4ba57365696ba8f8 Mon Sep 17 00:00:00 2001 From: Serj Date: Wed, 23 Jan 2019 20:24:35 +0000 Subject: [PATCH 24/24] FS-11614: [Packaging] Use full path for the chown command in the systemd unit. --- debian/freeswitch-systemd.freeswitch.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/freeswitch-systemd.freeswitch.service b/debian/freeswitch-systemd.freeswitch.service index 879a00ea13..c283f1df39 100644 --- a/debian/freeswitch-systemd.freeswitch.service +++ b/debian/freeswitch-systemd.freeswitch.service @@ -12,7 +12,7 @@ Type=forking PIDFile=/run/freeswitch/freeswitch.pid Environment="DAEMON_OPTS=-nonat" EnvironmentFile=-/etc/default/freeswitch -ExecStartPre=chown -R freeswitch:freeswitch /var/lib/freeswitch /var/log/freeswitch /etc/freeswitch /usr/share/freeswitch /var/run/freeswitch +ExecStartPre=/bin/chown -R freeswitch:freeswitch /var/lib/freeswitch /var/log/freeswitch /etc/freeswitch /usr/share/freeswitch /var/run/freeswitch ExecStart=/usr/bin/freeswitch -u freeswitch -g freeswitch -ncwait $DAEMON_OPTS TimeoutSec=45s Restart=always