diff options
35 files changed, 770 insertions, 153 deletions
diff --git a/apps/app_mp3.c b/apps/app_mp3.c index 5712cfe33..05afe54b1 100644 --- a/apps/app_mp3.c +++ b/apps/app_mp3.c @@ -77,9 +77,10 @@ ASTERISK_REGISTER_FILE() ***/ static char *app = "MP3Player"; -static int mp3play(const char *filename, int fd) +static int mp3play(const char *filename, unsigned int sampling_rate, int fd) { int res; + char sampling_rate_str[8]; res = ast_safe_fork(0); if (res < 0) @@ -93,30 +94,44 @@ static int mp3play(const char *filename, int fd) dup2(fd, STDOUT_FILENO); ast_close_fds_above_n(STDERR_FILENO); + snprintf(sampling_rate_str, 8, "%u", sampling_rate); + /* Execute mpg123, but buffer if it's a net connection */ - if (!strncasecmp(filename, "http://", 7)) { + if (!strncasecmp(filename, "http://", 7) && strstr(filename, ".m3u")) { + char buffer_size_str[8]; + snprintf(buffer_size_str, 8, "%u", (int) 0.5*2*sampling_rate/1000); // 0.5 seconds for a live stream + /* Most commonly installed in /usr/local/bin */ + execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); + /* But many places has it in /usr/bin */ + execl(MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); + /* As a last-ditch effort, try to use PATH */ + execlp("mpg123", "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); + } + else if (!strncasecmp(filename, "http://", 7)) { + char buffer_size_str[8]; + snprintf(buffer_size_str, 8, "%u", 6*2*sampling_rate/1000); // 6 seconds for a remote MP3 file /* Most commonly installed in /usr/local/bin */ - execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); + execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); /* But many places has it in /usr/bin */ - execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); + execl(MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ - execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); + execlp("mpg123", "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); } else if (strstr(filename, ".m3u")) { /* Most commonly installed in /usr/local/bin */ - execl(LOCAL_MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); + execl(LOCAL_MPG_123, "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); /* But many places has it in /usr/bin */ - execl(MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); + execl(MPG_123, "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ - execlp("mpg123", "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); + execlp("mpg123", "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); } else { /* Most commonly installed in /usr/local/bin */ - execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); + execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); /* But many places has it in /usr/bin */ - execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); + execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ - execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); + execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); } /* Can't use ast_log since FD's are closed */ fprintf(stderr, "Execute of mpg123 failed\n"); @@ -155,6 +170,9 @@ static int mp3_exec(struct ast_channel *chan, const char *data) } myf = { .f = { 0, }, }; + struct ast_format * native_format; + unsigned int sampling_rate; + struct ast_format * write_format; if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n"); @@ -168,15 +186,19 @@ static int mp3_exec(struct ast_channel *chan, const char *data) ast_stopstream(chan); + native_format = ast_format_cap_get_format(ast_channel_nativeformats(chan), 0); + sampling_rate = ast_format_get_sample_rate(native_format); + write_format = ast_format_cache_get_slin_by_rate(sampling_rate); + owriteformat = ao2_bump(ast_channel_writeformat(chan)); - res = ast_set_write_format(chan, ast_format_slin); + res = ast_set_write_format(chan, write_format); if (res < 0) { ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); return -1; } myf.f.frametype = AST_FRAME_VOICE; - myf.f.subclass.format = ast_format_slin; + myf.f.subclass.format = write_format; myf.f.mallocd = 0; myf.f.offset = AST_FRIENDLY_OFFSET; myf.f.src = __PRETTY_FUNCTION__; @@ -184,7 +206,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data) myf.f.delivery.tv_usec = 0; myf.f.data.ptr = myf.frdata; - res = mp3play(data, fds[1]); + res = mp3play(data, sampling_rate, fds[1]); if (!strncasecmp(data, "http://", 7)) { timeout = 10000; } @@ -211,7 +233,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data) res = 0; break; } - next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000)); + next = ast_tvadd(next, ast_samp2tv(myf.f.samples, sampling_rate)); } else { ms = ast_waitfor(chan, ms); if (ms < 0) { diff --git a/build_tools/menuselect-deps.in b/build_tools/menuselect-deps.in index f194482e9..a04440955 100644 --- a/build_tools/menuselect-deps.in +++ b/build_tools/menuselect-deps.in @@ -4,6 +4,7 @@ COROSYNC=@PBX_COROSYNC@ CRYPTO=@PBX_CRYPTO@ BFD=@PBX_BFD@ BISON=@PBX_BISON@ +CODEC2=@PBX_CODEC2@ CURL=@PBX_CURL@ DAHDI=@PBX_DAHDI@ DLADDR=@PBX_DLADDR@ diff --git a/codecs/codec_codec2.c b/codecs/codec_codec2.c new file mode 100644 index 000000000..e446854c3 --- /dev/null +++ b/codecs/codec_codec2.c @@ -0,0 +1,222 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2016, Alexander Traud + * + * Alexander Traud <pabstraud@compuserve.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Translate between signed linear and Codec 2 + * + * \author Alexander Traud <pabstraud@compuserve.com> + * + * \note http://www.rowetel.com/codec2.html + * + * \ingroup codecs + */ + +/*** MODULEINFO + <depend>codec2</depend> + <support_level>core</support_level> + ***/ + +#include "asterisk.h" + +#include "asterisk/codec.h" /* for AST_MEDIA_TYPE_AUDIO */ +#include "asterisk/frame.h" /* for ast_frame */ +#include "asterisk/linkedlists.h" /* for AST_LIST_NEXT, etc */ +#include "asterisk/logger.h" /* for ast_log, etc */ +#include "asterisk/module.h" +#include "asterisk/rtp_engine.h" /* ast_rtp_engine_(un)load_format */ +#include "asterisk/translate.h" /* for ast_trans_pvt, etc */ + +#include <codec2/codec2.h> + +#define BUFFER_SAMPLES 8000 +#define CODEC2_SAMPLES 160 /* consider codec2_samples_per_frame(.) */ +#define CODEC2_FRAME_LEN 6 /* consider codec2_bits_per_frame(.) */ + +/* Sample frame data */ +#include "asterisk/slin.h" +#include "ex_codec2.h" + +struct codec2_translator_pvt { + struct CODEC2 *state; /* May be encoder or decoder */ + int16_t buf[BUFFER_SAMPLES]; +}; + +static int codec2_new(struct ast_trans_pvt *pvt) +{ + struct codec2_translator_pvt *tmp = pvt->pvt; + + tmp->state = codec2_create(CODEC2_MODE_2400); + + if (!tmp->state) { + ast_log(LOG_ERROR, "Error creating Codec 2 conversion\n"); + return -1; + } + + return 0; +} + +/*! \brief decode and store in outbuf. */ +static int codec2tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct codec2_translator_pvt *tmp = pvt->pvt; + int x; + + for (x = 0; x < f->datalen; x += CODEC2_FRAME_LEN) { + unsigned char *src = f->data.ptr + x; + int16_t *dst = pvt->outbuf.i16 + pvt->samples; + + codec2_decode(tmp->state, dst, src); + + pvt->samples += CODEC2_SAMPLES; + pvt->datalen += CODEC2_SAMPLES * 2; + } + + return 0; +} + +/*! \brief store samples into working buffer for later decode */ +static int lintocodec2_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct codec2_translator_pvt *tmp = pvt->pvt; + + memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen); + pvt->samples += f->samples; + + return 0; +} + +/*! \brief encode and produce a frame */ +static struct ast_frame *lintocodec2_frameout(struct ast_trans_pvt *pvt) +{ + struct codec2_translator_pvt *tmp = pvt->pvt; + struct ast_frame *result = NULL; + struct ast_frame *last = NULL; + int samples = 0; /* output samples */ + + while (pvt->samples >= CODEC2_SAMPLES) { + struct ast_frame *current; + + /* Encode a frame of data */ + codec2_encode(tmp->state, pvt->outbuf.uc, tmp->buf + samples); + + samples += CODEC2_SAMPLES; + pvt->samples -= CODEC2_SAMPLES; + + current = ast_trans_frameout(pvt, CODEC2_FRAME_LEN, CODEC2_SAMPLES); + + if (!current) { + continue; + } else if (last) { + AST_LIST_NEXT(last, frame_list) = current; + } else { + result = current; + } + last = current; + } + + /* Move the data at the end of the buffer to the front */ + if (samples) { + memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); + } + + return result; +} + +static void codec2_destroy_stuff(struct ast_trans_pvt *pvt) +{ + struct codec2_translator_pvt *tmp = pvt->pvt; + + if (tmp->state) { + codec2_destroy(tmp->state); + } +} + +static struct ast_translator codec2tolin = { + .name = "codec2tolin", + .src_codec = { + .name = "codec2", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + }, + .dst_codec = { + .name = "slin", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + }, + .format = "slin", + .newpvt = codec2_new, + .framein = codec2tolin_framein, + .destroy = codec2_destroy_stuff, + .sample = codec2_sample, + .desc_size = sizeof(struct codec2_translator_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES * 2, +}; + +static struct ast_translator lintocodec2 = { + .name = "lintocodec2", + .src_codec = { + .name = "slin", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + }, + .dst_codec = { + .name = "codec2", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + }, + .format = "codec2", + .newpvt = codec2_new, + .framein = lintocodec2_framein, + .frameout = lintocodec2_frameout, + .destroy = codec2_destroy_stuff, + .sample = slin8_sample, + .desc_size = sizeof(struct codec2_translator_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = (BUFFER_SAMPLES * CODEC2_FRAME_LEN + CODEC2_SAMPLES - 1) / CODEC2_SAMPLES, +}; + +static int unload_module(void) +{ + int res = 0; + + res |= ast_rtp_engine_unload_format(ast_format_codec2); + res |= ast_unregister_translator(&lintocodec2); + res |= ast_unregister_translator(&codec2tolin); + + return res; +} + +static int load_module(void) +{ + int res = 0; + + res |= ast_register_translator(&codec2tolin); + res |= ast_register_translator(&lintocodec2); + res |= ast_rtp_engine_load_format(ast_format_codec2); + + if (res) { + unload_module(); + return AST_MODULE_LOAD_FAILURE; + } + + return AST_MODULE_LOAD_SUCCESS; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Codec 2 Coder/Decoder"); diff --git a/codecs/ex_codec2.h b/codecs/ex_codec2.h new file mode 100644 index 000000000..f2f4c9723 --- /dev/null +++ b/codecs/ex_codec2.h @@ -0,0 +1,32 @@ +/*! \file + * \brief 8-bit raw data + * + * Copyright (C) 2016, Alexander Traud + * + * Distributed under the terms of the GNU General Public License + * + */ + +#include "asterisk/format_cache.h" /* for ast_format_codec2 */ +#include "asterisk/frame.h" /* for ast_frame, etc */ + +static uint8_t ex_codec2[] = { + 0xea, 0xca, 0x14, 0x85, 0x91, 0x78, +}; + +static struct ast_frame *codec2_sample(void) +{ + static struct ast_frame f = { + .frametype = AST_FRAME_VOICE, + .datalen = sizeof(ex_codec2), + .samples = CODEC2_SAMPLES, + .mallocd = 0, + .offset = 0, + .src = __PRETTY_FUNCTION__, + .data.ptr = ex_codec2, + }; + + f.subclass.format = ast_format_codec2; + + return &f; +} diff --git a/configs/samples/alsa.conf.sample b/configs/samples/alsa.conf.sample index ced5b4485..23aac4e10 100644 --- a/configs/samples/alsa.conf.sample +++ b/configs/samples/alsa.conf.sample @@ -46,7 +46,7 @@ extension=s ; systems where there will be no return audio path, such as overhead pagers. ;noaudiocapture=true -;------------------------------ JITTER BUFFER CONFIGURATION -------------------------- +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of an ; ALSA channel. Defaults to "no". An enabled jitterbuffer will ; be used only if the sending side can create and the receiving @@ -74,5 +74,5 @@ extension=s ; network normally has low jitter, but occasionally has spikes. ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". -;----------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- diff --git a/configs/samples/ccss.conf.sample b/configs/samples/ccss.conf.sample index 21b0b0668..7b3fe7d23 100644 --- a/configs/samples/ccss.conf.sample +++ b/configs/samples/ccss.conf.sample @@ -64,9 +64,9 @@ ; PLEASE READ THIS!!! ;=========================================== ; -;--------------------------------------------------------------------- +; -------------------------------------------------------------------- ; Timers -;--------------------------------------------------------------------- +; -------------------------------------------------------------------- ;There are three configurable timers for all types of CC: the ;cc_offer_timer, the ccbs_available_timer, and the ccnr_available_timer. ;In addition, when using a generic agent, there is a fourth timer, @@ -98,9 +98,9 @@ ; only affects operation when using a generic agent. ; ;cc_recall_timer = 20 -;--------------------------------------------------------------------- +; -------------------------------------------------------------------- ; Policies -;--------------------------------------------------------------------- +; -------------------------------------------------------------------- ; Policy settings tell Asterisk how to behave and what sort of ; resources to allocate in order to facilitate CC. There are two ; settings to control the actions Asterisk will take. @@ -153,9 +153,9 @@ ;cc_monitor_policy=never ; ; -;--------------------------------------------------------------------- +; -------------------------------------------------------------------- ; Limits -;--------------------------------------------------------------------- +; -------------------------------------------------------------------- ; ; The use of CC requires Asterisk to potentially use more memory than ; some administrators would like. As such, it is a good idea to limit @@ -175,9 +175,9 @@ ; ;cc_max_monitors = 5 ; -;--------------------------------------------------------------------- +; -------------------------------------------------------------------- ; Other -;--------------------------------------------------------------------- +; -------------------------------------------------------------------- ; ; When using a generic CC agent, the caller who requested CC will be ; called back when a called party becomes available. When the caller diff --git a/configs/samples/chan_dahdi.conf.sample b/configs/samples/chan_dahdi.conf.sample index a0c729c11..e70a2a138 100644 --- a/configs/samples/chan_dahdi.conf.sample +++ b/configs/samples/chan_dahdi.conf.sample @@ -1220,7 +1220,7 @@ pickupgroup=1 ; ;jitterbuffers=4 ; -;------------------------------ JITTER BUFFER CONFIGURATION -------------------------- +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a ; DAHDI channel. Defaults to "no". An enabled jitterbuffer will ; be used only if the sending side can create and the receiving @@ -1248,7 +1248,7 @@ pickupgroup=1 ; network normally has low jitter, but occasionally has spikes. ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". -;----------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- ; ; You can define your own custom ring cadences here. You can define up to 8 ; pairs. If the silence is negative, it indicates where the caller ID spill is diff --git a/configs/samples/console.conf.sample b/configs/samples/console.conf.sample index 606254eee..aad306ed5 100644 --- a/configs/samples/console.conf.sample +++ b/configs/samples/console.conf.sample @@ -44,7 +44,7 @@ ; ;mohinterpret=default -;------------------------------ JITTER BUFFER CONFIGURATION -------------------------- +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of an ; Console channel. Defaults to "no". An enabled jitterbuffer will ; be used only if the sending side can create and the receiving @@ -72,7 +72,7 @@ ; network normally has low jitter, but occasionally has spikes. ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". -;----------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- ; diff --git a/configs/samples/mgcp.conf.sample b/configs/samples/mgcp.conf.sample index 7c725bc3d..f4bc0dbf2 100644 --- a/configs/samples/mgcp.conf.sample +++ b/configs/samples/mgcp.conf.sample @@ -11,12 +11,12 @@ ;cos=3 ; Sets 802.1p priority for signaling packets. ;cos_audio=5 ; Sets 802.1p priority for RTP audio packets. -;---------------------- DIGIT TIMEOUTS ---------------------------- +; --------------------- DIGIT TIMEOUTS ---------------------------- firstdigittimeout = 30000 ; default 16000 = 16s gendigittimeout = 10000 ; default 8000 = 8s matchdigittimeout = 5000 ; defaults 3000 = 3s -;------------------------------ JITTER BUFFER CONFIGURATION -------------------------- +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a ; MGCP channel. Defaults to "no". An enabled jitterbuffer will ; be used only if the sending side can create and the receiving @@ -48,7 +48,7 @@ matchdigittimeout = 5000 ; defaults 3000 = 3s ; network normally has low jitter, but occasionally has spikes. ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". -;----------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- ;[dlinkgw] ;host = 192.168.0.64 diff --git a/configs/samples/minivm.conf.sample b/configs/samples/minivm.conf.sample index 55a39c869..2df3449d1 100644 --- a/configs/samples/minivm.conf.sample +++ b/configs/samples/minivm.conf.sample @@ -12,7 +12,7 @@ ; this configuration file or realtime. The idea is to build voicemail as building blocks so that ; a complete and adaptive voicemail system can be built in the dialplan ; -;------------------------------ Variables to use in subject, from and message body ------------------ +; ----------------------------- Variables to use in subject, from and message body ------------------ ; Change the from, body and/or subject, variables: ; MVM_NAME, MVM_DUR, MVM_MSGNUM, VM_MAILBOX, MVM_CALLERID, MVM_CIDNUM, ; MVM_CIDNAME, MVM_DATE @@ -24,7 +24,7 @@ ; Note: The emailbody config row can only be up to 512 characters due to a ; limitation in the Asterisk configuration subsystem. ; To create longer mails, use the templatefile option when creating the template -;---------------------------------------------------------------------------------------------------- +; --------------------------------------------------------------------------------------------------- [general] ; Default format for storing and sending voicemail @@ -64,7 +64,7 @@ silencethreshold=128 ; This is used both for e-mail and pager messages ;mailcmd=/usr/sbin/sendmail -t ; -;--------------Default e-mail message template (used if no templates are used) ------ +; -------------Default e-mail message template (used if no templates are used) ------ ;fromstring=The Asterisk PBX ; @@ -82,7 +82,7 @@ emaildateformat=%A, %B %d, %Y at %r ; 24h date format ;emaildateformat=%A, %d %B %Y at %H:%M:%S ; -;--------------Default pager message template (used if no templates are used) ------ +; -------------Default pager message template (used if no templates are used) ------ ; You can also change the Pager From: string, the pager body and/or subject. ; The above defined variables also can be used here ;pagerfromstring=The Asterisk PBX @@ -90,7 +90,7 @@ emaildateformat=%A, %B %d, %Y at %r ;pagerbody=New ${MVM_DUR} long msg in box ${MVM_MAILBOX}\nfrom ${MVM_CALLERID}, on ${MVM_DATE} ; ; -;--------------Timezone definitions (used in voicemail accounts) ------------------- +; -------------Timezone definitions (used in voicemail accounts) ------------------- ; ; Users may be located in different timezones, or may have different ; message announcements for their introductory message when they enter @@ -133,7 +133,7 @@ central=America/Chicago|'vm-received' Q 'digits/at' IMp central24=America/Chicago|'vm-received' q 'digits/at' H N 'hours' military=Zulu|'vm-received' q 'digits/at' H N 'hours' 'phonetic/z_p' -;----------------------- Message body templates--------------------- +; ---------------------- Message body templates--------------------- ; [template-name] ; "template-" is a verbatim marker ; fromaddress = Your Friendly Asterisk Server ; fromemail = asteriskvm@digium.com @@ -187,7 +187,7 @@ dateformat=%A, %B %d, %Y at %r ;subject = Dear old chap, you've got an electronic communique ;charset=ascii -;----------------------- Mailbox accounts -------------------------- +; ---------------------- Mailbox accounts -------------------------- ;Template for mailbox definition - all options ; ; [username@domain] ; Has to be unique within domain (MWM_USERNAME, MWM_DOMAIN) diff --git a/configs/samples/misdn.conf.sample b/configs/samples/misdn.conf.sample index ac54dbc5a..ca27c03bd 100644 --- a/configs/samples/misdn.conf.sample +++ b/configs/samples/misdn.conf.sample @@ -109,7 +109,7 @@ crypt_prefix=** ; crypt_keys=test,muh -;------------------------------ JITTER BUFFER CONFIGURATION -------------------------- +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a ; SIP channel. Defaults to "no". An enabled jitterbuffer will ; be used only if the sending side can create and the receiving @@ -140,7 +140,7 @@ crypt_keys=test,muh ; network normally has low jitter, but occasionally has spikes. ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". -;----------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- ; users sections: ; diff --git a/configs/samples/oss.conf.sample b/configs/samples/oss.conf.sample index c3781a2a2..ee169209f 100644 --- a/configs/samples/oss.conf.sample +++ b/configs/samples/oss.conf.sample @@ -46,7 +46,7 @@ ; queuesize = 10 ; frames in device driver ; frags = 8 ; argument to SETFRAGMENT - ;------------------------------ JITTER BUFFER CONFIGURATION -------------------------- + ; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of an ; OSS channel. Defaults to "no". An enabled jitterbuffer will ; be used only if the sending side can create and the receiving @@ -74,7 +74,7 @@ ; network normally has low jitter, but occasionally has spikes. ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". - ;----------------------------------------------------------------------------------- + ; ---------------------------------------------------------------------------------- ; below is an entry for a second console channel ; [card1] diff --git a/configs/samples/queues.conf.sample b/configs/samples/queues.conf.sample index 85cf9e40f..8a9c88402 100644 --- a/configs/samples/queues.conf.sample +++ b/configs/samples/queues.conf.sample @@ -129,7 +129,7 @@ monitor-type = MixMonitor ; ;penaltymemberslimit = 5 ; -;----------------------QUEUE TIMING OPTIONS------------------------------------ +; ---------------------QUEUE TIMING OPTIONS------------------------------------ ; A Queue has two different "timeout" values associated with it. One is the ; timeout parameter configured in queues.conf. This timeout specifies the ; amount of time to try ringing a member's phone before considering the @@ -181,7 +181,7 @@ monitor-type = MixMonitor ;retry = 5 ;timeoutpriority = app|conf ; -;-----------------------END QUEUE TIMING OPTIONS--------------------------------- +; ----------------------END QUEUE TIMING OPTIONS--------------------------------- ; Weight of queue - when compared to other queues, higher weights get ; first shot at available channels when the same channel is included in ; more than one queue. diff --git a/configs/samples/res_snmp.conf.sample b/configs/samples/res_snmp.conf.sample index a6e40c8e2..7f3734910 100644 --- a/configs/samples/res_snmp.conf.sample +++ b/configs/samples/res_snmp.conf.sample @@ -1,6 +1,6 @@ ; ; Configuration file for res_snmp -;--------------------------------- +; -------------------------------- ; ; Res_snmp can run as a subagent or standalone SNMP agent. The standalone snmp ; agent is based on net-snmp and will read a configuration file called diff --git a/configs/samples/sip.conf.sample b/configs/samples/sip.conf.sample index da176b4d6..916e2d671 100644 --- a/configs/samples/sip.conf.sample +++ b/configs/samples/sip.conf.sample @@ -15,7 +15,7 @@ ; - context - Which set of services you offer various users ; ; SIP dial strings -;----------------------------------------------------------- +; ---------------------------------------------------------- ; In the dialplan (extensions.conf) you can use several ; syntaxes for dialing SIP devices. ; SIP/devicename @@ -87,7 +87,7 @@ ; sip reload Reload configuration file ; sip show settings Show the current channel configuration ; -;------- Naming devices ------------------------------------------------------ +; ------ Naming devices ------------------------------------------------------ ; ; When naming devices, make sure you understand how Asterisk matches calls ; that come in. @@ -111,7 +111,7 @@ ; not needed at all. Check below. In later releases, it's renamed ; to "defaultuser" which is a better name, since it is used in ; combination with the "defaultip" setting. -;----------------------------------------------------------------------------- +; ---------------------------------------------------------------------------- ; ** Old configuration options ** ; The "call-limit" configuation option is considered old is replaced @@ -573,7 +573,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; are not purged during SIP reloads. ; -;------------------------ TLS settings ------------------------------------------------------------ +; ----------------------- TLS settings ------------------------------------------------------------ ;tlscertfile=</path/to/certificate.pem> ; Certificate chain (*.pem format only) to use for TLS connections ; The certificates must be sorted starting with the subject's certificate ; and followed by intermediate CA certificates if applicable. If the @@ -622,7 +622,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; Your distribution might have changed that list ; further. ; -;--------------------------- SIP timers ---------------------------------------------------- +; -------------------------- SIP timers ---------------------------------------------------- ; These timers are used primarily in INVITE transactions. ; The default for Timer T1 is 500 ms or the measured run-trip time between ; Asterisk and the device if you have qualify=yes for the device. @@ -636,7 +636,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; in this amount of time, the call will autocongest ; Defaults to 64*timert1 -;--------------------------- RTP timers ---------------------------------------------------- +; -------------------------- RTP timers ---------------------------------------------------- ; These timers are currently used for both audio and video streams. The RTP timeouts ; are only applied to the audio channel. ; The settings are settable in the global section as well as per device @@ -652,7 +652,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ;rtpkeepalive=<secs> ; Send keepalives in the RTP stream to keep NAT open ; (default is off - zero) -;--------------------------- SIP Session-Timers (RFC 4028)------------------------------------ +; -------------------------- SIP Session-Timers (RFC 4028)------------------------------------ ; SIP Session-Timers provide an end-to-end keep-alive mechanism for active SIP sessions. ; This mechanism can detect and reclaim SIP channels that do not terminate through normal ; signaling procedures. Session-Timers can be configured globally or at a user/peer level. @@ -681,7 +681,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ;session-minse=90 ;session-refresher=uac ; -;--------------------------- SIP DEBUGGING --------------------------------------------------- +; -------------------------- SIP DEBUGGING --------------------------------------------------- ;sipdebug = yes ; Turn on SIP debugging by default, from ; the moment the channel loads this configuration. ; NOTE: You cannot use the CLI to turn it off. You'll @@ -692,7 +692,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; SIP history is output to the DEBUG logging channel -;--------------------------- STATUS NOTIFICATIONS (SUBSCRIPTIONS) ---------------------------- +; -------------------------- STATUS NOTIFICATIONS (SUBSCRIPTIONS) ---------------------------- ; You can subscribe to the status of extensions with a "hint" priority ; (See extensions.conf.sample for examples) ; chan_sip support two major formats for notifications: dialog-info and SIMPLE @@ -741,7 +741,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ;callcounter = yes ; Enable call counters on devices. This can be set per ; device too. -;----------------------------------------- T.38 FAX SUPPORT ---------------------------------- +; ---------------------------------------- T.38 FAX SUPPORT ---------------------------------- ; ; This setting is available in the [general] section as well as in device configurations. ; Setting this to yes enables T.38 FAX (UDPTL) on SIP calls; it defaults to off. @@ -774,7 +774,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; faxdetect = cng ; Enables only CNG detection ; faxdetect = t38 ; Enables only T.38 detection ; -;----------------------------------------- OUTBOUND SIP REGISTRATIONS ------------------------ +; ---------------------------------------- OUTBOUND SIP REGISTRATIONS ------------------------ ; Asterisk can register as a SIP user agent to a SIP proxy (provider) ; Format for the register statement is: ; register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] @@ -851,7 +851,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; 401 responses and continue retrying according to normal ; retry rules. -;----------------------------------------- OUTBOUND MWI SUBSCRIPTIONS ------------------------- +; ---------------------------------------- OUTBOUND MWI SUBSCRIPTIONS ------------------------- ; Asterisk can subscribe to receive the MWI from another SIP server and store it locally for retrieval ; by other phones. At this time, you can only subscribe using UDP as the transport. ; Format for the mwi register statement is: @@ -866,7 +866,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; MWI received will be stored in the 1234 mailbox of the SIP_Remote context. ; It can be used by other phones by following the below: ; mailbox=1234@SIP_Remote -;----------------------------------------- NAT SUPPORT ------------------------ +; ---------------------------------------- NAT SUPPORT ------------------------ ; ; WARNING: SIP operation behind a NAT is tricky and you really need ; to read and understand well the following section. @@ -1008,7 +1008,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; ; icesupport = yes -;----------------------------------- MEDIA HANDLING -------------------------------- +; ---------------------------------- MEDIA HANDLING -------------------------------- ; By default, Asterisk tries to re-invite media streams to an optimal path. If there's ; no reason for Asterisk to stay in the media path, the media will be redirected. ; This does not really work well in the case where Asterisk is outside and the @@ -1090,7 +1090,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; option may be specified at the global or peer scope. ;force_avp=yes ; Force 'RTP/AVP', 'RTP/AVPF', 'RTP/SAVP', and 'RTP/SAVPF' to be used for ; media streams when appropriate, even if a DTLS stream is present. -;----------------------------------------- REALTIME SUPPORT ------------------------ +; ---------------------------------------- REALTIME SUPPORT ------------------------ ; For additional information on ARA, the Asterisk Realtime Architecture, ; please read https://wiki.asterisk.org/wiki/display/AST/Realtime+Database+Configuration ; @@ -1128,7 +1128,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; is still in memory (due to caching or other reasons), the ; information will not be removed from realtime storage -;----------------------------------------- SIP DOMAIN SUPPORT ------------------------ +; ---------------------------------------- SIP DOMAIN SUPPORT ------------------------ ; Incoming INVITE and REFER messages can be matched against a list of 'allowed' ; domains, each of which can direct the call to a specific context if desired. ; By default, all domains are accepted and sent to the default context or the @@ -1167,13 +1167,13 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; destinations which do not have a prior ; account relationship with your server. -;------------------------------ Advice of Charge CONFIGURATION -------------------------- +; ----------------------------- Advice of Charge CONFIGURATION -------------------------- ; snom_aoc_enabled = yes; ; This options turns on and off support for sending AOC-D and ; AOC-E to snom endpoints. This option can be used both in the ; peer and global scope. The default for this option is off. -;------------------------------ JITTER BUFFER CONFIGURATION -------------------------- +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a ; SIP channel. Defaults to "no". An enabled jitterbuffer will ; be used only if the sending side can create and the receiving @@ -1205,7 +1205,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". -;----------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- [authentication] ; Global credentials for outbound calls, i.e. when a proxy challenges your @@ -1224,7 +1224,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; You may also add auth= statements to [peer] definitions ; Peer auth= override all other authentication settings if we match on realm -;------------------------------------------------------------------------------ +; ----------------------------------------------------------------------------- ; DEVICE CONFIGURATION ; ; SIP entities have a 'type' which determines their roles within Asterisk. @@ -1351,7 +1351,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; ; from the peer's configuration. ; -;------------------------------------------------------------------------------ +; ----------------------------------------------------------------------------- ; DTLS-SRTP CONFIGURATION ; ; DTLS-SRTP support is available if the underlying RTP engine in use supports it. @@ -1409,7 +1409,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ;port=80 ; The port number we want to connect to on the remote side ; Also used as "defaultport" in combination with "defaultip" settings -;--- sample definition for a provider +; -- sample definition for a provider ;[provider1] ;type=peer ;host=sip.provider1.com diff --git a/configs/samples/skinny.conf.sample b/configs/samples/skinny.conf.sample index be88dc230..2bf06fbc8 100644 --- a/configs/samples/skinny.conf.sample +++ b/configs/samples/skinny.conf.sample @@ -54,7 +54,7 @@ keepalive=120 ;cos_audio=5 ; Sets 802.1p priority for RTP audio packets. ;cos_video=4 ; Sets 802.1p priority for RTP video packets. -;------------------------------ JITTER BUFFER CONFIGURATION -------------------------- +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- ;jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a ; skinny channel. Defaults to "no". An enabled jitterbuffer will ; be used only if the sending side can create and the receiving @@ -79,10 +79,10 @@ keepalive=120 ; Defaults to fixed. ;jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". -;----------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- [lines] -;----------------------------------- LINES SECTION -------------------------------- +; ---------------------------------- LINES SECTION -------------------------------- ; Options set under [lines] apply to all lines unless explicitly set for a particular ; device. The options that can be set under lines are specified in GENERAL LINE OPTIONS. ; These options can also be set for each individual device as well as those under SPECIFIC @@ -95,15 +95,15 @@ keepalive=120 ; Where options are common to both lines and devices, the results typically take that of ; the least permission. ie if a no is set for either line or device, the call will not be ; able to use that permission -;-------------------------------- GENERAL LINE OPTIONS ----------------------------- +; ------------------------------- GENERAL LINE OPTIONS ----------------------------- ;earlyrtp=1 ; whether audio signalling should be provided by asterisk ; ; (earlyrtp=1) or device generated (earlyrtp=0). default=yes ;transfer=1 ; whether the device is allowed to transfer. default=yes ;context=default ; context to use for this line. ;callfwdtimeout=20000 ; ms before cfwd_noans occurs (default 20 secs) -;------------------------------- SPECIFIC LINE OPTIONS ----------------------------- +; ------------------------------ SPECIFIC LINE OPTIONS ----------------------------- ;setvar= ; allows for the setting of chanvars. -;----------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- ;[100] ;nat=yes @@ -149,7 +149,7 @@ keepalive=120 [devices] -;---------------------------------- DEVICES SECTION ------------------------------- +; --------------------------------- DEVICES SECTION ------------------------------- ; Options set under [devices] apply to all devices unless explicitly set for a particular ; device. The options that can be set under devices are specified in GENERAL DEVICE OPTIONS. ; These options can also be set for each individual device as well as those under SPECIFIC @@ -162,16 +162,16 @@ keepalive=120 ; Where options are common to both lines and devices, the results typically take that of ; the least permission. ie if a no is set for either line or device, the call will not be ; able to use that permission -;------------------------------- GENERAL DEVICE OPTIONS ---------------------------- +; ------------------------------ GENERAL DEVICE OPTIONS ---------------------------- ;earlyrtp=1 ; whether audio signalling should be provided by asterisk ; ; (earlyrtp=1) or device generated (earlyrtp=0). default=yes ;transfer=1 ; whether the device is allowed to transfer. default=yes -;------------------------------ SPECIFIC DEVICE OPTIONS ---------------------------- +; ----------------------------- SPECIFIC DEVICE OPTIONS ---------------------------- ;device="SEPxxxxxxxxxxxx ; id of the device. Must be set. ;version=P002G204 ; firmware version to be loaded. If this version is different ; ; to the one on the device, the device will try to load this ; ; version from the tftp server. Set to device firmware version. -;----------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- ; Typical config for 12SP+ ;[florian] diff --git a/configs/samples/unistim.conf.sample b/configs/samples/unistim.conf.sample index c33426b0c..a09642796 100644 --- a/configs/samples/unistim.conf.sample +++ b/configs/samples/unistim.conf.sample @@ -17,7 +17,7 @@ port=5000 ; UDP port ;autoprovisioning=no ; Allow undeclared phones to register an extension. See README for important ; informations. no (default), yes, tn. ;mohsuggest=default -;------------------------------ JITTER BUFFER CONFIGURATION -------------------------- +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a ; SIP channel. Defaults to "no". An enabled jitterbuffer will ; be used only if the sending side can create and the receiving @@ -41,7 +41,7 @@ port=5000 ; UDP port ; variable size, actually the new jb of IAX2). Defaults to fixed. ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". -;----------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- ;[black] ; name of the device diff --git a/configs/samples/vpb.conf.sample b/configs/samples/vpb.conf.sample index fecb3ec59..bdc89dff5 100644 --- a/configs/samples/vpb.conf.sample +++ b/configs/samples/vpb.conf.sample @@ -199,7 +199,7 @@ grunttimeout=3600 ; mode=immediate -;------------------------------------------------------------------------- +; ------------------------------------------------------------------------ ; Channel definitions ; ; Each channel inherits the settings specified above, unless the are @@ -1164,6 +1164,10 @@ PBX_COROSYNC COROSYNC_DIR COROSYNC_INCLUDE COROSYNC_LIB +PBX_CODEC2 +CODEC2_DIR +CODEC2_INCLUDE +CODEC2_LIB PBX_CAP CAP_DIR CAP_INCLUDE @@ -1338,6 +1342,7 @@ with_bfd with_execinfo with_bluetooth with_cap +with_codec2 with_cpg with_curses with_crypt @@ -2077,6 +2082,7 @@ Optional Packages: --with-execinfo=PATH use Stack Backtrace files in PATH --with-bluetooth=PATH use Bluetooth files in PATH --with-cap=PATH use POSIX 1.e capabilities files in PATH + --with-codec2=PATH use Codec 2 Audio Decoder/Encoder files in PATH --with-cpg=PATH use Corosync files in PATH --with-curses=PATH use curses files in PATH --with-crypt=PATH use password and data encryption files in PATH @@ -9000,6 +9006,38 @@ fi + CODEC2_DESCRIP="Codec 2 Audio Decoder/Encoder" + CODEC2_OPTION="codec2" + PBX_CODEC2=0 + +# Check whether --with-codec2 was given. +if test "${with_codec2+set}" = set; then : + withval=$with_codec2; + case ${withval} in + n|no) + USE_CODEC2=no + # -1 is a magic value used by menuselect to know that the package + # was disabled, other than 'not found' + PBX_CODEC2=-1 + ;; + y|ye|yes) + ac_mandatory_list="${ac_mandatory_list} CODEC2" + ;; + *) + CODEC2_DIR="${withval}" + ac_mandatory_list="${ac_mandatory_list} CODEC2" + ;; + esac + +fi + + + + + + + + COROSYNC_DESCRIP="Corosync" COROSYNC_OPTION="cpg" PBX_COROSYNC=0 @@ -30531,6 +30569,111 @@ fi fi +if test "x${PBX_CODEC2}" != "x1" -a "${USE_CODEC2}" != "no"; then + pbxlibdir="" + # if --with-CODEC2=DIR has been specified, use it. + if test "x${CODEC2_DIR}" != "x"; then + if test -d ${CODEC2_DIR}/lib; then + pbxlibdir="-L${CODEC2_DIR}/lib" + else + pbxlibdir="-L${CODEC2_DIR}" + fi + fi + pbxfuncname="codec2_create" + if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers + AST_CODEC2_FOUND=yes + else + ast_ext_lib_check_save_CFLAGS="${CFLAGS}" + CFLAGS="${CFLAGS} " + as_ac_Lib=`$as_echo "ac_cv_lib_codec2_${pbxfuncname}" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lcodec2" >&5 +$as_echo_n "checking for ${pbxfuncname} in -lcodec2... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcodec2 ${pbxlibdir} $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ${pbxfuncname} (); +int +main () +{ +return ${pbxfuncname} (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + AST_CODEC2_FOUND=yes +else + AST_CODEC2_FOUND=no +fi + + CFLAGS="${ast_ext_lib_check_save_CFLAGS}" + fi + + # now check for the header. + if test "${AST_CODEC2_FOUND}" = "yes"; then + CODEC2_LIB="${pbxlibdir} -lcodec2 " + # if --with-CODEC2=DIR has been specified, use it. + if test "x${CODEC2_DIR}" != "x"; then + CODEC2_INCLUDE="-I${CODEC2_DIR}/include" + fi + CODEC2_INCLUDE="${CODEC2_INCLUDE} " + if test "xcodec2/codec2.h" = "x" ; then # no header, assume found + CODEC2_HEADER_FOUND="1" + else # check for the header + ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} ${CODEC2_INCLUDE}" + ac_fn_c_check_header_mongrel "$LINENO" "codec2/codec2.h" "ac_cv_header_codec2_codec2_h" "$ac_includes_default" +if test "x$ac_cv_header_codec2_codec2_h" = xyes; then : + CODEC2_HEADER_FOUND=1 +else + CODEC2_HEADER_FOUND=0 +fi + + + CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}" + fi + if test "x${CODEC2_HEADER_FOUND}" = "x0" ; then + CODEC2_LIB="" + CODEC2_INCLUDE="" + else + if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library + CODEC2_LIB="" + fi + PBX_CODEC2=1 + cat >>confdefs.h <<_ACEOF +#define HAVE_CODEC2 1 +_ACEOF + + fi + fi +fi + + + + if test "x${PBX_COROSYNC}" != "x1" -a "${USE_COROSYNC}" != "no"; then pbxlibdir="" # if --with-COROSYNC=DIR has been specified, use it. diff --git a/configure.ac b/configure.ac index ba13bf46d..950cfc5a1 100644 --- a/configure.ac +++ b/configure.ac @@ -407,6 +407,7 @@ AST_EXT_LIB_SETUP([BFD], [Debug symbol decoding], [bfd]) AST_EXT_LIB_SETUP([BKTR], [Stack Backtrace], [execinfo]) AST_EXT_LIB_SETUP([BLUETOOTH], [Bluetooth], [bluetooth]) AST_EXT_LIB_SETUP([CAP], [POSIX 1.e capabilities], [cap]) +AST_EXT_LIB_SETUP([CODEC2], [Codec 2 Audio Decoder/Encoder], [codec2]) AST_EXT_LIB_SETUP([COROSYNC], [Corosync], [cpg]) AST_EXT_LIB_SETUP_OPTIONAL([COROSYNC_CFG_STATE_TRACK], [A callback only in corosync 1.x], [COROSYNC], [cfg]) AST_EXT_LIB_SETUP([CURSES], [curses], [curses]) @@ -2341,6 +2342,8 @@ else AST_EXT_LIB_CHECK([RADIUS], [radiusclient-ng], [rc_read_config], [radiusclient-ng.h]) fi +AST_EXT_LIB_CHECK([CODEC2], [codec2], [codec2_create], [codec2/codec2.h]) + AST_EXT_LIB_CHECK([COROSYNC], [cpg], [cpg_join], [corosync/cpg.h], [-lcfg]) AST_EXT_LIB_CHECK([COROSYNC_CFG_STATE_TRACK], [cfg], [corosync_cfg_state_track], [corosync/cfg.h], [-lcfg]) diff --git a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py index 437386a67..4da31cb59 100755 --- a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py +++ b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py @@ -17,7 +17,7 @@ PREFIX = 'pjsip_' def section_by_type(section, pjsip, type): """Finds a section based upon the given type, adding it if not found.""" def __find_dict(mdicts, key, val): - """Given a list of mult-dicts, return the multi-dict that contains + """Given a list of multi-dicts, return the multi-dict that contains the given key/value pair.""" def found(d): @@ -1021,7 +1021,7 @@ class Registration: if self.outbound_proxy: set_value('outboundproxy', self.outbound_proxy, section, pjsip, - nmapped, 'registartion') + nmapped, 'registration') def map_registrations(sip, pjsip, nmapped): @@ -1182,7 +1182,7 @@ def cli_options(): """ global PREFIX usage = "usage: %prog [options] [input-file [output-file]]\n\n" \ - "Converts the chan_sip configuration input-file to the chan_pjsip output-file.\n"\ + "Converts the chan_sip configuration input-file to the chan_pjsip output-file.\n" \ "The input-file defaults to 'sip.conf'.\n" \ "The output-file defaults to 'pjsip.conf'." parser = optparse.OptionParser(usage=usage) diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h index 0472c1b37..28ae73e87 100644 --- a/include/asterisk/astobj2.h +++ b/include/asterisk/astobj2.h @@ -368,6 +368,13 @@ enum ao2_alloc_opts { AO2_ALLOC_OPT_LOCK_NOLOCK = (2 << 0), /*! The ao2 object locking option field mask. */ AO2_ALLOC_OPT_LOCK_MASK = (3 << 0), + /*! + * \internal The ao2 object uses a separate object for locking. + * + * \note This option is used internally by ao2_alloc_with_lockobj and + * should never be passed directly to ao2_alloc. + */ + AO2_ALLOC_OPT_LOCK_OBJ = AO2_ALLOC_OPT_LOCK_MASK, }; /*! @@ -408,6 +415,26 @@ void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned in /*! @} */ +/*! + * \since 14.1.0 + * \brief Allocate and initialize an object with separate locking. + * + * \param data_size The sizeof() of the user-defined structure. + * \param destructor_fn The destructor function (can be NULL) + * \param lockobj A separate ao2 object that will provide locking. + * \param debug_msg An ao2 object debug tracing message. + * \return A pointer to user-data. + * + * \see \ref ao2_alloc for additional details. + * + * \note lockobj must be a valid AO2 object. + */ +#define ao2_alloc_with_lockobj(data_size, destructor_fn, lockobj, tag) \ + __ao2_alloc_with_lockobj((data_size), (destructor_fn), (lockobj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) + +void *__ao2_alloc_with_lockobj(size_t data_size, ao2_destructor_fn destructor_fn, void *lockobj, + const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result; + /*! \brief * Reference/unreference an object and return the old refcount. * diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index bdd93bb64..f9a6b46e4 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -145,6 +145,9 @@ /* Define to 1 if you have the `closefrom' function. */ #undef HAVE_CLOSEFROM +/* Define to 1 if you have the Codec 2 Audio Decoder/Encoder library. */ +#undef HAVE_CODEC2 + /* Define to 1 if you have the Corosync library. */ #undef HAVE_COROSYNC diff --git a/include/asterisk/format_cache.h b/include/asterisk/format_cache.h index 3894ad21b..6099c59ea 100644 --- a/include/asterisk/format_cache.h +++ b/include/asterisk/format_cache.h @@ -209,6 +209,11 @@ extern struct ast_format *ast_format_siren7; extern struct ast_format *ast_format_opus; /*! + * \brief Built-in cached Codec 2 format. + */ +extern struct ast_format *ast_format_codec2; + +/*! * \brief Built-in cached t140 format. */ extern struct ast_format *ast_format_t140; diff --git a/include/asterisk/named_locks.h b/include/asterisk/named_locks.h index 0fe07d992..1959841d0 100644 --- a/include/asterisk/named_locks.h +++ b/include/asterisk/named_locks.h @@ -48,7 +48,7 @@ * To use a named lock: * Call ast_named_lock_get with the appropriate keyspace and key. * Use the standard ao2 lock/unlock functions as needed. - * Call ast_named_lock_put when you're finished with it. + * Call ao2_cleanup when you're finished with it. */ /*! @@ -66,9 +66,6 @@ struct ast_named_lock; struct ast_named_lock *__ast_named_lock_get(const char *filename, int lineno, const char *func, enum ast_named_lock_type lock_type, const char *keyspace, const char *key); -int __ast_named_lock_put(const char *filename, int lineno, const char *func, - struct ast_named_lock *lock); - /*! * \brief Geta named lock handle * \since 13.9.0 @@ -92,11 +89,8 @@ int __ast_named_lock_put(const char *filename, int lineno, const char *func, * \since 13.9.0 * * \param lock The pointer to the ast_named_lock structure returned by ast_named_lock_get - * \retval 0 Success - * \retval -1 Failure */ -#define ast_named_lock_put(lock) \ - __ast_named_lock_put(__FILE__, __LINE__, __PRETTY_FUNCTION__, lock) +#define ast_named_lock_put(lock) ao2_cleanup(lock) /*! * @} diff --git a/include/asterisk/sorcery.h b/include/asterisk/sorcery.h index 23219ec41..896633816 100644 --- a/include/asterisk/sorcery.h +++ b/include/asterisk/sorcery.h @@ -988,10 +988,30 @@ int ast_sorcery_changeset_create(const struct ast_variable *original, const stru * * \retval non-NULL success * \retval NULL failure + * + * \note The returned object does not support AO2 locking. */ void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor); /*! + * \since 14.1.0 + * \brief Allocate a generic sorcery capable object with locking. + * + * \details Sorcery objects may be replaced with new allocations during reloads. + * If locking is required on sorcery objects it must be shared between the old + * object and the new one. lockobj can be any AO2 object with locking enabled, + * but in most cases named locks should be used to provide stable locking. + * + * \param size Size of the object + * \param destructor Optional destructor function + * \param lockobj An AO2 object that will provide locking. + * + * \retval non-NULL success + * \retval NULL failure + */ +void *ast_sorcery_lockable_alloc(size_t size, ao2_destructor_fn destructor, void *lockobj); + +/*! * \brief Allocate an object * * \param sorcery Pointer to a sorcery structure diff --git a/main/astobj2.c b/main/astobj2.c index 5c92f263f..604e6a1ae 100644 --- a/main/astobj2.c +++ b/main/astobj2.c @@ -108,6 +108,17 @@ struct astobj2_rwlock { void *user_data[0]; }; +struct ao2_lockobj_priv { + void *lock; +}; + +/* AstObj2 with locking provided by a separate object. */ +struct astobj2_lockobj { + struct ao2_lockobj_priv lockobj; + struct __priv_data priv_data; + void *user_data[0]; +}; + #ifdef AO2_DEBUG struct ao2_stats ao2; #endif @@ -118,6 +129,9 @@ struct ao2_stats ao2; #define INTERNAL_OBJ_RWLOCK(user_data) \ ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock))) +#define INTERNAL_OBJ_LOCKOBJ(user_data) \ + ((struct astobj2_lockobj *) (((char *) (user_data)) - sizeof(struct astobj2_lockobj))) + #define INTERNAL_OBJ(user_data) \ (struct astobj2 *) ((char *) user_data - sizeof(struct astobj2)) @@ -187,6 +201,7 @@ int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, co struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func); struct astobj2_lock *obj_mutex; struct astobj2_rwlock *obj_rwlock; + struct astobj2_lockobj *obj_lockobj; int res = 0; if (obj == NULL) { @@ -231,6 +246,10 @@ int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, co case AO2_ALLOC_OPT_LOCK_NOLOCK: /* The ao2 object has no lock. */ break; + case AO2_ALLOC_OPT_LOCK_OBJ: + obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data); + res = __ao2_lock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var); + break; default: ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n", user_data); @@ -245,6 +264,7 @@ int __ao2_unlock(void *user_data, const char *file, const char *func, int line, struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func); struct astobj2_lock *obj_mutex; struct astobj2_rwlock *obj_rwlock; + struct astobj2_lockobj *obj_lockobj; int res = 0; int current_value; @@ -281,6 +301,10 @@ int __ao2_unlock(void *user_data, const char *file, const char *func, int line, case AO2_ALLOC_OPT_LOCK_NOLOCK: /* The ao2 object has no lock. */ break; + case AO2_ALLOC_OPT_LOCK_OBJ: + obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data); + res = __ao2_unlock(obj_lockobj->lockobj.lock, file, func, line, var); + break; default: ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n", user_data); @@ -295,6 +319,7 @@ int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func); struct astobj2_lock *obj_mutex; struct astobj2_rwlock *obj_rwlock; + struct astobj2_lockobj *obj_lockobj; int res = 0; if (obj == NULL) { @@ -339,6 +364,10 @@ int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, case AO2_ALLOC_OPT_LOCK_NOLOCK: /* The ao2 object has no lock. */ return 0; + case AO2_ALLOC_OPT_LOCK_OBJ: + obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data); + res = __ao2_trylock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var); + break; default: ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n", user_data); @@ -370,6 +399,7 @@ enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int { struct astobj2 *obj = INTERNAL_OBJ(user_data); struct astobj2_rwlock *obj_rwlock; + struct astobj2_lockobj *obj_lockobj; enum ao2_lock_req orig_lock; switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) { @@ -400,6 +430,10 @@ enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int break; } break; + case AO2_ALLOC_OPT_LOCK_OBJ: + obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data); + orig_lock = __adjust_lock(obj_lockobj->lockobj.lock, lock_how, keep_stronger); + break; default: ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data); /* Fall through */ @@ -441,6 +475,7 @@ int __ao2_ref(void *user_data, int delta, struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func); struct astobj2_lock *obj_mutex; struct astobj2_rwlock *obj_rwlock; + struct astobj2_lockobj *obj_lockobj; int current_value; int ret; void *weakproxy = NULL; @@ -552,6 +587,12 @@ int __ao2_ref(void *user_data, int delta, case AO2_ALLOC_OPT_LOCK_NOLOCK: ast_free(obj); break; + case AO2_ALLOC_OPT_LOCK_OBJ: + obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data); + ao2_t_ref(obj_lockobj->lockobj.lock, -1, "release lockobj"); + + ast_free(obj_lockobj); + break; default: ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n", user_data); @@ -581,13 +622,14 @@ void __ao2_cleanup(void *obj) } } -void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, - const char *tag, const char *file, int line, const char *func) +static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, + void *lockobj, const char *tag, const char *file, int line, const char *func) { /* allocation */ struct astobj2 *obj; struct astobj2_lock *obj_mutex; struct astobj2_rwlock *obj_rwlock; + struct astobj2_lockobj *obj_lockobj; switch (options & AO2_ALLOC_OPT_LOCK_MASK) { case AO2_ALLOC_OPT_LOCK_MUTEX: @@ -614,6 +656,22 @@ void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned in return NULL; } break; + case AO2_ALLOC_OPT_LOCK_OBJ: + lockobj = ao2_t_bump(lockobj, "set lockobj"); + if (!lockobj) { + ast_log(__LOG_ERROR, file, line, func, "AO2_ALLOC_OPT_LOCK_OBJ requires a non-NULL lockobj.\n"); + return NULL; + } + + obj_lockobj = __ast_calloc(1, sizeof(*obj_lockobj) + data_size, file, line, func); + if (obj_lockobj == NULL) { + ao2_t_ref(lockobj, -1, "release lockobj for failed alloc"); + return NULL; + } + + obj_lockobj->lockobj.lock = lockobj; + obj = (struct astobj2 *) &obj_lockobj->priv_data; + break; default: /* Invalid option value. */ ast_log(__LOG_DEBUG, file, line, func, "Invalid lock option requested\n"); @@ -643,6 +701,19 @@ void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned in return EXTERNAL_OBJ(obj); } +void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, + const char *tag, const char *file, int line, const char *func) +{ + return internal_ao2_alloc(data_size, destructor_fn, options, NULL, tag, file, line, func); +} + +void *__ao2_alloc_with_lockobj(size_t data_size, ao2_destructor_fn destructor_fn, void *lockobj, + const char *tag, const char *file, int line, const char *func) +{ + return internal_ao2_alloc(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_OBJ, lockobj, + tag, file, line, func); +} + unsigned int ao2_options_get(void *obj) { struct astobj2 *orig_obj; diff --git a/main/codec_builtin.c b/main/codec_builtin.c index 15147980d..facb5a84c 100644 --- a/main/codec_builtin.c +++ b/main/codec_builtin.c @@ -108,6 +108,30 @@ static struct ast_codec g723 = { .get_length = g723_length, }; +static int codec2_samples(struct ast_frame *frame) +{ + return 160 * (frame->datalen / 6); +} + +static int codec2_length(unsigned int samples) +{ + return (samples / 160) * 6; +} + +static struct ast_codec codec2 = { + .name = "codec2", + .description = "Codec 2", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + .minimum_ms = 20, + .maximum_ms = 300, + .default_ms = 20, + .minimum_bytes = 6, + .samples_count = codec2_samples, + .get_length = codec2_length, + .smooth = 1, +}; + static int none_samples(struct ast_frame *frame) { return frame->datalen; @@ -869,6 +893,7 @@ int ast_codec_builtin_init(void) { int res = 0; + res |= CODEC_REGISTER_AND_CACHE(codec2); res |= CODEC_REGISTER_AND_CACHE(g723); res |= CODEC_REGISTER_AND_CACHE(ulaw); res |= CODEC_REGISTER_AND_CACHE(alaw); diff --git a/main/format_cache.c b/main/format_cache.c index b4d426092..c704f1c37 100644 --- a/main/format_cache.c +++ b/main/format_cache.c @@ -218,6 +218,11 @@ struct ast_format *ast_format_siren7; struct ast_format *ast_format_opus; /*! + * \brief Built-in cached codec2 format. + */ +struct ast_format *ast_format_codec2; + +/*! * \brief Built-in cached t140 format. */ struct ast_format *ast_format_t140; @@ -328,6 +333,7 @@ static void format_cache_shutdown(void) ao2_replace(ast_format_testlaw, NULL); ao2_replace(ast_format_g719, NULL); ao2_replace(ast_format_opus, NULL); + ao2_replace(ast_format_codec2, NULL); ao2_replace(ast_format_jpeg, NULL); ao2_replace(ast_format_png, NULL); ao2_replace(ast_format_h261, NULL); @@ -360,7 +366,9 @@ int ast_format_cache_init(void) static void set_cached_format(const char *name, struct ast_format *format) { - if (!strcmp(name, "g723")) { + if (!strcmp(name, "codec2")) { + ao2_replace(ast_format_codec2, format); + } else if (!strcmp(name, "g723")) { ao2_replace(ast_format_g723, format); } else if (!strcmp(name, "ulaw")) { ao2_replace(ast_format_ulaw, format); diff --git a/main/format_cap.c b/main/format_cap.c index 2b3e6cd5f..013b7bea1 100644 --- a/main/format_cap.c +++ b/main/format_cap.c @@ -703,7 +703,7 @@ const char *ast_format_cap_get_names(struct ast_format_cap *cap, struct ast_str ast_str_set(buf, 0, "("); - if (!AST_VECTOR_SIZE(&cap->preference_order)) { + if (!cap || !AST_VECTOR_SIZE(&cap->preference_order)) { ast_str_append(buf, 0, "nothing)"); return ast_str_buffer(*buf); } diff --git a/main/named_locks.c b/main/named_locks.c index 596048388..c71f3b579 100644 --- a/main/named_locks.c +++ b/main/named_locks.c @@ -35,13 +35,17 @@ ASTERISK_REGISTER_FILE() struct ao2_container *named_locks; #define NAMED_LOCKS_BUCKETS 101 -struct ast_named_lock { +struct named_lock_proxy { + AO2_WEAKPROXY(); char key[0]; }; +struct ast_named_lock { +}; + static int named_locks_hash(const void *obj, const int flags) { - const struct ast_named_lock *lock = obj; + const struct named_lock_proxy *lock = obj; switch (flags & OBJ_SEARCH_MASK) { case OBJ_SEARCH_KEY: @@ -57,8 +61,8 @@ static int named_locks_hash(const void *obj, const int flags) static int named_locks_cmp(void *obj_left, void *obj_right, int flags) { - const struct ast_named_lock *object_left = obj_left; - const struct ast_named_lock *object_right = obj_right; + const struct named_lock_proxy *object_left = obj_left; + const struct named_lock_proxy *object_right = obj_right; const char *right_key = obj_right; int cmp; @@ -98,45 +102,72 @@ int ast_named_locks_init(void) return 0; } +static void named_lock_proxy_cb(void *weakproxy, void *data) +{ + ao2_unlink(named_locks, weakproxy); +} + struct ast_named_lock *__ast_named_lock_get(const char *filename, int lineno, const char *func, enum ast_named_lock_type lock_type, const char *keyspace, const char *key) { + struct named_lock_proxy *proxy = NULL; struct ast_named_lock *lock = NULL; - int concat_key_buff_len = strlen(keyspace) + strlen(key) + 2; - char *concat_key = ast_alloca(concat_key_buff_len); + int keylen = strlen(keyspace) + strlen(key) + 2; + char *concat_key = ast_alloca(keylen); sprintf(concat_key, "%s-%s", keyspace, key); /* Safe */ ao2_lock(named_locks); - lock = ao2_find(named_locks, concat_key, OBJ_SEARCH_KEY | OBJ_NOLOCK); - if (lock) { + proxy = ao2_find(named_locks, concat_key, OBJ_SEARCH_KEY | OBJ_NOLOCK); + if (proxy) { ao2_unlock(named_locks); - ast_assert((ao2_options_get(lock) & AO2_ALLOC_OPT_LOCK_MASK) == lock_type); - return lock; - } + lock = __ao2_weakproxy_get_object(proxy, 0, __PRETTY_FUNCTION__, filename, lineno, func); + + if (lock) { + /* We have an existing lock and it's not being destroyed. */ + ao2_ref(proxy, -1); + ast_assert((ao2_options_get(lock) & AO2_ALLOC_OPT_LOCK_MASK) == lock_type); + + return lock; + } - lock = ao2_alloc_options(sizeof(*lock) + concat_key_buff_len, NULL, lock_type); - if (lock) { - strcpy(lock->key, concat_key); /* Safe */ - ao2_link_flags(named_locks, lock, OBJ_NOLOCK); + /* the old proxy is being destroyed, clean list before creating/adding new one */ + ao2_lock(named_locks); + ao2_unlink_flags(named_locks, proxy, OBJ_NOLOCK); + ao2_ref(proxy, -1); } - ao2_unlock(named_locks); - return lock; -} + proxy = ao2_t_weakproxy_alloc(sizeof(*proxy) + keylen, NULL, concat_key); + if (!proxy) { + goto failure_cleanup; + } -int __ast_named_lock_put(const char *filename, int lineno, const char *func, - struct ast_named_lock *lock) -{ + lock = __ao2_alloc(sizeof(*lock) + keylen, NULL, lock_type, concat_key, filename, lineno, func); if (!lock) { - return -1; + goto failure_cleanup; } - ao2_lock(named_locks); - if (ao2_ref(lock, -1) == 2) { - ao2_unlink_flags(named_locks, lock, OBJ_NOLOCK); + /* We have exclusive access to proxy and lock, no need for locking here. */ + if (ao2_weakproxy_set_object(proxy, lock, OBJ_NOLOCK)) { + goto failure_cleanup; } + + if (ao2_weakproxy_subscribe(proxy, named_lock_proxy_cb, NULL, OBJ_NOLOCK)) { + goto failure_cleanup; + } + + strcpy(proxy->key, concat_key); /* Safe */ + ao2_link_flags(named_locks, proxy, OBJ_NOLOCK); ao2_unlock(named_locks); + ao2_t_ref(proxy, -1, "Release allocation reference"); - return 0; + return lock; + +failure_cleanup: + ao2_unlock(named_locks); + + ao2_cleanup(proxy); + ao2_cleanup(lock); + + return NULL; } diff --git a/main/sorcery.c b/main/sorcery.c index 55ee830b7..9f8c35c3b 100644 --- a/main/sorcery.c +++ b/main/sorcery.c @@ -1736,9 +1736,26 @@ static void sorcery_object_destructor(void *object) ast_free(details->object->id); } +void *ast_sorcery_lockable_alloc(size_t size, ao2_destructor_fn destructor, void *lockobj) +{ + void *object = ao2_alloc_with_lockobj(size + sizeof(struct ast_sorcery_object), + sorcery_object_destructor, lockobj, ""); + struct ast_sorcery_object_details *details = object; + + if (!object) { + return NULL; + } + + details->object = object + size; + details->object->destructor = destructor; + + return object; +} + void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor) { - void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object), sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK); + void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object), + sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK); struct ast_sorcery_object_details *details = object; if (!object) { diff --git a/makeopts.in b/makeopts.in index d4347daf1..f0b0d0ef5 100644 --- a/makeopts.in +++ b/makeopts.in @@ -126,6 +126,9 @@ BFD_LIB=@BFD_LIB@ BLUETOOTH_INCLUDE=@BLUETOOTH_INCLUDE@ BLUETOOTH_LIB=@BLUETOOTH_LIB@ +CODEC2_INCLUDE=@CODEC2_INCLUDE@ +CODEC2_LIB=@CODEC2_LIB@ + CURL_INCLUDE=@CURL_INCLUDE@ CURL_LIB=@CURL_LIB@ diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c index 0ab69ec5b..5abfcabad 100644 --- a/res/res_pjsip/location.c +++ b/res/res_pjsip/location.c @@ -49,11 +49,22 @@ static void aor_destroy(void *obj) /*! \brief Allocator for AOR */ static void *aor_alloc(const char *name) { - struct ast_sip_aor *aor = ast_sorcery_generic_alloc(sizeof(struct ast_sip_aor), aor_destroy); + void *lock; + struct ast_sip_aor *aor; + + lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", name); + if (!lock) { + return NULL; + } + + aor = ast_sorcery_lockable_alloc(sizeof(struct ast_sip_aor), aor_destroy, lock); + ao2_ref(lock, -1); + if (!aor) { return NULL; } ast_string_field_init(aor, 128); + return aor; } @@ -206,17 +217,11 @@ struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor) { struct ao2_container *contacts; - struct ast_named_lock *lock; - lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", ast_sorcery_object_get_id(aor)); - if (!lock) { - return NULL; - } - - ao2_lock(lock); + /* ao2_lock / ao2_unlock do not actually write aor since it has an ao2 lockobj. */ + ao2_lock((void*)aor); contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor); - ao2_unlock(lock); - ast_named_lock_put(lock); + ao2_unlock((void*)aor); return contacts; } @@ -369,19 +374,12 @@ int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struct ast_sip_endpoint *endpoint) { int res; - struct ast_named_lock *lock; - - lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", ast_sorcery_object_get_id(aor)); - if (!lock) { - return -1; - } - ao2_lock(lock); + ao2_lock(aor); res = ast_sip_location_add_contact_nolock(aor, uri, expiration_time, path_info, user_agent, via_addr, via_port, call_id, endpoint); - ao2_unlock(lock); - ast_named_lock_put(lock); + ao2_unlock(aor); return res; } diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c index f99a3b84d..47d5991e4 100644 --- a/res/res_pjsip_registrar.c +++ b/res/res_pjsip_registrar.c @@ -523,25 +523,17 @@ static int register_aor(pjsip_rx_data *rdata, { int res; struct ao2_container *contacts = NULL; - struct ast_named_lock *lock; - lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", aor_name); - if (!lock) { - return PJ_TRUE; - } - - ao2_lock(lock); + ao2_lock(aor); contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor); if (!contacts) { - ao2_unlock(lock); - ast_named_lock_put(lock); + ao2_unlock(aor); return PJ_TRUE; } res = register_aor_core(rdata, endpoint, aor, aor_name, contacts); ao2_cleanup(contacts); - ao2_unlock(lock); - ast_named_lock_put(lock); + ao2_unlock(aor); return res; } |